用于打印到标准输出的 `mov edx, Len` 是否将“Len”的值或地址存储到寄存器中?

mer*_*114 1 x86 assembly nasm cpu-registers

我是汇编编程(x86 32 位架构)的新手,对以下代码有疑问:

SECTION .data

Msg: db "Hello", 10
Len: equ $-Msg

SECTION .text

global _start

_start:
    ; Printing Msg to stdout
    mov eax, 4
    mov ebx, 1
    mov ecx, Msg  ; Passing the ADDRESS to the beginning of what's stored in Msg
    mov edx, Len  ; Are we passing the address of Len, or the value of Len?
    int 80H

    ; Terminating
    mov eax, 1
    mov ebx, 0
    int 80H
Run Code Online (Sandbox Code Playgroud)

有人告诉我,mov ecx, Msg指令将Msg存储位置的地址移动到ecx寄存器中。

下一条指令 mov edx, Len呢?

  • 如果我们将Len值移动到edx寄存器,那么指令不应该以不同的方式编写,例如mov edx, [Len]

  • 如果我们移动地址,Len那么为什么打印消息的系统调用如此复杂?为什么需要一个寄存器来包含消息长度的地址而不是实际长度值?

Nat*_*dge 5

Len没有地址。定义为 的标签equ只是使名称Len成为引用特定数值的便捷方式,在这种情况下,该数值由汇编器计算,恰好是 6。它不会在内存中分配任何空间。并且mov edx, Len是将数值 6 放入edx寄存器的立即加载。

从某种意义上说,Msg也是一种引用特定数值的便捷方式——但这里的数值恰好是内存中包含字节“Hello”的某个位置的地址。所以mov ecx, Msg也立即载荷这使该数值为ecx

如果你愿意,你可以把它Msg: db "Hello", 10看作是

Msg: equ $
    db "Hello", 10
Run Code Online (Sandbox Code Playgroud)

它将标签设置为Msg等于汇编器的当前地址,然后从当前地址开始组装一些字节。

(请注意,此答案特定于 nasm。其他 Intel 语法汇编程序通常类似;但例如,在 AT&T 语法中,指令movl Len, %edx是从内存中移动,相当于 Intel 的mov edx, [Len];它会尝试从地址 6 获取四个字节, 这会崩溃。在这种语法中,您将改为编写movl $Len, %edx.)

  • 术语:“[disp32]”寻址模式通常称为“直接”(或绝对),因为地址实际上存在于指令编码中。间接是“[reg]”。但是,是的,它是从内存加载而不是立即移动。x86 没有为其完整寻址模式功能的不同子集提供特定名称(“[base + idx*scale + disp0/8/32]”),但有些人喜欢命名事物。[Intel x86 手册中是否实际存在直接/间接寻址模式等术语](/sf/ask/3237991291/) (2认同)
  • @ecm:好点,尽管对于气体来说,在该示例中它是可选的,因为操作数大小可以从寄存器名称中推断出来。无论如何我改变了它。 (2认同)