我尝试用GCC -S选项将C语言代码转换和解释为汇编语言。push %rbp和push rbp的区别是什么?
push %rbp
push rbp
efzxgjgh1#
你给出的两个语句做的是同样的事情,主要的区别在于语法。X86有两种主要的语法约定,Intel约定和AT&T约定。有关详细信息,请参见语法比较。
**[UPD:]**以防万一,这里重复语法信息:
| | 美国电话电报公司|英特尔|| - -----|- -----|- -----||参数顺序| 源在目的地之前。movl $5, %eax|目标在源之前。mov eax, 5||参数大小| 助记符的后缀是一个字母,表示操作数的大小:q表示qword,l表示long(dword),w表示word,B表示byte。addl $4, %esp|从使用的寄存器名称派生(例如:rax、eax、ax、al分别暗示q、l、w、B)。add esp, 4|| Sigils| Immediate values前缀为**$,寄存器前缀为%。|汇编程序自动检测符号的类型;即它们是寄存器、常量还是其它。||有效地址| DISP(BASE,INDEX,SCALE)的一般语法。movl mem_addr(%ebx,%ecx,4), %eax|方括号中的算术表达式;另外,如果不能从操作数确定大小,则必须使用大小关键字,如byte**、word或dword。mov eax, [ebx + ecx*4 + mem_addr]|
movl $5, %eax
mov eax, 5
addl $4, %esp
add esp, 4
movl mem_addr(%ebx,%ecx,4), %eax
mov eax, [ebx + ecx*4 + mem_addr]
5lwkijsr2#
在AT&T语法中,push rbp将是一个内存操作数的推送,符号名为rbp,就像你编译了一些使用long rbp;作为全局变量的C代码一样。rbp没有%,所以汇编器知道你没有引用同名的寄存器;这就是AT&T语法消除这种情况歧义的方法。如果你确实需要寄存器,你 * 必须 * 像%rbp一样使用%。
rbp
long rbp;
%
%rbp
rbp是绝对寻址模式;通常你会使用pushq rbp(%rip),如果你真的想推一个全局的内容。具有任何其他寻址模式的推式存储器看起来像pushq (%rdi, %rsi, 8)。在32位代码中,通常使用纯符号名访问全局变量,如mov foo, %eax从一个变量加载。但更有可能的是,你指的push rbp是push %rbp的英特尔语法版本,像普通人一样推动寄存器。
pushq rbp(%rip)
pushq (%rdi, %rsi, 8)
mov foo, %eax
gcc -masm=intel将使用Intel语法,默认为-masm=att。挑你觉得容易读的。参见How to remove "noise" from GCC/clang assembly output?
gcc -masm=intel
-masm=att
有关语法差异的更多详细信息,请参阅@hidefromkgb的答案,以及:
2条答案
按热度按时间efzxgjgh1#
你给出的两个语句做的是同样的事情,主要的区别在于语法。
X86有两种主要的语法约定,Intel约定和AT&T约定。
有关详细信息,请参见语法比较。
**[UPD:]**以防万一,这里重复语法信息:
| | 美国电话电报公司|英特尔|
| - -----|- -----|- -----|
|参数顺序| 源在目的地之前。
movl $5, %eax
|目标在源之前。mov eax, 5
||参数大小| 助记符的后缀是一个字母,表示操作数的大小:q表示qword,l表示long(dword),w表示word,B表示byte。
addl $4, %esp
|从使用的寄存器名称派生(例如:rax、eax、ax、al分别暗示q、l、w、B)。add esp, 4
|| Sigils| Immediate values前缀为**$,寄存器前缀为%。|汇编程序自动检测符号的类型;即它们是寄存器、常量还是其它。|
|有效地址| DISP(BASE,INDEX,SCALE)的一般语法。
movl mem_addr(%ebx,%ecx,4), %eax
|方括号中的算术表达式;另外,如果不能从操作数确定大小,则必须使用大小关键字,如byte**、word或dword。mov eax, [ebx + ecx*4 + mem_addr]
|5lwkijsr2#
在AT&T语法中,
push rbp
将是一个内存操作数的推送,符号名为rbp
,就像你编译了一些使用long rbp;
作为全局变量的C代码一样。rbp
没有%
,所以汇编器知道你没有引用同名的寄存器;这就是AT&T语法消除这种情况歧义的方法。如果你确实需要寄存器,你 * 必须 * 像%rbp
一样使用%
。rbp
是绝对寻址模式;通常你会使用pushq rbp(%rip)
,如果你真的想推一个全局的内容。具有任何其他寻址模式的推式存储器看起来像pushq (%rdi, %rsi, 8)
。在32位代码中,通常使用纯符号名访问全局变量,如mov foo, %eax
从一个变量加载。但更有可能的是,你指的
push rbp
是push %rbp
的英特尔语法版本,像普通人一样推动寄存器。gcc -masm=intel
将使用Intel语法,默认为-masm=att
。挑你觉得容易读的。参见How to remove "noise" from GCC/clang assembly output?有关语法差异的更多详细信息,请参阅@hidefromkgb的答案,以及: