2011-11-04 57 views

Respuesta

26

La primera es equate, similar a C de:

#define len 2 

, ya que en realidad no asigna ningún espacio en el código final, simplemente se establece el símbolo len ser igual a 2. Luego, cuando usted usa len más adelante en su código fuente, es lo mismo que si está usando la constante 2.

El segundo es define byte, similar a C de:

int len = 2; 

Se no realidad asignar el espacio, un byte en la memoria, almacena una 2 allí, y establece len a ser la dirección de ese byte .

Aquí hay un código pseudo-ensamblador que muestra la distinción:

line addr code  label instruction 
---- ---- -------- ----- ----------- 
    1 0000      org 1234 
    2 1234    elen equ 2 
    3 1234 02   dlen db  2 
    4 1235 44 02 00   mov ax  elen 
    5 1238 44 34 12   mov ax  dlen 

Línea 1 se limita a establecer la dirección de la Asamblea a ser 1234, para que sea más fácil de explicar lo que está pasando.

En la línea 2, no se genera código, el ensamblador simplemente carga elen en la tabla de símbolos con el valor 2. Como no se ha generado ningún código, la dirección no cambia.

Luego, cuando lo usa en la línea 4, carga ese valor en el registro.

La línea 3 muestra que db es diferente, en realidad asigna un espacio (un byte) y almacena el valor en ese espacio. Luego carga dlen en la tabla de símbolos pero le da el valor de esa dirección 1234 en lugar del valor constante 2.

Cuando más tarde usa dlen en la línea 5, obtiene la dirección, que tendría que eliminar para obtener el valor real 2.

+2

NASM 2.10.09 OBJETOS de salida ELF: 1) "no se generan datos": verdadero para el ejecutable después del enlace y espacio RAM, pero el archivo objeto que NASM genera contiene los datos del símbolo. 2) "similar a C's #define": en cierto sentido, pero 'equ' genera un símbolo, que podría ser utilizado por otros archivos de objetos con' extern' y sin incluir la macro en esos archivos. Más detalles: http://stackoverflow.com/a/33148242/895245 –

+0

Buenos puntos, @Ciro, pensé que el significado era obvio desde el contexto pero, para estar seguro, he cambiado los datos al código para garantizar la claridad. En cuanto al '# define', la similitud no es necesariamente la igualdad, pero intentaré aclarar eso también :-) – paxdiablo

1

Resumen

NASM salida 2.10.09 ELF:

  • db no tiene ningún efectos mágicos: simplemente da salida bytes directamente en el fichero objeto de salida.

    Si esos bytes están delante de un símbolo, el símbolo apuntará a ese valor cuando se inicie el programa.

    Si se encuentra en la sección de texto, sus bytes se ejecutarán.

    Tiempo que usa db o dw, etc.eso no especifica el tamaño del símbolo: el campo st_size de la entrada de la tabla de símbolos no se ve afectado.

  • equ hace que el símbolo en la línea actual tenga st_shndx == SHN_ABS valor mágico en su entrada de tabla de símbolos.

    En lugar de enviar un byte a la ubicación del archivo de objeto actual, lo envía al campo st_value de la entrada de la tabla de símbolos.

Todo lo demás se deduce de esto.

Para entender lo que realmente significa, primero debe comprender the basics of the ELF standard y .

teoría SHN_ABS

SHN_ABS le indica al enlazador que:

  • reubicación no debe ser hecho en este símbolo
  • el campo de la introducción de símbolos st_value es para ser utilizado como un valor directamente

Contraste esto con símbolos "regulares", en el que el v Al contrario, el símbolo del símbolo es una dirección de memoria y, por lo tanto, debe pasar por la reubicación.

Dado que no apunta a la memoria, el enlazador puede eliminar efectivamente los símbolos SHN_ABS del enlazador al delimitarlos.

Pero todavía son símbolos regulares en los archivos de objeto y do ocupan la memoria allí, y podrían compartirse entre varios archivos si es global.

Ejemplo de uso

section .data 
    x: equ 1 
    y: db 2 
section .text 
global _start 
_start: 
    mov al, x 
    ; al == 1 
    mov al, [y] 
    ; al == 2 

Tenga en cuenta que dado que el símbolo x contiene un valor literal, sin eliminar la referencia [] debe hacerse para ella como para y.

Si se quiere utilizar x de un programa en C, que íbamos a necesitar algo como:

extern char x; 
printf("%d", &x); 

y ajustar en las asm:

global x 

La observación empírica de salida generada

Podemos observar lo que hemos dicho antes con:

nasm -felf32 -o equ.o equ.asm 
ld -melf_i386 -o equ equ.o 

Ahora:

readelf -s equ.o 

contiene:

Num: Value Size Type Bind Vis  Ndx Name 
    4: 00000001  0 NOTYPE LOCAL DEFAULT ABS x 
    5: 00000000  0 NOTYPE LOCAL DEFAULT 1 y 

Ndx es st_shndx, por lo que vemos que es xSHN_ABS mientras que no es y.

ver también que Size es 0 para y: db de ninguna manera y dijo que se trataba de un solo byte de ancho. Simplemente podríamos agregar dos directivas db para asignar 2 bytes allí.

Y luego:

objdump -dr equ 

da:

08048080 <_start>: 
8048080:  b0 01     mov $0x1,%al 
8048082:  a0 88 90 04 08   mov 0x8049088,%al 

Y vemos que se 0x1 entre líneas en la instrucción, mientras que y tiene el valor de una dirección de reubicación 0x8049088.

Probado en Ubuntu 14.04 AMD64.

Docs

http://www.nasm.us/doc/nasmdoc3.html#section-3.2.4:

EQU define un símbolo a un valor constante dado: cuando EQU se utiliza, la línea de fuente debe contener una etiqueta. La acción de EQU es definir el nombre de etiqueta dado al valor de su (único) operando. Esta definición es absoluta, y no puede cambiar más tarde. Así, por ejemplo,

message   db  'hello, world' 
msglen   equ  $-message 

define msglen para ser la constante de 12. msglen no puede entonces ser redefinido más tarde. Esta tampoco es una definición de preprocesador: el valor de msglen se evalúa una vez, usando el valor de $ (ver sección 3.5 para una explicación de $) en el punto de definición, en lugar de ser evaluado donde sea que se haga referencia y usando el valor de $ en el punto de referencia.

Ver también

pregunta análoga para GAS: Difference between .equ and .word in ARM Assembly?.equiv parece ser el equivalente cierra GAS.

0

equ: preprocessor time. análoga a #define, pero la mayoría de los ensambladores carecen de #undef y no pueden tener nada más que una constante atómica de número fijo de bytes en el lado derecho, por lo que las flotantes, dobles y listas no son compatibles con la directiva equ de la mayoría de los ensambladores.

db: tiempo de compilación. el valor almacenado en db es almacenado en la salida binaria por el ensamblador en un desplazamiento específico. equ le permite definir constantes que normalmente necesitarían estar codificadas, o requerir una operación mov para obtenerlas. db le permite tener datos disponibles en la memoria incluso antes de que el programa comience.

Aquí es una base de datos nasm demostrando:

; I am a 16 byte object at offset 0. 
    db '----------------' 

; I am a 14 byte object at offset 16 
; the label foo makes the assembler remember the current 'tell' of the 
; binary being written. 
foo: 
    db 'Hello, World!', 0 

; I am a 2 byte filler at offset 30 to help readability in hex editor. 
    db ' .' 

; I am a 4 byte object at offset 16 that the offset of foo, which is 16(0x10). 
    dd foo 

enter image description here

Una ecuación sólo puede definir una constante hasta el más grande el ensamblador apoya

ejemplo de la ecuación, junto con algunas limitaciones comunes de eso

; OK 
ZERO equ 0 

; OK(some assemblers won't recognize \r and will need to look up the ascii table to get the value of it). 
CR equ 0xD 
; OK(some assemblers won't recognize \n and will need to look up the ascii table to get the value of it). 
LF equ 0xA 

; error: bar.asm:2: warning: numeric constant 102919291299129192919293122 - 
; does not fit in 64 bits 
; LARGE_INTEGER equ 102919291299129192919293122 

; bar.asm:5: error: expression syntax error 
; assemblers often don't support float constants, despite fitting in 
; reasonable number of bytes. This is one of the many things 
; we take for granted in C, ability to precompile floats at compile time 
; without the need to create your own assembly preprocessor/assembler. 
; PI equ 3.1415926 

; bar.asm:14: error: bad syntax for EQU 
; assemblers often don't support list constants, this is something C 
; does support using define, allowing you to define a macro that 
; can be passed as a single argument to a function that takes multiple. 
; eg 
; #define RED 0xff, 0x00, 0x00, 0x00 
; glVertex4f(RED); 
; #undef RED 
;RED equ 0xff, 0x00, 0x00, 0x00 

el binario resultante no tiene bytes en absoluto porque equ no contamina la imagen; todas las referencias a una equ se reemplazan por el lado derecho de esa equ.

Cuestiones relacionadas