NASM 和8位内存偏移混淆
NASM and 8-bit memory offset confusion
从英特尔软件开发人员手册(在此 post 中称为 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 — A simple memory variable (memory offset) of type byte, word, or doubleword used by some variants of the MOV instruction. The actual address is given by a simple offset relative to the segment base. No ModR/M byte is used in the instruction. The number shown with moffs
indicates its size, which is determined by the address-size attribute of the instruction.
我强调了 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?如果是这样,它的代码将无法在 Intel CPUs 上正确执行,所以它应该遵循它!
你能解释一下我哪里错了吗?
moffs
后面的大小后缀其实是指操作数的大小,而不是地址本身的大小。这反映了 r/m
.
后尺寸后缀的含义
手册实际上在注释中是这样说的:
NOTES:
* The moffs8, moffs16, moffs32 and moffs64 operands specify a simple offset relative to the segment base, where 8, 16, 32 and 64
refer to the size of the data. The address-size attribute of the instruction determines the size of the offset, either 16, 32 or 64
bits.
从英特尔软件开发人员手册(在此 post 中称为 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 — A simple memory variable (memory offset) of type byte, word, or doubleword used by some variants of the MOV instruction. The actual address is given by a simple offset relative to the segment base. No ModR/M byte is used in the instruction. The number shown with
moffs
indicates its size, which is determined by the address-size attribute of the instruction.
我强调了 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?如果是这样,它的代码将无法在 Intel CPUs 上正确执行,所以它应该遵循它!
你能解释一下我哪里错了吗?
moffs
后面的大小后缀其实是指操作数的大小,而不是地址本身的大小。这反映了 r/m
.
手册实际上在注释中是这样说的:
NOTES:
* The moffs8, moffs16, moffs32 and moffs64 operands specify a simple offset relative to the segment base, where 8, 16, 32 and 64 refer to the size of the data. The address-size attribute of the instruction determines the size of the offset, either 16, 32 or 64 bits.