为什么我们需要在将立即值添加到内存地址处的值时消除歧义

Why do we need to disambiguate when adding an immediate value to a value at a memory address

Explains 除非我们在添加立即数时指定大小运算符(例如 bytedword)存储在内存地址的值,NASM 将 return 一条错误消息。

section .data           ; Section containing initialized data

    memory_address: db "PIPPACHIP"

section .text           ; Section containing code

global  _start          ; Linker needs this to find the entry point!

_start:

23            mov ebx, memory_address
24            add [ebx], 32

................................................ ............

24:  error: operation size not specified. 

公平的公平。

我很好奇为什么会这样。由于以下两段代码将产生相同的结果。

add byte [ebx], 32

add dword [ebx], 32

那么这有什么区别呢? (除了在这种情况下为什么要使用 dword 没有多大意义)。仅仅是因为“NASM 这么说”吗?还是这里有我缺少的逻辑?

如果汇编程序可以从寄存器名称破译操作数的大小,例如 add [ebx], eax 就可以,为什么不对立即值做同样的事情,即继续计算立即值的大小前期。

将立即数与内存地址处的值相加时需要指定大小运算符的要求是什么?

NASM 版本 2.11.08 架构 x86

确实 出于多种原因,您使用的操作数大小很重要,并且整数值暗示的大小会很奇怪且不直观/不明显。当存在歧义时出现 NASM 错误是一个更好的设计,因为两个操作数都不是寄存器。


As the two following segments of code will yield the same result:

add byte [ebx], 32
add dword [ebx], 32

它们只产生相同的结果,因为 'P' + 32 没有进位到下一个字节。

根据结果设置标志。如果第 4 个字节设置了高位,则 SF 将为双字版本设置。

回复:关于 CF 工作原理的评论:

添加的结转总是 01。即两个 N 位整数的总和将始终适合 (N+1) 位整数,其中额外的位是 CF。将 add eax, ebx 视为在 CF:EAX 中产生结果,其中每个位可以是 0 或 1,具体取决于输入操作数。


此外,如果 ebx 指向页面中的最后一个字节,则 dword [ebx] 可能会出现段错误(如果下一页未映射),但 byte [ebx] 不会。

这也对性能有影响:一个字节的读取-修改-写入不能存储转发到双字加载,而双字读取-修改-写入访问所有 4 个字节。 (如果另一个线程在该线程将旧值存储在其上之前刚刚修改了其他字节之一,则正确。)


出于这些和其他各种原因,NASM 汇编到输出文件中的指令的操作码是 add r/m32, imm8 还是 add r/m8, imm8 的操作码。[=27 很重要=]

这是一件好事,它迫使您明确说明您的意思,而不是有某种默认值。将它基于立即数的大小也会造成混淆,尤其是在使用 ASCII_casebit equ 0x20 常量时。当您更改常量时,您不希望指令的操作数大小发生变化。