【问题标题】:Confusing brackets in MASM32MASM32 中令人困惑的括号
【发布时间】:2014-09-27 13:54:57
【问题描述】:

我正在尝试掌握 MASM32,但对以下内容感到困惑:

我认为括号是用于间接的,所以如果我有一个预定义的变量

 .data
   item dd 42

然后

 mov ebx, item

会将“item”的内容,即数字 42,放入 ebx 和

 mov ebx, [item]

会将“item”的地址,即存储 42 的位置,放入 ebx。

但控制台应用程序中的以下代码:

 mov ebx, item
 invoke dwtoa, ebx, ADDR valuestr 
 invoke StdOut, ADDR valuestr
 mov ebx, [item]
 invoke dwtoa, ebx, ADDR valuestr 
 invoke StdOut, ADDR valuestr

打印 42 两次。要获取“项目”的地址,我似乎需要

 mov ebx, [OFFSET item]
 invoke dwtoa, ebx, ADDR valuestr 
 invoke StdOut, ADDR valuestr

谁能解释一下 MASM 中方括号的含义,或者给我一个好的参考。

【问题讨论】:

  • duplicate of this question 还指出var2 dword var1 组装到var1 的地址。这是唯一正常的行为,因为var1 可能是extern,使其内容在汇编时不可用。幸运的是,offset var1 在该上下文中是允许的,因此您始终可以使用明确的表示法。

标签: assembly masm masm32


【解决方案1】:

MASM 对于具有类型的汇编语言来说是不寻常的。 MASM 知道是因为您如何定义符号item,它是DWORD 类型的内存位置。当您将它用作操作数时,您知道您(可能)意味着您想要存储在地址中的值,而不是地址的值。因此,无论您使用item 还是[item],MASM 都假定您的意思是后者。如果你真的想要项目的地址,你需要使用OFFSET item

另一方面,如果您使用item = 42item 定义为常量,那么mov ebx, item 将加载立即值。由于这种模糊性,您需要知道如何定义 item 以确定它是立即操作数还是内存操作数,最好避免使用裸符号作为操作数。

我应该补充一点,当您仅使用符号或数字时,方括号 [] 对 MASM 几乎没有任何意义。仅当您将它们与寄存器一起使用时,它们才有意义。下面是一些例子:

item    DD  42
const   =   43

    mov eax, item             ; memory operand (the value stored at item)
    mov eax, [item]           ; memory operand
    mov eax, OFFSET item      ; immediate operand (the address of item)
    mov eax, [OFFSET item]    ; immediate operand

    mov eax, const            ; immediate operand (43)
    mov eax, [const]          ; immediate operand
    mov eax, ds:[const]       ; memory operand (the value at address 43)
    mov eax, fs:30h           ; memory operand (the value at address 30h + fs base)
    mov eax, OFFSET const     ; immediate operand
    mov eax, [OFFSET const]   ; immediate operand

    mov eax, 42               ; immediate operand
    mov eax, ebx              ; register operand (the value of EBX)
    mov eax, [ebx]            ; indirect operand (the value pointed to by EBX)

因此,如果没有寄存器,方括号只会显示您的意图。如果您打算将符号用作内存操作数,则应在符号周围加上方括号,并将 OFFSET 与您打算用作立即值的符号一起使用。

【讨论】:

  • 如果你使用mov eax, [esi + OFFSET item],MASM 会做什么?有效地址中存在寄存器是否会将其变为负载而不是mov r32, imm32
  • @PeterCordes 寄存器和括号的组合使它成为一个内存操作数。因为有一个寄存器添加到一个值,所以需要括号。指令mov eax, esi + OFFSET item 是非法的,因为它不能被编码为立即操作数或寄存器操作数,我相信你知道。如果你想要这条指令所隐含的操作,将item的偏移量加到ESI并存入EAX,你可以使用lea eax, [esi + OFFSET item]。我还要补充一点,mov eax. [esi + item] 的含义与您的示例几乎相同,除非item 是它必须为 DWORD 类型的标签。
  • 我想我的意思是问这是负载还是语法错误,因为我真的很惊讶[OFFSET item] 是立即数。当然[esi + OFFSET item] 不能是imm32 :P 无论如何,好的,所以这是一个负载,需要括号,谢谢。
  • @PeterCordes 我恢复了您的编辑,因为它比您描述的要复杂一些。您最近作为副本关闭的问题中的问题是跳转表标签是用table: 定义的,使其成为 NEAR 符号(或任何 x64 版本的 MASM 调用它)。如果它被定义为table QWORD ...,那么它将是一个 QWORD 符号并且将使用间接跳转。无论哪种方式,括号都没有区别,但符号的类型确实很重要。使用 QWORD PTR 通过更改地址的类型来解决问题,但通常这不是必需的。
  • fs:30h 也是一个内存操作数,对吧?您只显示fs:[30h] 表单。 [两条指令的区别:mov eax, dword ptr fs:[30h] and mov eax, large fs:30h in dereferencing PEB?](Difference between two instructions: mov eax, dword ptr fs:[30h] and mov eax, large fs:30h in dereferencing PEB?) 有一个mov eax, large fs:30h(可能是IDA语法),OP很困惑由于缺少[]。 (所以它可能是这个的副本)
猜你喜欢
  • 1970-01-01
  • 2022-01-21
  • 2022-01-17
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多