Explains除非我们在存储地址存储的值中添加立即值时指定大小运算符(例如 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
............................................... .........
24: error: operation size not specified.
公平公平。
我很好奇为什么会这样。由于以下两段代码将产生相同的结果。
add byte [ebx], 32
或
add dword [ebx], 32
那它有什么区别? (除了在这个例子中你为什么要使用dword没有多大意义)。这只是因为“NASM这么说”吗?或者这里有一些我缺少的逻辑?
如果汇编程序可以从寄存器名称解密操作数大小,例如add [ebx], eax
可以工作,为什么不对立即值执行相同的操作,即只需继续并预先计算立即值的大小。
在向内存地址的值添加立即值时,需要指定大小运算符的要求是什么?
NASM版本2.11.08 架构x86
答案 0 :(得分:4)
由于以下两段代码将产生相同的结果:
add byte [ebx], 32 add dword [ebx], 32
它们只会产生相同的结果,因为'P' + 32
不会进入下一个字节。
根据结果设置标志。如果第4个字节的高位设置,那么将为dword版本设置SF
。
re:关于CF如何运作的评论:
来自添加的结果始终为0
或1
。即,两个N
位整数之和总是适合(N+1)
位整数,其中额外位为CF
。可以将add eax, ebx
视为在CF:EAX
中产生结果,其中每个位可以是0或1,具体取决于输入操作数。
此外,如果ebx
指向页面中的最后一个字节,则dword [ebx]
可能会出现段错误(如果下一页未映射),但byte [ebx]
则不会。
这也有性能影响:字节的读 - 修改 - 写不能存储转发到双字加载,而dword读 - 修改 - 写访问所有4个字节。
由于这些以及其他各种原因,NASM汇编到输出文件中的指令的操作码是add r/m32, imm8
还是add r/m8, imm8
的操作码是否重要。
这是一件好事,它迫使你明确指出你的意思而不是某种默认。基于直接大小的基础也会令人困惑,尤其是在使用ASCII_casebit equ 0x20
常量时。更改常量时,不希望指令的操作数大小发生变化。