为什么在NASM中我们必须使用方括号([])来MOV到内存位置?

时间:2018-03-28 12:33:05

标签: assembly nasm yasm

例如,如果我有一个名为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

那么,为什么方括号的行为会有所不同,这取决于它们是第一个还是第二个操作数?

2 个答案:

答案 0 :(得分:4)

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

例如,我们以此为例。

mov ax, [0x1000]

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

如果将值移动到某个数字,则将其置于值(内存位置)。

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

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

如果您愿意,可以忽略此项,但如果您了解C,则可能知道scanf()

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

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

如果我们这样做,

scanf("%d", &a);

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

答案 1 :(得分: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指令根据其操作数是内存位置还是值而表现不同。我正在自学汇编程序,必须自己解释一下。