在遇到Why is my register-constant comparison not working in NASM Assembly?的头痛之后,我发现我一直在将1字节变量(db
)复制到EAX
,这意味着变量之后的三个字节会被复制同样。现在我知道了,我正在查看类似场景的代码,并发现了这个:
在.data
中,我有一个数组,其大小定义为常量:
array db 1,2,3,4
size equ $-array
稍后,在.text
我有这个:
mov EAX,size
这让我想知道:到底发生了什么? size
的大小是多少?这是一个字节吗?一个字? EAX是否应该接收额外的字节?
答案 0 :(得分:3)
它是an immediate,汇编程序应该为它选择最合适的大小(如果有多个可能的编码)。如果可能的最小尺寸超过目标寄存器的大小,则应该出现错误,或至少发出警告。
在您的示例中,行mov EAX,size
会像您键入mov EAX,4
一样汇编。
答案 1 :(得分:2)
是从实际位置减去array
的开头计算的立即数值。
equ
和%define
之间的重要区别在于编译器直接替换使用$
的{{1}}符号,而equ
只是在预处理代码时有用的文本表示,所以%define
对于每次出现都是不同的。使用$
的相应代码是
%define
尽管array: db 1, 2, 3, 4
array_end:
%define array_end - array
对于数组数据操作似乎是完美的,但equ
对于stringss非常有用。
当编译器达到你的指令时到底发生了什么? 它只是将常量的名称替换为已经计算的值。编译器然后按如下方式对指令进行编码:
%define
其他寄存器具有不同的值,可在“英特尔手册”中找到。 mov r32, imm -> 0xB8 + 0x00 (for EAX)
size -> 0x04 0x00 0x00 0x00
的加法是英特尔节省1个字节的技巧,用于在0xB8
字节中存储REG
代码。
指令通常不会使用这种技巧,但是一些频繁的指令通过使用特殊操作码来累加器寄存器来保存一个字节。