来自英特尔软件开发人员手册(本文中称为ISDM)和x86 Instruction Set Reference(我认为,这只是前者的副本),我们知道mov
指令可以将数据从eax/ax/al
移动到内存偏移量,反之亦然。
例如,mov moffs8, al
将al
寄存器的内容移动到某个 8位内存偏移moffs8
。
现在,moffs8
是什么?引用ISDM(3.1.1.3):
moffs8,moffs16,moffs32,moffs64 - MOV指令的某些变体使用的字节,字或双字类型的简单存储器变量(存储器偏移)。实际地址由相对于段基的简单偏移给出。指令中没有使用ModR / M字节。
moffs
显示的数字表示其大小,由指令的地址大小属性决定。
我强调句子说moffs8
的类型为 byte ,大小为8位。
我是大会的初学者,所以,在读完之后,我开始使用NASM开始使用mov moffs8, al
指令。这是我写过的代码:
; File name: mov_8_bit_al.s
USE32
section .text
mov BYTE [data], al
section .bss
data resb 2
这是nasm -f bin mov_8_bit_al.s
生成的(十六进制):
A2 08 00 00 00
以下是我对此的理解:
A2
是MOV moffs8, AL
08
是内存偏移本身,大小 1字节 00 00 00
是垃圾看起来08 00 00 00
是内存偏移量,但在这种情况下,它是moffs32
,而不是moffs8
!因此,CPU在执行A2
时只读取一个字节,并将00
视为ADD
指令或其他内容,这不是预期的。
目前,在我看来,NASM在这里生成了无效的字节代码,但我想我是谁误解了某些东西......也许NASM并没有跟随IDSM?如果是这样,它的代码将无法在英特尔CPU上正确执行,因此它应该遵循它!
你能解释一下我错在哪里吗?
答案 0 :(得分:7)
moffs
之后的大小后缀实际上是指操作数大小,而不是地址本身的大小。这反映了r/m
之后大小后缀的含义。
手册在说明中实际上是这样说的:
注意:
* moffs8,moffs16,moffs32和moffs64操作数指定相对于段基的简单偏移量,其中8,16,32和64 指的是数据的大小。指令的address-size属性确定偏移的大小,16,32或64 位。