35

假设我声明了以下内容:

section .bss
buffer    resb     1

这些说明如下section .text

mov    al, 5                    ; mov-immediate
mov    [buffer], al             ; store
mov    bl, [buffer]             ; load
mov    cl, buffer               ; mov-immediate?

我是否正确理解 bl 将包含值 5,而 cl 将包含变量的内存地址buffer

我对两者之间的区别感到困惑

  • 将立即数移入寄存器,
  • 将寄存器移动到立即数(什么进入,数据或地址?)和
  • 将立即数移入不带括号的寄存器
    • 例如,mov cl, buffervsmov cl, [buffer]

更新:阅读回复后,我认为以下摘要是准确的:

  • mov edi, array将第零个数组索引的内存地址放入edi. 即标签地址。
  • mov byte [edi], 3将 VALUE 3 放入数组的第零个索引中
  • 之后add edi, 3edi现在包含数组的第三个索引的内存地址
  • mov al, [array]将第零索引处的 DATA 加载到al.
  • mov al, [array+3]将第三个索引处的 DATA 加载到al.
  • mov [al], [array]无效,因为x86 不能对 2 个显式内存操作数进行编码,并且因为al只有 8 位,即使在 16 位寻址模式下也不能使用。 引用内存位置的内容。(x86 寻址模式)
  • mov array, 3是无效的,因为你不能说“嘿,我不喜欢array存储的偏移量,所以我称之为 3”。立即数只能是源操作数。
  • mov byte [array], 3将值 3 放入数组的第零个索引(第一个字节)。 需要说明byte来避免带有内存、立即操作数的指令的字节/字/双字之间的歧义。否则,这将是一个汇编时错误(操作数大小不明确)。

请说明其中任何一个是否是错误的。(编者注:我修复了语法错误/歧义,因此有效的实际上有效的 NASM 语法。并链接了其他问答以获取详细信息)

4

4 回答 4

26

方括号本质上像解引用运算符一样工作(例如,像*在 C 中一样)。

所以,像

mov REG, x

将 的值移动xREG,而

mov REG, [x]

将指向的内存位置的值移动xREG. 请注意,如果x是标签,则其值为该标签的地址。

至于你的问题:

我是否正确理解 bl 将包含值 5,而 cl 将包含变量缓冲区的内存地址?

是的,你是对的。但请注意,由于CL它只有 8 位宽,它只会包含buffer.

于 2012-04-28T10:13:11.550 回答
20

确实,你的想法是对的。就是bl会包含5,cl会包含buffer的内存地址(其实label buffer本身就是内存地址)。


现在,让我解释一下您提到的操作之间的区别:

  • 可以使用 . 将立即数移动到寄存器中。mov reg,imm可能令人困惑的是,诸如缓冲区之类的标签本身就是包含地址的立即数。

  • 您不能真正将寄存器移动到立即数,因为立即数是常量,例如2或。FF1Ah您可以做的是将寄存器移动到常量指向的位置。您可以这样做mov [const], reg

  • 您还可以使用间接寻址,例如mov reg2,[reg1]提供的 reg1 指向有效位置,它会将 reg1 指向的值传输到 reg2。


因此,mov cl, buffer将缓冲区的地址移动到 cl(它可能会或可能不会给出正确的地址,因为 cl 只有一个字节长),而 mov cl, [buffer]将获得实际值。

概括

  • 当你使用 [a] 时,你指的是 a 指向的地方的值。例如,如果 a 是F5B1,那么 [a] 指的是RAM中的地址 F5B1 。
  • 标签是地址,即像F5B1.
  • 存储在寄存器中的值不必引用为[reg],因为寄存器没有地址。实际上,寄存器可以被认为是立即值。
于 2012-04-28T10:21:20.203 回答
6

你明白了。但是,有一些细节值得牢记:

  1. 地址可以而且通常大于 8 位可以容纳的地址(cl8 位、cx16 位、ecx32 位、rcx64 位)。所以,cl很可能会不等于变量的地址buffer。它只有地址的最低有效 8 位。
  2. 如果存在可以抢占上述代码和/或访问的中断例程或线程,则bufferin 的值bl可能与 5 不同。中断的中断例程在无法保存寄存器值时实际上可能会影响任何寄存器。
于 2012-04-28T10:27:53.810 回答
4

对于使用立即数作为操作数将值写入 ram 位置(或在其中计算)的所有指令,我们必须指定要访问的字节数。因为我们的汇编程序无法知道我们是否只想访问一个字节、一个或一个多字,例如,如果立即值是一个较低的值,如下面的说明所示。

array db 0FFh, 0FFh, 0FFh, 0FFh
mov byte [array], 3

结果:

array db 03h, 0FFh, 0FFh, 0FFh

……

mov word [array], 3

结果:

array db 03h, 00h, 0FFh, 0FFh

……

mov dword [array], 3

结果:

array db 03h, 00h, 00h, 00h

短剑

于 2013-05-05T12:35:21.023 回答