(汇编)试图将数据加载到不适合它的寄存器中的行为?
(Assembly) behavior of trying to load data into registers that cannot fit it?
我现在正在学习汇编,只是想知道是否有人可以阐明试图将数据移动到不适合它的寄存器中的行为。
例如,假设我们有(在 x86 上,AT&T 语法):
movl [=10=]xff00abcd, %ax
其中%ax 是%eax 的16 位子寄存器,会发生什么?指令会完全失败,还是 %ax 会包含 $0xff00?
指令完全失败,如果你编译你会得到:
warning: word data exceeds bounds [-w+number-overflow]
因此您首先必须将数据移动到eax
寄存器,然后ax
将包含eax
的低16位,因此ax
将等于 0xabcd
首先,这不是 mov
ing 到 16 位寄存器的正确后缀。movl
表示“mov
到 longword/doubleword” ,因此必须将 movw
更改为“mov
到一个单词”,这是 ax
寄存器的大小。有了这个,调试器是检查此类行为的最简单方法。假设您使用 AT&T 语法中的 GAS,可以使用这个简单的程序进行检查:
.text
.globl main
main:
movw [=10=]xff00abcd, %ax
# Then exit the program
GAS 可能会抱怨这个:对我来说,它产生了这个警告:
test.S: Assembler messages:
test.S:4: Warning: -16733235 shortened to 43981
如果我在 movw
指令之后放置一个断点,我可以看到 %ax
保持 0xabcd
,所以低 16 位。不过,这对您来说可能也不是保证,也许还有其他一些因素,其中之一是,正如哈罗德所指出的那样,这是汇编程序必须处理的事情,而不是处理器。因此,如果您没有使用 GAS,或者即使您使用了 GAS,您可能不会遇到与我相同的行为。
这样的指令不可编码:根本没有机器代码的字节序列可以告诉CPU移动值0xff00abcd
进入 ax
。 (为什么体系结构设计者应该指定任何字节序列来告诉 CPU 这样做,而这显然是不可能的?)。所以不可能执行这样的指令,因为它不存在。
那么当被要求 assemble 一条不存在的指令时,您的 assembler 会怎么做?当然,它应该警告你。它接下来做什么取决于你的 assembler 是如何设计的。一些 assemble 回复者可能只会将其设为致命错误并拒绝继续,直到您修复它。其他人可能会发出一些不同指令的机器代码,希望它可能是你的意思。
gas 显然所做的,与在许多其他情况下处理溢出的方式相匹配,是截断高位并发出 movw [=12=]xabcd, %ax
的机器代码。不过,依赖这种行为并不是一个好主意。