NASM中equ和db之间有什么区别?

时间:2011-11-04 08:41:59

标签: nasm

len:  equ  2
len:  db   2

它们是否相同,产生的标签可以代替2使用?如果没有,那么每份申报表的优缺点是什么?它们可以互换使用吗?

3 个答案:

答案 0 :(得分:32)

第一个是equate,类似于C:

#define len 2

因为它实际上并没有在最终代码中分配任何空格,它只是将len符号设置为等于2.然后,当您在源代码中使用len时,就像你使用常量2一样。

第二个是define byte,类似于C:

int len = 2;

实际分配空间,内存中的一个字节,在那里存储2,并将len设置为地址字节。

这里有一些psuedo-assembler代码显示了区别:

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

第1行只是将汇编地址设置为1234,以便更容易解释发生了什么。

在第2行中,没有生成代码,汇编器只需将elen加载到符号表中,其值为2。由于没有生成代码,因此地址不会改变。

然后,当您在第4行使用它时,它会将该值加载到寄存器中。

第3行显示db不同,它实际上分配了一些空间(一个字节)并将值存储在该空间中。然后,它会将dlen加载到符号表中,但会为其提供该地址1234的值,而不是常量值2

如果您稍后在第5行使用dlen,则会获得地址,您必须取消引用该地址才能获得实际值2

答案 1 :(得分:1)

<强>摘要

NASM 2.10.09 ELF输出:

  • db没有任何魔法效果:它只是将字节直接输出到输出目标文件。

    如果这些字节恰好位于符号前面,则符号将在程序启动时指向该值。

    如果您在文本部分,您的字节将被执行。

    您使用dbdw等未指定符号大小的天气:符号表条目的st_size字段不受影响。

  • equ使当前行中的符号在其符号表条目中具有st_shndx == SHN_ABS魔术值。

    不是将字节输出到当前对象文件位置,而是将其输出到符号表条目的st_value字段。

其他所有内容都来自此。

要了解其真正含义,首先应了解the basics of the ELF standardrelocation

SHN_ABS理论

SHN_ABS告诉链接器:

  • 不对此符号进行重定位
  • 符号条目的st_value字段将直接用作值

将此与#34;常规&#34;进行对比。符号,其中符号的值是内存地址,因此必须通过重定位。

由于它没有指向内存,因此链接器可以通过内联来有效地从可执行文件中删除SHN_ABS个符号。

但它们仍然是目标文件上的常规符号,占用内存,如果是全局的话,可以在多个文件之间共享。

示例用法

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

请注意,由于符号x包含文字值,因此不必像[]那样对其进行解除引用y

如果我们想要使用C程序中的x,我们需要以下内容:

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

并设置为asm:

global x

生成输出的经验观察

我们可以观察我们之前说过的话:

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

现在:

readelf -s equ.o

包含:

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

Ndxst_shndx,因此我们发现xSHN_ABS,而y则不是。{/ p>

另请注意Size 0 y dby绝不告诉db它是单字节宽。我们可以简单地添加两个objdump -dr equ 指令来在那里分配2个字节。

然后:

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

给出:

0x1

因此,我们看到y被内联到指令中,而0x8049088获得了重定位地址message db 'hello, world' msglen equ $-message 的值。

在Ubuntu 14.04 AMD64上测试。

<强>文档

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

  

EQU定义给定常数值的符号:当使用EQU时,源代码行必须包含标签。 EQU的作用是将给定的标签名称定义为其(仅)操作数的值。这个定义是绝对的,以后不能改变。所以,例如,

.equiv
  

将msglen定义为常量12.稍后可能不会重新定义msglen。这也不是预处理器定义:msglen的值被评估一次,在定义点使用$的值(参见第3.5节有关$的解释),而不是在被引用的任何地方进行求值并使用值$在参考点。

另见

GAS的类似问题:Difference between .equ and .word in ARM Assembly? {{1}}似乎是关闭GAS的等价物。

答案 2 :(得分:1)

equ :预处理器时间。类似于#define,但是大多数汇编程序缺少#undef,并且除了右侧的固定字节数的原子常量之外不能有任何东西,所以大多数汇编程序的equ指令都不支持浮点数,双精度数,列表。

db :编译时间。存储在db中的值由汇编程序在特定偏移量处存储在二进制输出中。 equ允许您定义通常需要硬编码或需要mov操作才能获得的常量。 db允许您在程序启动之前在内存中提供数据。

这是一个演示db的鼻子:

; 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

equ只能定义一个常量,直到汇编器支持的最大值

equ的例子,以及它的一些常见限制。

; 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

生成的二进制文件根本没有字节,因为equ不会污染图像;所有对equ的引用都被该equ的右边所取代。