尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

x86 汇编语言指令大全(附详细案例)

x86 汇编语言指令大全(附详细案例) 第一部分基础知识回顾寄存器x86 32位通用寄存器32位/16位/8位 EAX - AX - AH/AL ; 累加器 EBX - BX - BH/BL ; 基址 ECX - CX - CH/CL ; 计数器 EDX - DX - DH/DL ; 数据 ESI, EDI ; 源/目的变址 EBP ; 基址指针栈帧 ESP ; 栈顶指针 EIP ; 指令指针 段寄存器CS, DS, SS, ES, FS, GS 标志寄存器EFLAGSZF, CF, SF, OF, PF, AF第二部分数据传送指令1. MOV — 数据传送语法MOV 目的, 源规则两个操作数大小必须相同不能内存到内存直接传送不能立即数到段寄存器案例1基本传送MOV EAX, 100 ; EAX 100立即数→寄存器 MOV EBX, EAX ; EBX EAX寄存器→寄存器 MOV [ESI], EAX ; [ESI] EAX寄存器→内存 MOV EAX, [ESI] ; EAX [ESI]内存→寄存器案例2错误示例MOV [ESI], [EDI] ; ❌ 错误不能内存到内存 MOV EAX, BL ; ❌ 错误大小不匹配 MOV DS, 1000 ; ❌ 错误立即数不能给段寄存器 ; 正确做法 MOV EAX, [EDI] MOV [ESI], EAX ; 用寄存器中转案例3不同寻址方式MOV EAX, [1000h] ; 直接寻址 MOV EAX, [EBX] ; 寄存器间接 MOV EAX, [EBX4] ; 基址偏移 MOV EAX, [EBXESI] ; 基址变址 MOV EAX, [EBXESI*4] ; 基址变址*比例 MOV EAX, [EBXESI*48] ; 完整寻址2. XCHG — 交换数据案例交换两个变量MOV EAX, 10 MOV EBX, 20 XCHG EAX, EBX ; 交换后EAX20, EBX10 ; 相当于经典的临时变量交换但只需一条指令3. PUSH / POP — 栈操作原理PUSHESP先减4再把数据放到[ESP]POP把[ESP]取出ESP再加4案例1保存和恢复PUSH EAX ; 保存EAX PUSH EBX ; 保存EBX ; 中间可以随意使用EAX、EBX MOV EAX, 100 MOV EBX, 200 POP EBX ; 恢复EBX注意顺序后进先出 POP EAX ; 恢复EAX案例2函数调用参数传递; 调用 Add(3, 5) PUSH 5 ; 参数从右往左压栈cdecl PUSH 3 CALL Add ADD ESP, 8 ; 清理栈2个参数×4字节案例3栈交换技巧; 用栈交换EAX和EBX不用XCHG PUSH EAX PUSH EBX POP EAX ; EAX得到原EBX POP EBX ; EBX得到原EAX4. LEA — 加载有效地址用途计算地址不访问内存、快速运算案例1获取地址LEA EAX, [EBX8] ; EAX EBX8只算地址不取值 MOV EAX, [EBX8] ; EAX 内存中[EBX8]的值对比案例2巧妙用作快速计算; 计算 EAX EBX*5 3 LEA EAX, [EBX EBX*4 3] ; 一条指令搞定 ; 计算 EAX ECX*3 LEA EAX, [ECX ECX*2] ; ECX ECX*2 ECX*3第三部分算术运算指令5. ADD / SUB — 加减法案例1基本使用MOV EAX, 10 ADD EAX, 5 ; EAX 15 SUB EAX, 3 ; EAX 12 ADD EAX, EBX ; EAX EAX EBX ADD [ESI], EAX ; 内存中的值EAX案例2影响标志位MOV EAX, 0FFFFFFFFh ADD EAX, 1 ; EAX0, CF1进位, ZF1结果为零 MOV EAX, 5 SUB EAX, 10 ; EAX-5, SF1负号6. INC / DEC — 自增自减MOV EAX, 10 INC EAX ; EAX 11 DEC EAX ; EAX 10 ; 与ADD/SUB的区别INC/DEC不影响CF标志案例循环计数MOV ECX, 10 loop_start: ; ... 做一些事 DEC ECX JNZ loop_start ; 不为零则跳转7. MUL / IMUL — 乘法MUL无符号乘法IMUL有符号乘法案例1单操作数乘法; 8位乘法AL * 操作数 - AX MOV AL, 10 MOV BL, 20 MUL BL ; AX AL * BL 200 ; 32位乘法EAX * 操作数 - EDX:EAX MOV EAX, 100000 MOV EBX, 100000 MUL EBX ; EDX:EAX 100亿超32位高位在EDX案例2IMUL的多种形式IMUL EBX ; EDX:EAX EAX * EBX IMUL EAX, EBX ; EAX EAX * EBX截断到32位 IMUL EAX, EBX, 10 ; EAX EBX * 10常用8. DIV / IDIV — 除法规则被除数是隐含的AX / DX:AX / EDX:EAX案例132位除法; 计算 100 / 7 MOV EAX, 100 ; 被除数低32位 MOV EDX, 0 ; 被除数高32位清零很重要 MOV EBX, 7 DIV EBX ; EAX14商, EDX2余数案例2有符号除法MOV EAX, -100 CDQ ; 符号扩展到EDX-100→EDX全1 MOV EBX, 7 IDIV EBX ; EAX-14, EDX-2⚠️ 陷阱; 忘记清零EDX会导致除法出错 MOV EAX, 100 ; EDX有残留值 DIV EBX ; 可能溢出异常9. NEG — 取负MOV EAX, 10 NEG EAX ; EAX -10 MOV EAX, -5 NEG EAX ; EAX 510. CMP — 比较原理执行减法但不保存结果只影响标志位案例条件判断MOV EAX, 10 CMP EAX, 5 ; 计算10-55标志位ZF0, SF0, CF0 JG greater ; 大于则跳转有符号 CMP EAX, EBX ; 比较EAX和EBX JE equal ; 相等跳转 JL less ; 小于跳转 JG greater ; 大于跳转第四部分逻辑运算指令11. AND — 逻辑与案例1清零特定位MOV EAX, 0FFh ; 11111111 AND EAX, 0F0h ; 11110000 - EAX F0h清零低4位案例2判断奇偶MOV EAX, 17 AND EAX, 1 ; 最低位1奇数 JZ even ; 结果为0则偶数12. OR — 逻辑或案例置位MOV EAX, 0F0h OR EAX, 0Fh ; EAX FFh低4位置1 ; 常用设置某个标志位 OR EAX, 00000100b ; 设置第2位13. XOR — 逻辑异或案例1清零最常见用法XOR EAX, EAX ; EAX 0比MOV EAX, 0更短更快案例2交换不用临时变量MOV EAX, 5 MOV EBX, 10 XOR EAX, EBX XOR EBX, EAX XOR EAX, EBX ; 现在EAX10, EBX5案例3翻转特定位MOV EAX, 0FFh XOR EAX, 0Fh ; EAX F0h翻转低4位14. NOT — 逻辑非MOV EAX, 0FFh NOT EAX ; EAX FFFFFF00h所有位取反15. TEST — 测试原理执行AND但不保存结果案例检测某位TEST EAX, EAX ; 检测EAX是否为0常用 JZ is_zero ; EAX0则跳转 TEST EAX, 1 ; 检测最低位 JNZ odd ; 最低位1则跳转奇数第五部分移位指令16. SHL / SHR — 逻辑移位案例1快速乘除2的幂MOV EAX, 10 SHL EAX, 1 ; EAX 20左移1位×2 SHL EAX, 3 ; EAX 160左移3位×8 MOV EAX, 100 SHR EAX, 2 ; EAX 25右移2位÷4案例2移位可视化初始: 00000000 00000000 00000000 00001010 (10) SHL 1: 00000000 00000000 00000000 00010100 (20) SHL 1: 00000000 00000000 00000000 00101000 (40)17. SAR — 算术右移保留符号MOV EAX, -8 ; FFFFFFF8h SAR EAX, 1 ; EAX -4保持负数 SHR EAX, 1 ; ❌ 如果用SHR会变成正数大值18. ROL / ROR — 循环移位案例循环MOV EAX, 10000001b ROL EAX, 1 ; 最高位移到最低位00000011b ROR EAX, 1 ; 反过来第六部分控制转移指令19. JMP — 无条件跳转JMP label ; 直接跳 JMP EAX ; 跳转到EAX中的地址 JMP [EBX] ; 跳转到内存中的地址案例无限循环start: ; 做事 JMP start ; 永远循环20. 条件跳转 — Jcc常用条件跳转对照表指令意思C语言对应JE/JZ相等/为零 0JNE/JNZ不等/非零! 0JG/JNLE大于有符号JGE/JNL大于等于有符号JL/JNGE小于有符号JLE/JNG小于等于有符号JA大于无符号JB小于无符号案例1if-else 结构; C: if (a b) c 1; else c 0; MOV EAX, [a] CMP EAX, [b] JG set_one MOV [c], 0 JMP end set_one: MOV [c], 1 end:案例2找最大值; 找EAX和EBX中的最大值放入ECX CMP EAX, EBX JG eax_bigger MOV ECX, EBX JMP done eax_bigger: MOV ECX, EAX done:21. LOOP — 循环原理ECX-1如果不为0则跳转案例数组求和; 计算数组array[10]的和 MOV ECX, 10 ; 循环次数 MOV ESI, 0 ; 索引 MOV EAX, 0 ; 累加器 sum_loop: ADD EAX, [array ESI*4] INC ESI LOOP sum_loop ; ECX--, 不为0则跳 ; 循环结束EAX 总和22. CALL / RET — 函数调用案例完整的函数调用; 主程序 main: PUSH 5 ; 参数b PUSH 3 ; 参数a CALL Add ; 调用Add(3, 5) ADD ESP, 8 ; 清理参数cdecl调用约定 ; 结果在EAX中 ; Add函数 Add: PUSH EBP ; 保存旧栈帧 MOV EBP, ESP ; 建立新栈帧 MOV EAX, [EBP8] ; 参数a ADD EAX, [EBP12] ; 参数b POP EBP ; 恢复栈帧 RET ; 返回栈帧图解高地址 ------- | 参数b | [EBP12] ------- | 参数a | [EBP8] ------- | 返回址 | [EBP4] ------- | 旧EBP | [EBP] - EBP指向这里 ------- | 局部变 | [EBP-4] ------- - ESP 低地址第七部分串操作指令23. MOVS — 串传送案例内存拷贝; 从source拷贝100字节到dest MOV ESI, OFFSET source ; 源地址 MOV EDI, OFFSET dest ; 目的地址 MOV ECX, 100 ; 字节数 CLD ; 方向标志清零正向 REP MOVSB ; 重复拷贝 ; 优化按DWORD拷贝更快 MOV ECX, 25 ; 100/4 REP MOVSD ; 一次4字节24. STOS — 存储串案例内存清零; 将buffer的1000字节清零 MOV EDI, OFFSET buffer MOV ECX, 250 ; 1000/4 XOR EAX, EAX ; EAX 0 CLD REP STOSD ; 每次存4字节25. CMPS / SCAS — 串比较/扫描案例字符串比较; 比较两个字符串是否相等 MOV ESI, OFFSET str1 MOV EDI, OFFSET str2 MOV ECX, 20 CLD REPE CMPSB ; 相等则继续 JE equal ; 不相等...案例查找字符; 在字符串中查找A MOV EDI, OFFSET string MOV ECX, 100 MOV AL, A CLD REPNE SCASB ; 不相等则继续 JE found ; 找到了第八部分综合实战案例案例1冒泡排序; 对array[n]进行冒泡排序 ; 假设array是DWORD数组n是元素个数 bubble_sort: MOV ECX, n DEC ECX ; 外层循环 n-1 次 outer_loop: PUSH ECX ; 保存外层计数 MOV ESI, 0 ; 内层索引 inner_loop: MOV EAX, [array ESI*4] MOV EBX, [array ESI*4 4] CMP EAX, EBX JLE no_swap ; 交换 MOV [array ESI*4], EBX MOV [array ESI*4 4], EAX no_swap: INC ESI LOOP inner_loop POP ECX LOOP outer_loop RET案例2计算字符串长度; 类似strlen函数 strlen: MOV EDI, [ESP4] ; 参数字符串地址 XOR EAX, EAX ; AL 0查找\0 MOV ECX, -1 ; 最大长度 CLD REPNE SCASB ; 扫描直到找到0 NOT ECX DEC ECX ; ECX 字符串长度 MOV EAX, ECX RET案例3求斐波那契数; fib(n) - 递归版 ; 参数在栈上[EBP8] fib: PUSH EBP MOV EBP, ESP MOV EAX, [EBP8] CMP EAX, 1 JLE fib_end ; n1直接返回n PUSH EBX DEC EAX PUSH EAX ; fib(n-1) CALL fib ADD ESP, 4 MOV EBX, EAX ; 保存结果 MOV EAX, [EBP8] SUB EAX, 2 PUSH EAX ; fib(n-2) CALL fib ADD ESP, 4 ADD EAX, EBX ; fib(n-1) fib(n-2) POP EBX fib_end: POP EBP RET案例4判断素数; 判断EAX中的数是否为素数 ; 返回ZF1表示是素数 is_prime: CMP EAX, 2 JL not_prime ; 2 不是素数 JE is_prime_ret ; 2 是素数 MOV EBX, 2 ; 从2开始试除 check_loop: MOV ECX, EAX MOV EDX, 0 PUSH EAX MOV EAX, ECX DIV EBX ; ECX / EBX POP EAX TEST EDX, EDX ; 余数为0 JZ not_prime ; 能整除不是素数 INC EBX MOV ECX, EAX MOV EDX, EAX IMUL ECX, EBX IMUL EDX, EBX CMP EBX, EAX JL check_loop ; 简化应该判断EBX*EBXEAX is_prime_ret: XOR EAX, EAX ; 是素数 RET not_prime: MOV EAX, 1 ; 不是素数 RET第九部分常见调用约定cdeclC默认; 调用者清栈参数从右往左压栈 PUSH arg3 PUSH arg2 PUSH arg1 CALL func ADD ESP, 12 ; 调用者清栈stdcallWindows API; 被调用者清栈 PUSH arg3 PUSH arg2 PUSH arg1 CALL func ; 函数内部RET 12清栈fastcall; 前两个参数用ECX、EDX传其余压栈 MOV ECX, arg1 MOV EDX, arg2 PUSH arg3 CALL func第十部分调试和练习建议调试工具x64dbg / OllyDbg动态调试IDA Pro / Ghidra静态分析Compiler Explorer (godbolt.org)看C代码编译出的汇编练习建议入门练习// 把这些C代码转成汇编intadd(inta,intb){returnab;}intmax(inta,intb){returnab?a:b;}intsum(intn){ints0;for(inti1;in;i)si;returns;}进阶练习手写字符串处理函数strcpy, strcmp, strlen实现冒泡排序、快速排序读写文件用系统调用学习看反汇编代码学习资料推荐书籍《汇编语言》王爽— 中文入门首选《x86汇编语言从实模式到保护模式》李忠— 深入《深入理解计算机系统》(CSAPP)— 系统层面Intel官方手册— 权威参考在线资源godbolt.org— 在线看汇编felixcloutier.com/x86— 指令查询osdev.org— 系统级开发学习路径王爽《汇编语言》16位 ↓ 32位保护模式李忠书 ↓ x64扩展 ↓ 逆向工程/操作系统开发
返回列表