常见汇编代码及其指定

1. 数据传输指令

1.1. mov

  • 作用:将数据从源操作数复制到目标操作数。

  • 语法mov dest, src

    mov eax, 10 ; 将立即数 10 存入 eax 寄存器
    mov ebx, eax ; 将 eax 的值复制到 ebx
    mov [ecx], eax ; 将 eax 的值写入 ecx 指向的内存地址

1.2. lea

  • 作用:计算内存地址的偏移量并存入寄存器(不访问内存)。

  • 语法lea dest, [address]

    lea eax, [ebx + 8] ; 将 ebx + 8 的地址存入 eax(不读取内存内容)

2. 栈操作指令

2.1. push

  • 作用 :将操作数压入栈顶,栈指针(esp/rsp)减小。
  • 语法push src

底层行为

复制代码
sub esp, 4        ; x86: 栈指针下移 4 字节(32位)
mov [esp], src    ; 将数据写入新的栈顶

示例:

复制代码
push eax          ; 将 eax 的值压入栈
push 0xdeadbeef   ; 将立即数压入栈

2.2. pop

  • 作用 :将栈顶数据弹出到目标操作数,栈指针(esp/rsp)增大。
  • 语法pop dest

底层行为:

复制代码
mov dest, [esp]   ; 从栈顶读取数据
add esp, 4        ; x86: 栈指针上移 4 字节(32位)

示例:

复制代码
pop ebx           ; 弹出栈顶数据到 ebx

3. 算数运行指令

3.1. add

  • 作用:将目标操作数与源操作数相加,结果存入目标。
  • 语法add dest, src

示例:

复制代码
add eax, ebx      ; eax = eax + ebx
add dword [ecx], 5; 将 ecx 指向的内存值加 5

3.2. sub

  • 作用:目标操作数减去源操作数,结果存入目标。
  • 语法sub dest, src

示例:

复制代码
sub eax, 10       ; eax = eax - 10

3.3. inc/dec

  • 作用 :对操作数加 1(inc)或减 1(dec)。

示例:

复制代码
inc ecx           ; ecx += 1
dec dword [edx]   ; 将 edx 指向的内存值减 1

4. 控制流指令

4.1. jmp

  • 作用:无条件跳转到指定地址。
  • 语法jmp target

示例

复制代码
jmp 0x8048000     ; 跳转到绝对地址 0x8048000
jmp eax           ; 跳转到 eax 寄存器中的地址

4.2. call

作用:调用函数(保存返回地址并跳转)。

底层行为

复制代码
push eip + 5      ; 将下一条指令地址压入栈(返回地址)
jmp target        ; 跳转到目标函数

示例

复制代码
call 0x8048123    ; 调用位于 0x8048123 的函数

4.3. ret

  • 作用:从函数返回(弹出返回地址并跳转)。

底层行为

复制代码
pop eip           ; 将栈顶的返回地址存入 eip(程序计数器)

示例

复制代码
ret               ; 返回到调用者

5. 比较与条件跳转

5.1. cmp

  • 作用 :比较两个操作数(目标 - 源),结果影响标志寄存器(EFLAGS)。
  • 语法cmp dest, src

示例

复制代码
cmp eax, ebx      ; 比较 eax 和 ebx 的值

5.2. test

  • 作用:对两个操作数进行按位与(AND)操作,结果影响标志寄存器。
  • 语法test dest, src

示例

复制代码
test eax, eax     ; 检查 eax 是否为 0

5.3. 条件跳转指令

  • 作用:根据标志寄存器状态跳转(如相等、大于等)。
  • 常见指令
    • je / jz:等于/零时跳转。
    • jne / jnz:不等于/非零时跳转。
    • jg:有符号数大于时跳转。
    • jl:有符号数小于时跳转。
    • ja:无符号数大于时跳转。

示例

复制代码
cmp eax, 5
je  label         ; 若 eax == 5,跳转到 label

6. 函数调用与栈帧

6.1. 函数序言(Prologue)

  • 作用:保存调用者的栈帧并建立新栈帧。

典型代码

复制代码
push ebp          ; 保存旧的基址指针
mov  ebp, esp     ; 设置新的基址指针(当前栈顶)
sub  esp, 0x20    ; 为局部变量分配栈空间

6.2. 函数尾声(Epilogue)

  • 作用:恢复调用者的栈帧并返回。

典型代码

复制代码
mov  esp, ebp     ; 释放局部变量空间
pop  ebp          ; 恢复旧的基址指针
ret               ; 返回到调用者

7. 实际应用场景

请看以下代码,简单的输出"Hello word"。

复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    puts("hello world");
    exit(0);
}

对其生成的的汇编代码如下,详细介绍如下:

复制代码
	.section	__TEXT,__text,regular,pure_instructions  
	.macosx_version_min 10, 12
	.globl	_main
	.p2align	4, 0x90
_main:                                  ## @main
## BB#0:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
	calll	L0$pb
L0$pb:
	popl	%eax
	leal	L_str-L0$pb(%eax), %eax
	movl	%eax, (%esp)
	calll	_puts
	movl	$0, (%esp)
	calll	_exit
	subl	$4, %esp
 
	.section	__TEXT,__cstring,cstring_literals
L_str:                                  ## @str
	.asciz	"hello world"
 
 
.subsections_via_symbols

段定义与平台声明:

复制代码
.section	__TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
  • .section __TEXT,__text:定义代码段(__TEXT 段中的 __text 节),用于存放可执行代码。
  • .macosx_version_min 10,12:声明目标 macOS 最低版本为 10.12。
  • regular,pure_instructions:指定节属性(常规代码,纯指令)。

主函数入口:

复制代码
.globl	_main
.p2align	4, 0x90
_main:
## BB#0:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
  • .globl _main:声明 _main 为全局符号(程序入口)。
  • .p2align 4, 0x90:对齐指令(16字节对齐,填充 0x90(NOP))。
  • 函数序言
    • pushl %ebp:保存旧的基址指针(栈帧基址)。
    • movl %esp, %ebp:建立新的栈帧(ebp 指向当前栈顶)。
    • subl $8, %esp:在栈上分配 8 字节空间(可能用于后续函数调用参数)。

获取字符串地址:

复制代码
	calll	L0$pb
L0$pb:
	popl	%eax
	leal	L_str-L0$pb(%eax), %eax
  • calll L0pb**:调用下一条指令 **L0pb(实质是获取当前指令地址)。
    • call 会将下一条指令地址(即 L0$pb 的地址)压入栈。
  • popl %eax:弹出返回地址(即 L0$pb 的地址)到 eax 寄存器。
  • leal L_str-L0$pb(%eax), %eax
    • 计算 L_str 相对于 L0pb** 的偏移量,加上 **eax**(即 **L0pb 的实际地址),得到 L_str 的绝对地址。
    • 这是 macOS 中实现 位置无关代码(PIC) 的常见手法,用于获取数据地址。

调用puts输出字符串:

复制代码
	movl	%eax, (%esp)
	calll	_puts
  • movl %eax, (%esp):将字符串地址(eax)作为参数传递给 puts
  • calll _puts:调用标准库函数 puts,输出字符串 "hello word"

调用exit终止程序:

复制代码
	movl	$0, (%esp)
	calll	_exit
	subl	$4, %esp
  • movl $0, (%esp):将退出码 0 作为参数传递给 exit
  • calll _exit:调用 exit 终止程序(而非 return 0,直接退出不返回到调用者)。
  • subl $4, %esp:可能是调整栈指针的冗余操作(实际无意义,可能是编译器生成的冗余指令)。

字符串常量定义:

复制代码
.section	__TEXT,__cstring,cstring_literals
L_str:
	.asciz	"hello world"
  • .section __TEXT,__cstring:定义只读字符串段。
  • L_str:标签指向字符串 "hello world"
  • .asciz:定义以 \0 结尾的 ASCII 字符串。

子节生成控制器:

复制代码
.subsections_via_symbols
  • 汇编器指令:告知链接器通过符号生成子节(用于优化可执行文件体积)。
相关推荐
姚远Oracle ACE19 分钟前
解读Oracle AWR报告:Global Cache and Enqueue Services - Workload Characteristics
数据库·oracle
凤山老林20 分钟前
新一代Java应用日志可视化与监控系统开源啦
java·后端·开源
流星白龙20 分钟前
【Qt】7.信号和槽_connect函数用法(2)
java·数据库·qt
Zzz 小生2 小时前
Claude Code学习笔记(四)-助你快速搭建首个Python项目
大数据·数据库·elasticsearch
黎宇幻生4 小时前
Java全栈学习笔记39
java·笔记·学习
Aurorar0rua5 小时前
C Primer Plus Notes 09
java·c语言·算法
胡耀超5 小时前
隐私计算技术全景:从联邦学习到可信执行环境的实战指南—数据安全——隐私计算 联邦学习 多方安全计算 可信执行环境 差分隐私
人工智能·安全·数据安全·tee·联邦学习·差分隐私·隐私计算
nongcunqq6 小时前
abap 操作 excel
java·数据库·excel
rain bye bye6 小时前
calibre LVS 跑不起来 就将setup 的LVS Option connect下的 connect all nets by name 打开。
服务器·数据库·lvs
史迪奇_xxx7 小时前
10、一个简易 vector:C++ 模板与 STL
java·开发语言·c++