2011-11-04 223 views
16
len: equ 2 
len: db 2 

他們是否一樣,生產的標籤可以用來代替2?如果不是,那麼每個申報單的優點或缺點是什麼?它們可以互換使用嗎?NASM中equ和db有什麼區別?

回答

26

首先是equate,類似於C的:

#define len 2 

在於它實際上不分配在最終代碼的任何空間,它簡單地設置len符號爲等於2。然後,當稍後在源代碼中使用len,與使用常量2的情況相同。

第二是define byte,類似於C的:

int len = 2; 

實際分配空間,在存儲器中的一個字節,存儲2那裏,並設置len是該字節的地址

下面是一些僞彙編代碼顯示的區別:

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

+2

NASM 2.10.09 ELF輸出nitpicks:1)「沒有數據產生」:鏈接和RAM空間後,可執行文件爲true,但NASM生成的目標文件包含符號數據。 2)「類似於C的#define」:從某種意義上說,「equ」確實生成了一個符號,它可以被其他具有「extern」的目標文件使用,並且不會在這些文件中包含宏。更多細節:http://stackoverflow.com/a/33148242/895245 –

+0

好點,@Ciro,我認爲從上下文中可以明顯地看出其含義,但爲了確定,我已將數據更改爲代碼以確保清晰。至於'#define',相似性不一定是平等的,但我會盡力澄清:-) – paxdiablo

1

摘要

NASM 09年2月10日ELF輸出:

  • db沒有任何魔法效果:它簡單地直接輸出字節到輸出對象文件。

    如果那些字節碰巧位於符號的前面,那麼符號會在程序啓動時指向該值。

    如果你在文本部分,你的字節將被執行。

    您使用的天氣dbdw等沒有指定符號的大小:符號表條目的st_size字段不受影響。

  • equ使當前行中的符號在其符號表項中具有st_shndx == SHN_ABS魔法值。

    不是將字節輸出到當前目標文件位置,而是將其輸出到符號表條目的st_value字段。

其他所有從此。

要了解真正的含義,您應該首先了解the basics of the ELF standardrelocation

SHN_ABS理論

SHN_ABS通知鏈接是:

  • 搬遷是不是要在這個符號
  • 符號條目的st_value場被用作值完成直接

將此與「常規」符號進行對比,其中v符號的符號是內存地址,因此必須經過重定位。

由於它不指向內存,因此可以通過內聯將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

如果我們想用x從C程序,我們需要這樣的:

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_ABSy不是。

也看到Size0ydb絕不告訴y這是一個單字節寬。我們可以簡單地添加兩個db指令來在那裏分配2個字節。

然後:

objdump -dr equ 

給出:

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

所以我們看到,0x1被聯到指令,而y得到了搬遷地址0x8049088的價值。

在Ubuntu 14.04 AMD64上測試。

文檔

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

EQU定義一個符號,一個給定的常數值:當使用EQU,源極線必須含有一個標籤。 EQU的作用是將給定的標籤名稱定義爲其(僅)操作數的值。這個定義是絕對的,以後不能改變。因此,舉例來說,

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

限定msglen是恆定12. msglen可能不那麼稍後重新定義。這不是一個預處理器定義:msglen的值在定義時使用$的值(參見3.5節的解釋$)計算一次,而不是在被引用的任何地方評估,並使用$在參考點。

類似的問題,請參見氣:Difference between .equ and .word in ARM Assembly?.equiv似乎是關閉油氣當量。

0

equ:預處理器時間。類似於#define,但大多數彙編程序缺少#undef,除了右邊的固定字節數的原子常量外,其他所有彙編程序的equ指令都不支持浮點,雙精度和列表。

db:編譯時間。存儲在db中的值以彙編器的特定偏移量存儲在二進制輸出中。 equ允許你定義通常需要硬編碼的常量,或者需要mov操作才能得到。 db允許你在程序啓動之前在內存中有數據。

這裏有一個NASM示範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不污染圖像;所有對等式的引用都被該等式的右邊替換。