`movl(%eax),%eax`中的括号是什么意思?

问题描述 投票:0回答:5

我已经用谷歌搜索了足够多的内容,但无法弄清楚括号

()
的含义。另外,我看到一些语法为
movl 8(%ebp), %eax

有人能给我推荐一些好的参考吗?我在 Google 的前 20 个结果中找不到任何内容。

assembly x86 gnu-assembler att addressing-mode
5个回答
24
投票

%eax
是寄存器EAX;
(%eax)
是地址包含在寄存器EAX中的内存位置;
8(%eax)
是内存位置,其地址是EAX的值加8。


11
投票

http://web.archive.org/web/20080215230650/http://sig9.com/articles/att-syntax 是 Unix (AT&T) asm 语法的快速介绍。谷歌搜索

at&t asm syntax

这篇文章是 vivek 的“AT&T 汇编语法” (http://web.archive.org/web/20080228052132/http://sig9.com/blog/vivek),2003-09-01。其中有关于 AT&T 的主要信息:

例如,INTEL语法中基本数据移动指令的一般格式是,

mnemonic    destination, source

而对于 AT&T,一般格式为

mnemonic    source, destination

(我记得这个命令将 AT&T asm 称为真正的 Unix asm,所以它是right 之一,并且它使数据向右流动;而 Intel 语法基于一些不正确的 masms 文档,这显然不适合 Unix 世界,它们是 left 并且数据流向左侧)

IA-32 架构的所有寄存器名称必须以“%”符号为前缀,例如。 %al、%bx、%ds、%cr0 等

所有文字值必须以“$”符号作为前缀。例如,

mov $100,   %bx
mov $A, %al

第一条指令将值 100 移入寄存器 AX,第二条指令将 ascii A 的数值移入 AL 寄存器。

在 AT&T 语法中,内存是通过以下方式引用的,

segment-override:signed-offset(base,index,scale)

根据您想要的地址,可以省略部分内容。> %es:100(%eax,%ebx,2)

请注意,偏移量和比例不应以“$”为前缀。更多具有等效 NASM 语法的示例应该会让事情变得更清楚,

GAS memory operand      NASM memory operand
------------------      -------------------

100                     [100]
%es:100                 [es:100]
(%eax)                  [eax]
(%eax,%ebx)             [eax+ebx]
(%ecx,%ebx,2)           [ecx+ebx*2]
(,%ebx,2)               [ebx*2]
-10(%eax)               [eax-10]
%ds:-10(%ebp)           [ds:ebp-10]
Example instructions,
mov %ax,    100
mov %eax,   -100(%eax)

操作数大小。有时,特别是在将文字值移动到内存时,有必要指定传输大小或操作数大小。例如指令,

mov    $10,    100

仅指定将值10移动到内存偏移量100,但不指定传输大小。在 NASM 中,这是通过将转换关键字 byte/word/dword 等添加到任何操作数来完成的。在 AT&T 语法中,这是通过在指令中添加后缀 - b/w/l - 来完成的。例如,

movb    $10,    %es:(%eax)

将字节值 10 移动到内存位置 [ea:eax],而,

movl    $10,    %es:(%eax)

将长值(双字)10 移动到同一位置。

jmp、call、ret 等指令将控制从程序的一个部分转移到另一部分。它们可以分为到相同代码段(近)或不同代码段(远)的控制传输。分支寻址的可能类型是 - 相对偏移(标签)、寄存器、内存操作数和段偏移指针。

相对偏移量,使用标签指定,如下所示。

label1:
    .
    .
  jmp   label1

使用寄存器或内存操作数的分支寻址必须以“*”为前缀。要指定“远”控制传输,必须添加“l”前缀,如“ljmp”、“lcall”等。例如,

GAS syntax        NASM syntax
==========        ===========

jmp   *100        jmp  near [100]
call  *100        call near [100]
jmp   *%eax       jmp  near eax
jmp   *%ecx       call near ecx
jmp   *(%eax)     jmp  near [eax]
call  *(%ebx)     call near [ebx]
ljmp  *100        jmp  far  [100]
lcall *100        call far  [100]
ljmp  *(%eax)     jmp  far  [eax]
lcall *(%ebx)     call far  [ebx]
ret               retn
lret              retf
lret $0x100       retf 0x100

段偏移指针使用以下格式指定:

jmp    $segment, $offset

他还推荐 gnu 作为(gas)文档:http://web.archive.org/web/20080313132324/http://sourceware.org/binutils/docs-2.16/as/index.html


4
投票

它们是 move 指令,将数据从一个地方移动到另一个地方 - 在这些情况下,从内存移动到寄存器:

register_eax = *(unsigned long *)register_eax;

你的另一个例子是这样的:

register_eax = *(unsigned long *)(register_ebp + 8);

0
投票

LaC 是对的。 符号()表示寄存器的地址。 %eax 是该地址的值。 所以 'movl 8(%ebp), %eax' 表示将 %eax 设置为 %ebp 的地址。


0
投票

让我说明一下 movq %rax, %rdi 和 movq %rax, (%rdi) 在有无括号方面的区别:

  1. movq %rax, %rdi:该指令将寄存器 %rax 中的值复制到寄存器 %rdi 中。这是纯粹的寄存器到寄存器数据传输操作,不涉及任何内存访问。
  2. movq %rax, (%rdi):另一方面,该指令将寄存器 %rax 中包含的值写入寄存器 %rdi 中保存的地址所指向的内存位置。 %rdi 寄存器通常用于在函数调用期间传递第一个整数或指针参数,或用作内存操作中的基址寄存器。在这种情况下,( %rdi ) 表示基于 %rdi 内容的内存地址,因此该指令将 %rax 的内容存储到内存中。

总而言之,第一条指令在寄存器之间执行数据复制,而第二条指令将数据从寄存器传输到内存。

© www.soinside.com 2019 - 2024. All rights reserved.