我已经用谷歌搜索了足够多的内容,但无法弄清楚括号
()
的含义。另外,我看到一些语法为 movl 8(%ebp), %eax
有人能给我推荐一些好的参考吗?我在 Google 的前 20 个结果中找不到任何内容。
%eax
是寄存器EAX; (%eax)
是地址包含在寄存器EAX中的内存位置; 8(%eax)
是内存位置,其地址是EAX的值加8。
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
它们是 move 指令,将数据从一个地方移动到另一个地方 - 在这些情况下,从内存移动到寄存器:
register_eax = *(unsigned long *)register_eax;
你的另一个例子是这样的:
register_eax = *(unsigned long *)(register_ebp + 8);
LaC 是对的。 符号()表示寄存器的地址。 %eax 是该地址的值。 所以 'movl 8(%ebp), %eax' 表示将 %eax 设置为 %ebp 的地址。
让我说明一下 movq %rax, %rdi 和 movq %rax, (%rdi) 在有无括号方面的区别:
总而言之,第一条指令在寄存器之间执行数据复制,而第二条指令将数据从寄存器传输到内存。