[var] 和 var 之间的汇编区别

Assembly difference between [var], and var

我正在学习汇编程序,现在我对 [variable]variable 之间的区别一无所知。正如教程所说,两者都是指针,那么这样做有什么意义呢?为什么我必须在 [] 之前使用 type Identifier? 我的汇编器:nasm x86_64 running on Linux--> Ubuntu

在 x86 Intel 语法中 [expression] 表示地址 expression 处的内存内容。
(除了在 MASM 中 expression 是数字文字或 equ 没有寄存器的常量,then it's still an immediate


expression 不带括号取决于您使用的汇编程序。

NASM-风格(NASM,YASM):

mov eax,variable      ; moves address of variable into eax
lea eax,[variable]    ; equivalent to the previous one (LEA is exception)
mov eax,[variable]    ; loads content of variable into eax

MASM 风格(还有 TASM 甚至 GCC/GAS .intel_syntax noprefix):

mov eax,variable      ; load content of variable (for lazy programmers)
mov eax,OFFSET variable   ; address of variable
lea eax,[variable]    ; address of variable
mov eax,[variable]    ; content of variable

GAS(AT&T 语法):它不是 Intel 语法,请参阅 the AT&T tag wiki。 GAS 还使用不同的指令(例如 .byte 而不是 db),即使在 .intel_syntax 模式下也是如此。


在所有情况下,variable 是标记内存中特定位置的符号的别名,标签出现的位置。所以:

variable1  db  41
variable2  dw  41
label1:

将三个符号生成符号 table、variable1variable2label1

当你在代码中使用它们中的任何一个时,比如 mov eax,<symbol>,它没有信息是被 dbdw 定义还是作为标签,所以它不会当你做 mov [variable1],ebx 时给你任何警告(覆盖定义的第一个字节之外的 3 个字节)。

它只是内存中的一个地址。

(在 MASM 中除外,其中数据部分中标签后的 db 或 dd 确实与其关联的大小 "variable name"。)


当无法从指令操作数本身推导出类型时,类型标识符在大多数汇编器中是必需的。

mov [ebx],eax ; obviously 32 bits are stored, because eax is 32b wide
mov [ebx],1   ; ERROR: how "wide" is that immediate value 1?
mov [ebx],WORD 1 ; NASM syntax (16 bit value, storing two bytes)
mov WORD [ebx],1 ; NASM syntax (16 bit value, storing two bytes)
mov WORD PTR [ebx],1 ; MASM/TASM syntax

一个使用寄存器和指针的小例子:

mov eax, 10 表示:将值 10 移入寄存器 EAX。在这种情况下,EAX 仅用于存储一些内容。 EAX 包含什么对程序员来说根本不重要,因为它无论如何都会被擦除。

mov [eax], 10表示:将值10移动到EAX寄存器中存储的地址中。在这种情况下,存储在 EAX 中的值对我们来说很重要,因为它是一个 指针 ,这意味着我们必须去 EAX 寄存器看看包含什么,然后我们使用这个值作为访问地址。

使用指针时需要两个步骤:

  1. 转到 EAX,看看它包含什么值(例如 EAX = 0xBABA);

  2. 转到EAX指向的地址(在我们的例子中是0xBABA)并在其中写入10。

当然,指针不一定和寄存器一起使用,这个小例子只是为了解释它是如何工作的。

既然您已经了解 C++,我将通过向您展示这些表达式的 C 等价物来回答。

写的时候

[variable]

在汇编中,相当于

*variable

在 C 中。也就是说,将 variable 视为指针并取消引用该指针——获取指针指向的值。

类似地,'type identifiers' 就像将指针转换为不同的类型:

ASM:
    dword ptr [variable]
C:
    *((uint32_t*) variable)

ASM:
    word ptr [variable]
C:
    *((uint16_t*) variable)

我希望这可以帮助您理解这些表达式的含义。


(本节引用了已从原始问题中删除的附录)

我不完全确定你在使用 'conversion to ascii' 时遇到了什么问题,但我怀疑你只是对它在输出中的视觉呈现方式感到困惑。

例如,如果您有这样的代码:

myInteger db 41
mov AL, byte ptr [myInteger]

mov 会将值 41 从内存复制到 AL 寄存器中。数字 41 恰好是 ) 字符的 ascii 表示,但这并没有改变任何东西。该值是被解释为 ascii 字符还是整数由您决定,因为它们是相同的值。