2017-10-21 58 views
1

这里是我的代码:对于X86_64 linux组装中标签的使用感到困惑:为什么我们应该写mov [digit],al,而不是mov digit,al?

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 

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

我已经了解到,标签(如代码中的数字)表示数据的内存地址,操作符“[]”的作用就像取消引用指针的东西,因此它会加载值标签指向目的地。

例如,mov rax, [digit]将在数据的第一个元素扔0到rax寄存器,因为数字点(在此情况下,整数0)。

然而,在我的代码,它工作时,我写mov [digit], al,这意味着“加载存储在al到内存地址价值”,但我不知道为什么我们要在此用“[]”案件。 mov的第一个参数必须是目的地(如寄存器或内存地址),所以我认为它应该是mov digit, al而不是mov [digit], al。对于我来说,为什么我们使用一个值从另一个地方获取值,而不是使用内存地址来获取值。

这就是我所有的问题。请给我任何回应,关于我的思维错误或对标签概念的任何更正。

+0

'digit' *是*地址。但它也是一个数字。你需要告诉汇编器如何解释它。 –

+0

你是什么意思,“数字是一个地址,但它也是一个数字。”,你可以给任何具体的例子,以便我可以更多地了解,谢谢 –

+0

0是一个地址。这是一个数字。 3是地址。这是一个数字。 27是地址。这是一个数字。 252是地址。这是一个数字。 –

回答

5

在NASM语法(有装配使用不同的符号,如MASM/TASM use a different flavor of Intel syntax和气体使用AT&T syntax)以下的x86指令......

mov esi, someAddress 
mov esi, [someAddress] 
mov [someAddress], esi 
mov someAddress, esi ; see below 

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

mov esi, someAddress 

将表示存储someAddress的地址的数字写入寄存器esi。所以如果someAddress存储在地址1234处,则值1234被写入esi

mov esi, [someAddress] 

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

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

mov [someAddress], esi 

写的esi到内存地址someAddress内容。

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

mov someAddress, esi 

平均:更改常数代表地址someAddressesi

所以,如果someAddress位于地址1234和esi包含值5678的指令将意味着:

变化的数学常数1234的方式,1234 = 5678之后的变化。

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

(有些CPU有类似的指令,例如在SPARC CPU上指令给零寄存器赋值(也就是说:“给常数零赋一个值”),如果你只想使用指令副作用 - 例如设置标志 - 但您对结果本身不感兴趣。)

+1

你称之为“正常”的理性语法是NASM风格。 'mov esi,[digit]'和'mov esi,digit'都是加载和'mov esi,offset digit'的mov-immediate是MASM/TASM风格。 [MASM甚至在'mov eax中忽略括号,[constant]为'='常量(如equ)!](https://stackoverflow.com/a/25130189/224132)。显然有些人认为这是正常的,所以你可能需要澄清。 (我根据Linux标签和问题中的文字标记了问题'[nasm]',描述了一些事情做了什么) –

+0

@PeterCordes我使用了“normal”这个词,因为我通常使用AT&T风格的汇编器('movl $ someAddress ,%esi')。我并不知道NASM和MASM之间是有区别的。 –

+0

啊,那么你要找的术语是“英特尔语法”。 NASM和MASM都是英特尔语法的风格。我最近用一些关于NASM和MASM语法的东西更新了[intel-syntax tag wiki](https://stackoverflow.com/tags/intel-syntax/info)。请注意,GAS'.intel_syntax noprefix'类似于MASM,不像NASM。 (例如'mov eax,symbol'是一个负载。) –