En lenguaje ensamblador, el término addressing mode
no significa tomar la dirección de una variable; sino más bien cómo se codifica la información en el código de instrucción. Por ejemplo, el código de instrucción 0xE8 0x4D es la instrucción mov A,0x4D
que usa el modo de direccionamiento directo: acc A obtiene el contenido de la dirección iram 0x4D. Pero el código de instrucción 0x74 0x4D es mov A,#0x4D
: acc A obtiene el valor literal real 0x4D. Ambas instrucciones tienen la misma longitud y utilizan una codificación similar, pero el significado de 0x4D depende del modo de direccionamiento que se usó.
Incluso si define un símbolo LetterM equ 0x4D
, esto no hace ninguna diferencia en los ensamblajes 8051 - mov A,LetterM
como 0xE8 0x4D y mov A,#LetterM
ensambla como 0x74 0x4D. El 8051 en sí nunca ve el código fuente del ensamblaje, solo el código objeto. Por lo tanto, la única razón por la que la puntuación como #
o @
es importante es garantizar que el ensamblador utilice el modo de direccionamiento correcto para codificar cada instrucción.
Para cargar el registro de puntero de datos de 16 bits, mov dptr,#data16
solo admite immediate addressing mode
. Por lo general, desea usar dptr para apuntar a la dirección de memoria de un objeto, de modo que el modo de direccionamiento inmediato es lo que necesita. Para su pregunta, mov dptr,#Z
considera que mov dptr,#data16
es el modo de direccionamiento inmediato y Z
como la dirección del símbolo Z, que está utilizando para almacenar una variable.
Si ya entiende los punteros del lenguaje C, el registro dptr es un puntero a un valor de 8 bits en la memoria, y la instrucción movc A, @A+DPTR
es lo que quita el valor del puntero que está en el registro dptr. Entonces, dptr siempre obtiene la dirección donde vive la variable, y el modo de direccionamiento indirecto (@) usa el valor actualmente en dptr para obtener el valor al que apunta dptr.
// some C pseudocode to help explain 8051
uint8* dptr_register; // 8051 built-in DPTR register
uint8 acc_a; // 8051 built-in accumulator register A
static uint8 myVarZ = 123; // myVarZ: db 123
dptr_register = &myVarZ; // mov dptr,#myVarZ ; address of myVarZ
acc_a = *dptr_register; // movc A,@A+DPTR (assuming A is 0) ; get value of myVarZ
Sin embargo, el 8051 es un poco más complicado porque tiene más de un espacio de direcciones. La dirección de código 0 es diferente de la dirección de RAM interna 0, que también es diferente de la dirección de RAM externa 0. Por eso hay varias instrucciones diferentes que usan dptr ('movc', 'mov', 'movx'). Los compiladores de C real para 8051 (como Keil C51 o SDCC) tienen algunas palabras clave adicionales no estándar para distinguir entre estos diferentes espacios de direcciones.
Otros microcontroladores tienen conjuntos de instrucciones ligeramente diferentes y usan puntuaciones ligeramente diferentes, pero todos son lo suficientemente similares a uno que aprendes uno, puedes recoger fácilmente los otros.