Assembly 在YASM/NASM x86汇编中直接与方括号的基本用法

Assembly 在YASM/NASM x86汇编中直接与方括号的基本用法,assembly,x86,nasm,memory-address,yasm,Assembly,X86,Nasm,Memory Address,Yasm,假设我声明了以下内容: section .bss buffer resb 1 下面是部分的说明。text: mov al, 5 ; mov-immediate mov [buffer], al ; store mov bl, [buffer] ; load mov cl, buffer ; mov-immediate? bl将包含值5,cl将

假设我声明了以下内容:

section .bss
buffer    resb     1
下面是
部分的说明。text

mov    al, 5                    ; mov-immediate
mov    [buffer], al             ; store
mov    bl, [buffer]             ; load
mov    cl, buffer               ; mov-immediate?
bl将包含值5,cl将包含变量
缓冲区的内存地址,我的理解正确吗

我对两者的区别感到困惑

  • 将立即数移到寄存器中
  • 将寄存器移动到立即数(输入的是什么,数据还是地址?)
  • 将立即数移到不带括号的寄存器中
    • 例如,
      mov-cl,buffer
      vs
      mov-cl,[buffer]

更新:在阅读了回复后,我认为以下总结是准确的:

  • mov-edi,array
    将第0个数组索引的内存地址放入
    edi
    。i、 e.标签地址
  • mov byte[edi],3将值3放入数组的第0个索引中
  • 添加edi,3
    之后,
    edi
    现在包含数组第三个索引的内存地址
  • mov al,[array]
    将第0个索引处的数据加载到
    al
  • mov al,[array+3]
    将第三个索引处的数据加载到
    al
  • mov[al],[array]
    无效,因为
    al
    只有8位,即使在16位寻址模式下也无法使用
  • mov数组,3
    无效,因为您不能说“嘿,我不喜欢
    array
    存储的偏移量,所以我将其称为3”。立即数只能是源操作数
  • mov byte[array],3将值3放入数组的第0个索引(第一个字节)。为避免带内存指令的字节/字/dword之间的歧义,请使用立即操作数。否则,这将是一个汇编时间错误(操作数大小不明确)

如果其中任何一项是错误的,请说明。(编者按:我修复了语法错误/歧义,因此有效的语法实际上是有效的NASM语法。并链接了其他Q&a以获取详细信息)

方括号基本上像一个解引用操作符一样工作(例如,像C中的
*

比如

mov REG, x
x
的值移动到
REG
,而

mov REG, [x]
x
指向的内存位置的值移动到
REG
。请注意,如果
x
是一个标签,则其值为该标签的地址

至于你的问题:

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


是的,你说得对。但是请注意,由于
CL
只有8位宽,它将只包含
缓冲区的地址的最低有效字节。实际上,您的想法是正确的。也就是说,bl将包含5,CL是缓冲区的内存地址(实际上,标签缓冲区本身就是一个内存地址)


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

  • 可以使用
    mov reg,imm
    将立即数移动到寄存器中。可能会混淆的是,标签(例如缓冲区)本身就是包含地址的立即数

  • 您无法将寄存器移动到立即数中,因为立即数值是常量,如
    2
    FF1Ah
    。您可以将寄存器移动到常量指向的位置。您可以像
    mov[const],reg
    那样执行此操作

  • 如果reg1指向有效位置,还可以使用间接寻址,如
    mov reg2、[reg1]
    ,它将把reg1指向的值传输到reg2


因此,
mov-cl,buffer
将把buffer的地址移动到cl(这可能给出正确的地址,因为cl只有一个字节长),而
mov-cl,[buffer]
将得到实际值

总结
  • 当您使用[a]时,则指a指向的位置处的值。例如,如果a是
    F5B1
    ,则[a]指RAM中的地址F5B1
  • 标签是地址,即
    F5B1
    之类的值
  • 存储在寄存器中的值不必被引用为[reg],因为寄存器没有地址。事实上,寄存器可以被视为立即值

    • 你已经明白了。但是,有几个细节值得记住:

    • 地址可以并且通常大于8位所能容纳的值(
      cl
      为8位,
      cx
      为16位,
      ecx
      为32位,
      rcx
      为64位)。因此,
      cl
      很可能与变量
      缓冲区的地址不相等。它只有地址的最低有效8位
    • 如果有中断例程或线程可以抢占上述代码和/或访问
      buffer
      ,则
      bl
      中的值可能不同于5。当中断例程无法保留寄存器值时,中断例程实际上可能会影响任何寄存器

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

      array db 0FFh, 0FFh, 0FFh, 0FFh
      mov byte [array], 3
      
      结果:

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

      结果:

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

      结果:

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

      Dirk

      cl
      将只包含地址的8个最低有效位。@Alex:是的,我刚刚意识到:-)当你说“如果x是一个标签,它的值就是该标签的地址”时,这是否意味着如果x的地址是0x1234,那么当它是一个标签时,它的值也是0x1234?@InstructionPointer:在MASM中