01_基础理论
汇编
AT汇编和Intel汇编通常指的是用于编写x86架构处理器汇编语言的两种不同的语法风格。
AT&T汇编语法:
AT&T语法起源于Unix系统的汇编器,它的标志之一是操作数的顺序:源操作数在左,目标操作数在右。
操作数大小由操作码的后缀指明,例如
movl
表示移动一个长整数(32位)。内存操作数的表示方式是在括号内,例如
movl $1, (%eax)
。引用寄存器时,需要在寄存器名前加上百分比符号(%)。
立即数(Immediate values)前面加上美元符号($)。
示例(AT&T语法):
movl $1, %eax ; 将立即数1放入eax寄存器
movl %ebx, %eax ; 将ebx寄存器的值移动到eax寄存器
Intel汇编语法:
Intel语法是Intel公司自己使用的语法,它的操作数顺序与高级语言类似:目标操作数在左,源操作数在右。
操作数大小通常不需要在操作码中指明,因为它可以从操作数中推断出来。
内存操作数不需要括号。
引用寄存器时,不需要在寄存器名前加任何特殊符号。
立即数前可以不加符号,也可以加上不同的符号(如
$
),但通常省略。 示例(Intel语法):
mov eax, 1 ; 将立即数1放入eax寄存器
mov eax, ebx ; 将ebx寄存器的值移动到eax寄存器
两种语法都有其特定的用途和偏好者。AT&T语法因为历史原因在Unix和Linux系统中较为常见,而Intel语法因其直观性在Windows平台上更为普遍。不同的汇编器和开发环境支持不同的语法风格,例如GNU汇编器(gas)默认使用AT&T语法,而Microsoft的MASM和NASM汇编器则使用Intel语法。开发者可以根据自己的需求和习惯选择合适的语法风格。
底下是32位X86架构下的一些基础汇编指令:
mov:数据传输指令,格式为MOV DST,SRC;
push:压入堆栈指令,格式为PUSH SRC;
pop:弹出堆栈指令,格式为POP DST;
lea:取地址指令,格式为LEA REG,MEM;
call:调用指令,格式为CALL PTR。
leave:管理函数栈帧的便捷指令:
实际上执行了下面两个操作
mov esp, ebp
:将栈指针(ESP)的值设置为基指针(EBP)的值。这相当于撤销了在函数开始时设置的栈帧。pop ebp
:从堆栈中弹出之前保存的基指针(EBP)的值,恢复调用函数的基指针。 下面是leave
指令的详细作用:
它通常用于函数的末尾,作为函数清理和返回的一部分。
在函数开始时,通常使用
push ebp
和mov ebp, esp
来创建一个新的栈帧。leave
指令则是这些操作的反向操作。leave
指令相当于以下两条指令的组合:
mov esp, ebp ; 恢复栈指针
pop ebp ; 恢复旧的基指针
使用
leave
指令可以简化函数的结尾清理代码,使得汇编代码更加清晰。 这里是一个使用leave
指令的简单例子:
func:
push ebp ; 保存旧的基指针
mov ebp, esp ; 设置新的基指针
sub esp, 4 ; 为局部变量分配空间
; ... 函数体 ...
leave ; 清理栈帧
ret ; 返回到调用者
在这个例子中,leave
指令在函数执行完毕后调用,用于恢复栈帧,然后 ret
指令用于从函数返回。
栈结构可以去看07_C基础(回车换行、栈结构与函数调用) - Kiciot's Space