说明除非我们在将立即数添加到存储在内存地址的值时指定大小运算符(例如byte或dword),否则NASM 将返回错误消息。
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
Run Code Online (Sandbox Code Playgroud)
………………………………………………………………………………………………………………………………………………………… ......
24: error: operation size not specified.
Run Code Online (Sandbox Code Playgroud)
公平的公平。
我很好奇为什么会这样。由于以下两段代码将产生相同的结果。
add byte [ebx], 32
或者
add dword [ebx], 32
那么它有什么区别呢?(除了对为什么在这种情况下使用 dword 没有多大意义之外)。仅仅是因为“NASM 这么说”吗?还是这里有一些我缺少的逻辑?
例如,如果汇编程序可以从寄存器名称解密操作数大小,add [ebx], eax那么为什么不对立即值执行相同的操作,即继续并预先计算立即值的大小。
什么要求意味着在将立即值添加到内存地址处的值时需要指定大小运算符?
NASM 版本 2.11.08 架构 x86
它确实不管操作数大小您使用以下几个原因,这将是奇怪和不直观/非明显有被整数值暗示的大小。当存在歧义时出现 NASM 错误是一个更好的设计,因为这两个操作数都不是寄存器。
由于以下两段代码将产生相同的结果:
Run Code Online (Sandbox Code Playgroud)add byte [ebx], 32 add dword [ebx], 32
它们只产生相同的结果,因为'P' + 32不会进入下一个字节。
根据结果设置标志。如果第 4 个字节设置了其高位,则将SF为 dword 版本设置。
回复:关于 CF 工作原理的评论:
添加的结转始终是0或1。即两位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。
这是一件好事,它迫使您明确表示您的意思,而不是使用某种默认值。基于立即数的大小也会令人困惑,尤其是在使用ASCII_casebit equ 0x20常量时。您不希望在更改常量时更改指令的操作数大小。