NASM和8位内存偏移混淆

时间:2017-09-18 15:31:55

标签: assembly x86 mov

来自英特尔软件开发人员手册(本文中称为ISDM)和x86 Instruction Set Reference(我认为,这只是前者的副本),我们知道mov指令可以将数据从eax/ax/al移动到内存偏移量,反之亦然。

例如,mov moffs8, alal寄存器的内容移动到某个 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

以下是我对此的理解:

  • A2MOV moffs8, AL
  • 的操作码
  • 08是内存偏移本身,大小 1字节
  • 00 00 00是垃圾

看起来08 00 00 00是内存偏移量,但在这种情况下,它是moffs32,而不是moffs8!因此,CPU在执行A2时只读取一个字节,并将00视为ADD指令或其他内容,这不是预期的。

目前,在我看来,NASM在这里生成了无效的字节代码,但我想我是谁误解了某些东西......也许NASM并没有跟随IDSM?如果是这样,它的代码将无法在英特尔CPU上正确执行,因此它应该遵循它!

你能解释一下我错在哪里吗?

1 个答案:

答案 0 :(得分:7)

moffs之后的大小后缀实际上是指操作数大小,而不是地址本身的大小。这反映了r/m之后大小后缀的含义。

手册在说明中实际上是这样说的:

  

注意:
  * moffs8,moffs16,moffs32和moffs64操作数指定相对于段基的简单偏移量,其中8,16,32和64   指的是数据的大小。指令的address-size属性确定偏移的大小,16,32或64   位。