Assembly 当我将使用EQU定义的常量复制到NASM程序集中的EAX中时会发生什么?

Assembly 当我将使用EQU定义的常量复制到NASM程序集中的EAX中时会发生什么?,assembly,nasm,Assembly,Nasm,在经历了头痛之后,我发现我一直在将1字节变量(db)复制到EAX,这意味着变量后面的3个字节也会被复制。现在我知道了这一点,我正在查看类似场景的代码,并发现: 在.data中,我有一个数组,其大小定义为常量: array db 1,2,3,4 size equ $-array 稍后,在.text中,我有以下内容: mov EAX,size 这让我想知道:那里到底发生了什么?尺寸是多少?是一个字节吗?一句话?EAX是否接收到不应该接收的额外字节?是的,汇编程序应该为其选择最合适的大

在经历了头痛之后,我发现我一直在将1字节变量(
db
)复制到
EAX
,这意味着变量后面的3个字节也会被复制。现在我知道了这一点,我正在查看类似场景的代码,并发现:

.data
中,我有一个数组,其大小定义为常量:

array  db   1,2,3,4
size   equ  $-array
稍后,在
.text
中,我有以下内容:

mov EAX,size
这让我想知道:那里到底发生了什么?尺寸是多少?是一个字节吗?一句话?EAX是否接收到不应该接收的额外字节?

是的,汇编程序应该为其选择最合适的大小(如果有多个可能的编码)。如果可能的最小大小超过目标寄存器的大小,则应显示错误,或至少显示警告

在您的示例中,行
mov-EAX,size
将进行组合,就像您键入了
mov-EAX,4
一样,并且汇编器应该为它选择最合适的大小(如果有多个可能的编码)。如果可能的最小大小超过目标寄存器的大小,则应显示错误,或至少显示警告


在您的示例中,
mov-EAX,size
行的组合方式与您键入的
mov-EAX,4
相同,它是从实际位置减去
数组开始处计算的立即值。
eq
%define
之间的重要区别在于编译器直接在使用
eq
的地方替换
$
符号,而
%define
只是在预处理代码时有用的文本表示,因此
$
对于每次出现都是不同的。使用
%define
的对应代码为

array: db 1, 2, 3, 4
array_end: 
%define array_end - array
虽然
eq
似乎非常适合于数组数据操作,但是
%define
对于stringss很有用

编译器执行指令时会发生什么情况?
它只是将常量的名称替换为其已计算的值。编译器然后对指令进行如下编码:

mov r32, imm -> 0xB8 + 0x00 (for EAX)
size         -> 0x04 0x00 0x00 0x00
另一个寄存器具有不同的值,可在英特尔手册中找到。添加到
0xB8
中的是Intel保存1个字节的技巧,用于将
REG
代码存储在
ModR/M
字节中


指令通常不使用这种技巧,但一些常用指令通过使用累加器寄存器的特殊操作码来节省一个字节。

它是从实际位置减去
数组开始处计算的立即值。
eq
%define
之间的重要区别在于编译器直接在使用
eq
的地方替换
$
符号,而
%define
只是在预处理代码时有用的文本表示,因此
$
对于每次出现都是不同的。使用
%define
的对应代码为

array: db 1, 2, 3, 4
array_end: 
%define array_end - array
虽然
eq
似乎非常适合于数组数据操作,但是
%define
对于stringss很有用

编译器执行指令时会发生什么情况?
它只是将常量的名称替换为其已计算的值。编译器然后对指令进行如下编码:

mov r32, imm -> 0xB8 + 0x00 (for EAX)
size         -> 0x04 0x00 0x00 0x00
另一个寄存器具有不同的值,可在英特尔手册中找到。添加到
0xB8
中的是Intel保存1个字节的技巧,用于将
REG
代码存储在
ModR/M
字节中

指令通常不使用这种技巧,但一些频繁的指令通过使用累加器寄存器的特殊操作码来节省一个字节