对于X86_64 linux的程序集中标签的使用感到困惑:我们为什么要编写mov [digit],al,而不是mov digit,al?

李亮節*_*李亮節 1 linux x86 assembly nasm

这是我的代码:

section .data
    digit db 0,10

section .text
    global  _start
_start:

    call _printRAXDigit

    mov rax, 60
    mov rdx, 0
    syscall


_printRAXDigit:
    add rax, 48
    mov [digit], al

    mov rax, 1
    mov rdi, 1
    mov rsi, digit
    mov rdx, 2
    syscall
    ret
Run Code Online (Sandbox Code Playgroud)

我有一个关于之间的差异问题[digit]digit.

我已经知道标签(如代码中的数字)代表数据的内存地址,而运算符"[]"就像取消引用指针一样,因此它会将标签指向的值加载到目标.

例如,mov rax, [digit] 将0抛出到rax寄存器,因为数字指向数据的第一个元素(在本例中为整数0).

但是,在我的代码中,它在我写入时起作用mov [digit], al,这意味着"将存储的值加载al到内存地址数字 ",但我不知道为什么在这种情况下我们应该使用"[]".第一个参数mov必须是目的地(如寄存器或内存地址),所以我认为它应该是mov digit, al而不是mov [digit], al.对我来说,为什么我们使用一个值从另一个地方获取值而不是使用内存地址来获取值是没有意义的.

这就是我的全部问题.请给我任何关于我的想法错误或对我的标签概念的任何更正的回应.

Mar*_*nau 5

在NASM语法中(有使用不同符号的汇编程序,例如MASM/TASM使用不同风格的Intel语法,而gas使用AT&T语法)以下x86指令......

mov esi, someAddress
mov esi, [someAddress]
mov [someAddress], esi
mov someAddress, esi   ; see below
Run Code Online (Sandbox Code Playgroud)

......(会)具有以下含义:

mov esi, someAddress
Run Code Online (Sandbox Code Playgroud)

将表示someAddress存储地址的数字写入寄存器esi.因此,如果someAddress存储在地址1234处,则写入值1234 esi.

mov esi, [someAddress]
Run Code Online (Sandbox Code Playgroud)

写入内存的内容esi.因此,如果someAddress存储在地址1234处并且存储在地址1234处的值是5678,则写入值5678 esi.

您可能还会说:变量的值someAddress(变量通常只是某个地址的内存内容)被写入esi寄存器.

mov [someAddress], esi
Run Code Online (Sandbox Code Playgroud)

将内容写入esi地址的内存someAddress.

您可能还会说:将值写入esi变量someAddress.

mov someAddress, esi
Run Code Online (Sandbox Code Playgroud)

意味着:更改常数代表地址someAddressesi.

因此,如果someAddress位于地址1234并esi包含值5678,则指令将表示:

在该变化之后以1234 = 5678的方式改变数学常数1234.

这当然是愚蠢的,因为数学常数1234和5678永远不会相等.因此x86 CPU没有这样的指令.

(有些CPU具有类似的指令.在SPARC CPU上,例如,为零寄存器分配值的指令(这意味着:"为常量零赋值")如果你只想要指令的副作用,就会被使用 - 比如说设置标志 - 但你对结果本身不感兴趣.)