2011-11-04 12 views

Trả lời

26

Đầu tiên là equate, tương tự như C:

#define len 2 

ở chỗ nó không thực sự phân bổ bất kỳ không gian trong mã cuối cùng, nó chỉ đơn giản đặt biểu tượng len là bằng 2. Sau đó, khi bạn sử dụng len sau trong mã nguồn của mình, nó giống như khi bạn đang sử dụng hằng số 2.

Thứ hai là define byte, tương tự như C:

int len = 2; 

không thực sự phân bổ không gian, một byte trong bộ nhớ, lưu trữ một 2 ở đó, và đặt lenđịa chỉ của byte đó .

Dưới đây là một số mã giả-lắp ráp cho thấy sự khác biệt:

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 

Line 1 chỉ đơn giản là thiết lập địa chỉ lắp ráp được 1234, để làm cho nó dễ dàng hơn để giải thích những gì đang xảy ra.

Trong dòng 2, không có mã nào được tạo, trình lắp ráp chỉ cần tải elen vào bảng biểu tượng có giá trị 2. Vì không có mã nào được tạo nên địa chỉ không thay đổi.

Sau đó, khi bạn sử dụng nó trên dòng 4, nó sẽ tải giá trị đó vào thanh ghi.

Dòng 3 cho thấy rằng db là khác nhau, nó thực sự phân bổ một số không gian (một byte) và lưu trữ giá trị trong không gian đó. Sau đó, nó tải dlen vào bảng biểu tượng nhưng cung cấp cho nó giá trị của địa chỉ đó 1234 thay vì giá trị không đổi 2.

Khi sau này bạn sử dụng dlen trên dòng 5, bạn sẽ nhận được địa chỉ mà bạn sẽ phải cân nhắc để nhận giá trị thực tế 2.

+2

NASM 2.10.09 Kết quả đầu ra của ELF: 1) "không có dữ liệu được tạo": true cho tệp thi hành sau khi liên kết và không gian RAM, nhưng tệp đối tượng mà NASM tạo ra có chứa dữ liệu ký hiệu. 2) "tương tự như #define của C": theo nghĩa nào đó, nhưng 'equ' không tạo ra một biểu tượng, có thể được sử dụng bởi các tệp đối tượng khác với' extern' và không bao gồm macro trong các tệp đó. Chi tiết hơn: http://stackoverflow.com/a/33148242/895245 –

+0

Điểm tốt, @Ciro, tôi nghĩ ý nghĩa là rõ ràng từ ngữ cảnh nhưng, để chắc chắn, tôi đã thay đổi dữ liệu thành mã để đảm bảo sự rõ ràng. Đối với '# define', sự tương tự không nhất thiết là bình đẳng nhưng tôi sẽ cố gắng làm rõ điều đó :-) – paxdiablo

1

Tóm tắt

NASM 2.10.09 ELF đầu ra:

  • db không có bất kỳ tác dụng kỳ diệu: nó chỉ đơn giản là kết quả đầu ra byte trực tiếp đến đối tượng tập tin đầu ra.

    Nếu các byte đó xảy ra ở phía trước biểu tượng, biểu tượng sẽ trỏ đến giá trị đó khi chương trình bắt đầu.

    Nếu bạn đang ở trên phần văn bản, byte của bạn sẽ được thực thi.

    Thời tiết bạn sử dụng db hoặc dw, v.v.không chỉ định kích thước của biểu tượng: trường st_size của mục nhập bảng biểu tượng không bị ảnh hưởng.

  • equ làm cho biểu tượng trong dòng hiện tại có st_shndx == SHN_ABS giá trị ma thuật trong mục bảng biểu tượng của nó.

    Thay vì xuất một byte vào vị trí tệp đối tượng hiện tại, nó sẽ đưa nó vào trường st_value của mục nhập bảng biểu tượng.

Tất cả những điều khác sau này.

Để hiểu điều đó thực sự có nghĩa là gì, trước tiên bạn cần hiểu the basics of the ELF standardrelocation.

SHN_ABS lý thuyết

SHN_ABS kể mối liên kết rằng:

  • di dời không phải là để được thực hiện trên biểu tượng này
  • các st_value lĩnh vực mục biểu tượng được sử dụng như một giá trị trực tiếp

Tương phản với ký hiệu "thông thường", trong đó v dấu hiệu của biểu tượng là địa chỉ bộ nhớ thay vào đó, và do đó phải đi qua di chuyển.

Vì nó không trỏ đến bộ nhớ, SHN_ABS các biểu tượng có thể được xóa bỏ một cách hiệu quả khỏi tệp thực thi bởi trình liên kết bằng cách gạch chân chúng.

Nhưng chúng vẫn là biểu tượng thường xuyên trên tệp đối tượng và làm mất bộ nhớ ở đó và có thể được chia sẻ giữa nhiều tệp nếu toàn cầu.

sử dụng mẫu

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

Lưu ý rằng kể từ khi biểu tượng x chứa một giá trị văn chương, không dereference [] phải được thực hiện với nó như thế nào cho y.

Nếu chúng ta muốn sử dụng x từ một chương trình C, chúng tôi cần một cái gì đó như:

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

và thiết lập trên asm:

global x 

quan sát thực nghiệm về sản lượng tạo ra

Chúng tôi có thể quan sát những gì chúng tôi đã nói trước đây với:

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

Bây giờ là:

readelf -s equ.o 

chứa:

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, vì vậy chúng ta thấy rằng xSHN_ABS khi y thì không.

Cũng thấy rằng Size0 cho y: db không có cách nào nói với y rằng đó là rộng một byte duy nhất. Chúng tôi có thể chỉ cần thêm hai chỉ thị db để phân bổ 2 byte tại đó.

Và sau đó:

objdump -dr equ 

cho:

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

Vì vậy, chúng ta thấy rằng 0x1 được inlined vào giảng dạy, trong khi y có giá trị của một địa chỉ di dời 0x8049088.

Đã thử nghiệm trên Ubuntu 14.04 AMD64.

Documents

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

EQU định nghĩa một biểu tượng cho một giá trị không đổi đưa ra: khi EQU được sử dụng, dòng nguồn phải chứa một nhãn. Hành động của EQU là xác định tên nhãn đã cho với giá trị toán hạng (chỉ) của nó. Định nghĩa này là tuyệt đối và không thể thay đổi sau này. Vì vậy, ví dụ,

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

định nghĩa msglen là hằng số 12. msglen có thể không sau đó được xác định lại sau. Đây không phải là định nghĩa tiền xử lý: giá trị của msglen được đánh giá một lần, sử dụng giá trị $ (xem phần 3.5 để giải thích $) tại điểm định nghĩa, thay vì được đánh giá ở bất cứ nơi nào được tham chiếu và sử dụng giá trị của $ tại điểm tham chiếu.

Xem thêm

câu hỏi tương tự cho GAS: Difference between .equ and .word in ARM Assembly?.equiv có vẻ là GAS đóng cửa tương đương.

0

equ: thời gian tiền xử lý. tương tự như #define nhưng hầu hết các assembly không thiếu #undef, và không thể có bất cứ thứ gì ngoài hằng số nguyên tử của số byte cố định ở phía bên tay phải, vì vậy float, double, danh sách không được hỗ trợ với chỉ thị equ của hầu hết các assembly.

db: thời gian biên dịch. giá trị được lưu trữ trong db được lưu trữ trong đầu ra nhị phân bởi bộ ghép tại một độ bù đặc biệt. equ cho phép bạn xác định các hằng số mà thông thường sẽ cần phải được mã hóa cứng hoặc yêu cầu một hoạt động mov để có được. db cho phép bạn có sẵn dữ liệu trong bộ nhớ trước khi chương trình bắt đầu.

Dưới đây là một db NASM Thể hiện:

; 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

Một equ chỉ có thể xác định một hằng số lên đến lớn nhất lắp ráp hỗ trợ

ví dụ về thiết bị kỹ thuật, cùng với một vài hạn chế chung của nó.

; 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 

kết quả nhị phân không có byte nào vì equ không gây ảnh hưởng đến hình ảnh; tất cả các tham chiếu đến một equ được thay thế bằng phía bên tay phải của equ đó.

Các vấn đề liên quan