4

例如,如果我有一个名为 test 的变量声明如下:

test db 0x01      ;suppose the address is 0x00000052

如果我这样做:

mov rax, test     ;rax = 0x00000052
mov rax, [test]   ;rax = 0x01

但是,当我尝试保存它时,如果我们遵循相同的模式:

mov test, 0x01    ;address 0x00000052 = 0x01
mov [test], 0x01  ;address 0x01 = 0x01

但实际上是:

mov [test], 0x01  ;address 0x00000052 = 0x01

那么,为什么方括号的行为会根据它们是第一个操作数还是第二个操作数而有所不同呢?

4

2 回答 2

5

在大多数汇编程序中,使用方括号取消引用内存位置。您将该值视为内存地址。

例如,让我们以此为例。

mov ax, [0x1000]

这将获得 0x1000 处的值并将其放入 AX。如果删除方括号,则仅移动 0x1000。

如果将值移动到数字,则将其放入值(内存位置)中。

如果您是 C 开发人员,这里有一个示例问题。

如果你被别人欺负学习 C,不要让这个例子惹恼你,称你为“巨魔”。

如果你愿意,你可以忽略这个,但你可能已经知道scanf()你是否知道 C。

int a = 10;
scanf("%d", a);

现在,这是一个非常常见的错误,因为我们没有得到变量的内存地址。相反,我们使用它的值作为地址。该scanf()功能要求您提供地址。

如果我们这样做,

scanf("%d", &a);

我们将得到变量 a 的地址。

于 2018-03-28T14:15:38.863 回答
1

Steve Woods 的帖子给我的印象是他认为 & 是一个取消引用运算符。& 是 C 的引用运算符。* 是 C 的解引用运算符。OP有一个合理的担忧。[] 似乎可以同时发挥作用,具体取决于上下文。它既不是取消引用也不是引用运算符。它是“这是一个内存地址!!!” 操作员。

https://nasm.us/doc/nasmdoc3.html#section-3.3

有效地址是引用内存的指令的任何操作数。在 NASM 中,有效地址有一个非常简单的语法:它们由一个计算为所需地址的表达式组成,用方括号括起来。

; assume wordvar was used as a label, and the linker gave it address 6291668
; or mostly equivalently, you used   wordvar equ 6291668

mov eax,wordvar         ; eax = 6291668. Move value 6291668 to eax.
mov eax,[wordvar]       ; eax =  12. Move contents of address 6291668 to eax.

mov eax,13
; mov wordvar,eax       ; Move eax to value 6291668. syntax error.
mov [wordvar],eax       ; mem(6291668) = 13. Move eax to address 6291668.

当操作数是内存地址时,它必须用方括号括起来以告诉 nasm 是这种情况。它不是取消引用它,它只是让 nasm 知道发生了什么。如果它等价于解引用运算符,

mov [wordvar], eax

将内存位置 12 设置为 13。

这不是取消引用运算符。这是“这是一个内存地址”运算符。这似乎是在不同情况下的解引用和引用,因为 x86 和 x86_64 指令的行为基于其操作数是内存位置还是值而有所不同。我正在自学组装,我必须自己解释这一点才能弄清楚。

于 2019-02-09T16:46:58.363 回答