首页 文章

为什么在向内存地址的值添加立即值时需要消除歧义

提问于
浏览
3

Explains除非我们在向存储器地址存储的值添加立即值时指定大小运算符(例如字节或双字),否则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

1 回答

  • 4

    由于以下两段代码将产生相同的结果:add byte [ebx],32
    添加dword [ebx],32

    它们只产生相同的结果,因为 'P' + 32 不会进入下一个字节 .

    根据结果设置标志 . 如果第4个字节的高位设置,那么将为dword版本设置 SF .

    re:关于CF如何工作的评论:

    从添加中执行始终是 01 . 即,两个 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 常量时 . 更改常量时,不希望更改指令的操作数大小 .

相关问题