汇编

AT汇编和Intel汇编通常指的是用于编写x86架构处理器汇编语言的两种不同的语法风格。

  1. AT&T汇编语法

  • AT&T语法起源于Unix系统的汇编器,它的标志之一是操作数的顺序:源操作数在左,目标操作数在右。

  • 操作数大小由操作码的后缀指明,例如movl表示移动一个长整数(32位)。

  • 内存操作数的表示方式是在括号内,例如movl $1, (%eax)

  • 引用寄存器时,需要在寄存器名前加上百分比符号(%)。

  • 立即数(Immediate values)前面加上美元符号($)。

    示例(AT&T语法):

movl $1, %eax  ; 将立即数1放入eax寄存器
movl %ebx, %eax ; 将ebx寄存器的值移动到eax寄存器
  1. 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架构下的一些基础汇编指令:

  1. mov:数据传输指令,格式为MOV DST,SRC;

  2. push:压入堆栈指令,格式为PUSH SRC;

  3. pop:弹出堆栈指令,格式为POP DST;

  4. lea:取地址指令,格式为LEA REG,MEM;

  5. call:调用指令,格式为CALL PTR。

  6. leave:管理函数栈帧的便捷指令:

实际上执行了下面两个操作

  1. mov esp, ebp:将栈指针(ESP)的值设置为基指针(EBP)的值。这相当于撤销了在函数开始时设置的栈帧。

  2. pop ebp:从堆栈中弹出之前保存的基指针(EBP)的值,恢复调用函数的基指针。 下面是 leave 指令的详细作用:

  • 它通常用于函数的末尾,作为函数清理和返回的一部分。

  • 在函数开始时,通常使用 push ebpmov 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