从英特尔软件开发人员手册(本文中称为ISDM)和x86指令集参考(我假设,它只是前者的副本),我们知道该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是字节类型,大小是8位.
我是大会的初学者,所以,在读完之后,我立即开始mov moffs8, al使用NASM 的指令.这是我写的代码:
; File name: mov_8_bit_al.s
USE32
section .text
mov BYTE [data], al
section .bss
data resb 2
Run Code Online (Sandbox Code Playgroud)
这是nasm -f bin mov_8_bit_al.s产生的(十六进制):
A2 08 00 00 00
Run Code Online (Sandbox Code Playgroud)
以下是我对此的理解:
A2 是的操作码 MOV moffs8, AL08是内存偏移本身,大小为1个字节00 00 00 是一些垃圾它看起来像是08 00 00 00内存偏移,但在这种情况下,它是一个moffs32,而不是moffs8!因此,CPU在执行时只读取一个字节A2,并将其00视为ADD指令或其他内容,这不是预期的.
目前,在我看来,NASM在这里生成了无效的字节代码,但我想我是谁误解了某些东西......也许NASM不遵循IDSM?如果是这样,它的代码将无法在Intel CPU上正确执行,因此它应该遵循它!
你能解释我错在哪里吗?
moffs实际上,大小后缀是指操作数大小,而不是地址本身的大小.这反映了后面的大小后缀的含义r/m.
该手册实际上是在说明中这样说的:
注意:
*moffs8,moffs16,moffs32和moffs64操作数指定相对于段基的简单偏移量,其中8,16,32和64表示数据的大小.指令的address-size属性确定偏移的大小,16位,32位或64位.