Escribir un bucle while en ensamblaje

Estoy tratando de escribir un bucle while en ensamblaje con un procesador 6502 y no puedo averiguar cómo escribir el código hexadecimal. He visto ejemplos escritos usando la abreviatura donde hay una etiqueta para dónde debe comenzar y terminar el ciclo, pero no veo nada para el código hexadecimal real.

Los dos códigos que veo que son útiles son:

  1. Comparación de un byte en la memoria con el registro X (abreviatura: CPX, hex: EC). Esto establece la bandera Z en cero si es igual y
  2. Bifurcar X bytes si el indicador Z = 0 (abreviatura: BNE, hexadecimal: D0)

preguntado el 16 de mayo de 11 a las 17:05

¿Por qué quiere códigos hexadecimales en lugar de utilizar un ensamblador? -

@jnhyf "Código hexadecimal"? ¿Qué IDE, ensamblador o compilador estás usando? ¿Qué experiencia tiene con el montaje 6502? -

Espero que no nos esté diciendo que está escribiendo un programa 6502 sin usar un ensamblador. ¿Qué estás usando para un sistema de desarrollo? Una manzana ][ ? ¿O que? -

Intentando escribir un compilador que genere código hexadecimal para que pueda ejecutarse en un microprocesador 6502 simulado. -

Puede estar usando un entrenador de microprocesador (p. Ej. innovision-group.net/catalog/images/…). Estas son computadoras simples que programa directamente en código de máquina. Aún puede usar un ensamblador para generar el código de máquina, pero aún debe ingresar manualmente el código de máquina en el sistema. -

4 Respuestas

Aquí tienes un lugar para empezar. La página presenta un ensamblador cruzado que puede ejecutar en su PC. Que podría ser una buena plataforma de desarrollo para ti.

Antes de hacer nada, debe comprender la teoría de funcionamiento del 6502. Luego, debe comprender el proceso de desarrollo de software que incluye:

- preparar un "archivo fuente", así llamado, de instrucciones simbólicas que usted llama "taquigrafía"
- usando un ensamblador, traduciendo ese archivo fuente en instrucciones de máquina que el 6502 entiende
- cargando la traducción en el 6502
- decirle al 6502 que ejecute las instrucciones traducidas de la máquina

Su programa de ejemplo intenta copiar LEN bytes de memoria de SRC a DST.

Lo formatea así:

      LDX #0    ; Start with the first byte 
_LOOP LDA SRC,X ; load a byte from SRC into the A register 
      STA DST,X ; store that byte into DST
      INX       ; bump the index register to point to the next SRC and DST locations 
      CPX #LEN  ; have we moved LEN characters?  
      BNE _LOOP ; if not, go move the next one

Después de haber agregado más líneas de declaración (como END, por ejemplo); y después de haber definido SRC, DST, LEN, lo guarda todo en un archivo llamado, digamos, cploop.txt.

Luego le dice al ensamblador que lo traduzca. El ensamblador sale con un archivo de código de máquina binario 6502 que se puede representar como los bytes hexadecimales de los que está hablando.

Usted alimenta ese archivo de código de máquina al 6502 simulado. Luego, de alguna manera, le dice al 6502 que ejecute las operaciones que incorpora el código de máquina.

Respondido 23 Jul 20, 12:07

Gracias, eso ayuda, pero todavía no tengo claro cómo algo como este ejemplo de ese sitio web: "LDX # 0; Comience con el primer byte _LOOP LDA SRC, X; Muévalo STA DST, X INX; Luego suba el índice ... CPX #LEN; ... hasta que alcancemos el límite BNE _LOOP "se puede representar en hexadecimal. La etiqueta _loop es importante en la taquigrafía allí, pero no veo cómo tener algo así en el código de máquina real. Lo siento, no tengo idea de cómo formatear ese código. - jnhyf

@jnhyf Tú verdaderamente Necesito dividir su problema en "cómo puedo escribir este código en código de máquina 6502" y "cómo puedo convertir ese código a notación hexadecimal". Tal como está, es difícil ayudarlo. - bzlm

@jnhyf - Hay dos pasos: (1) escribe tu programa en lenguaje ensamblador, lo que llamas "taquigrafía" (un término que nunca escuché, por cierto); (2) entregue ese archivo de lenguaje ensamblador al ensamblador, que luego escupe los códigos hexadecimales que desee. - Pete Wilson

Por cierto, los bucles decrementales son más eficientes: omiten la necesidad de la instrucción de comparación y, además de guardar esos dos bytes, también son entre 2 y 6 relojes más rápidos por iteración (según el modo de comparación y direccionamiento): LDX #LEN; Empiece con el último byte _LOOP LDA SRC, X; cargar un byte de SRC en el registro A STA DST, X; almacenar ese byte en DST DEX; golpee el registro de índice para apuntar a las siguientes ubicaciones SRC y DST BNE _LOOP; si no es cero, ve a mover el siguiente - Gurú de ocho bits

@jnhyf - una cosa en la que parece estar atascado es la existencia de la etiqueta "_LOOP" en el código ensamblador. Esta es solo una directiva de ensamblador que representa la dirección en la ubicación en la que comienza la instrucción. No está ensamblado en nada en el código de máquina que se genera en el punto en el que se define. Cuando se usa como parte de un operando (es decir, los argumentos de las instrucciones de ensamblaje), se reemplaza con la dirección de la instrucción en la que se encuentra cuando se define. En el 6502 se escribe primero el byte menos significativo - la dirección $ 0300 se escribe "00 03" en el código de máquina. - Rob Heiser

Aquí hay un ejemplo que muestra la correspondencia entre ensamblado (lo que llama "taquigrafía") y código de máquina. Primero, aquí está el código ensamblador para el algoritmo, con algunos parámetros resumidos:

* = 4000          ; This is the address where our program will be stored

      LDX #len
loop  LDA src,X 
      STA dest,X 
      DEX       
      BNE loop

Por supuesto, no puede convertir eso directamente en código de máquina. También debe completar los valores de len, src y dest:

src = $1234
dest = $5678
len = 10

Lo que hay que entender sobre el loop el nombre es así como src se le asigna el valor $1234, loop se le asignará la dirección de la instrucción que sigue. Entonces, en este caso, dado que LDX #len ocupa 2 bytes (como te mostraré en breve), loop se establece a $4000 + 2 = $4002. El ensamblador lo hace automáticamente, pero, por supuesto, también puede hacerlo en papel.

Entonces, ¿cuál es el código de máquina 6502 para el programa de ensamblaje anterior?

A2 0A
BD 34 12
9D 78 56
CA
D0 F7

¿Cómo sé esto? Bueno, acabo de pegar el programa anterior en el ensamblador 6502 en línea en http://www.masswerk.at/6502/assembler.html. Incluso le muestra el mapeo detallado entre el ensamblaje y el código de máquina:

4000        LDX #LEN        A2 0A
4002 LOOP   LDA SRC,X       BD 34 12
4005        STA DEST,X      9D 78 56
4008        DEX             CA
4009        BNE LOOP        D0 F7
400B

Tenga en cuenta cómo el valor real de LOOP ni siquiera se utiliza para calcular el código de máquina para BNE LOOP, solo su dirección relativa en comparación con el BNE instrucción en sí: F7 es -9, y la diferencia entre $400B y $4002 es -9!

Entonces, si tuviera que hacer esto a mano, simplemente traduciría todo lo demás en código de máquina, luego, cuando llega a un salto, calcula la diferencia entre la dirección de inicio de la siguiente instrucción y la dirección del destino del salto. Debe ser negativo para los saltos hacia atrás y positivo para los saltos hacia adelante.

Respondido el 13 de junio de 14 a las 07:06

Las instrucciones de bifurcación toman un operando de dirección relativa con signo de un solo byte, que se agrega a la dirección de la siguiente instrucción para producir el destino de la bifurcación. Dado que la instrucción de bifurcación siempre ocupa 2 bytes, la dirección de destino es la dirección de la instrucción de bifurcación más el operando (con signo extendido) menos 2.

Ejemplos:
$D0 $00: no-op: la rama pasa a la siguiente instrucción independientemente de la condición
$D0 $FE: la rama apunta hacia sí misma, creando un bucle infinito si Z=0.

Respondido 18 ago 13, 22:08

Voto a favor por decodificar y responder la pregunta mal redactada. ; -) - Nick Westgate

A while declaración realmente significa:

  1. probar una condición
  2. si la condición es falsa, vaya a 5
  3. hacer algo
  4. volver a 1 (un JMP simple o una rama)
  5. resto del programa

Con 6502, nada de esto será extremadamente simple a menos que pueda hacer muchas suposiciones. Si la condición que está probando siempre será un registro, las instrucciones de comparación (cmp, cpx, cpy) y las instrucciones de bifurcación son obviamente lo que necesita para 1.

Si va a ser un solo byte almacenado en la memoria, entonces necesita cargar ese byte y luego compararlo.

Si se trata de un valor de 16 bits almacenado en dos bytes, debe cargar y probar cada valor del byte.

¿Tratando de flotadores? Si ha escrito o tiene disponible un paquete de punto flotante (como las rutinas de punto flotante de Commodore 64 ROM BASIC) necesitará usarlos.

Puede ver por qué los lenguajes de alto nivel tienen tipos de datos.

Entonces, realmente, depende del tipo de datos con los que esté tratando, pero cualquier implementación de while en 6502 debería seguir prácticamente lo anterior.

El caso específico que identifica en su pregunta está bien si sabe que los datos que comparará siempre estarán en X y que su destino siempre estará a + 127 / -128 bytes de distancia (límite de rango de las instrucciones Bxx).

Respondido 18 ago 13, 18:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.