吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7026|回复: 41
收起左侧

[调试逆向] X86汇编基础

  [复制链接]
loca1h0st 发表于 2025-1-22 01:34
本帖最后由 loca1h0st 于 2025-1-22 01:36 编辑

1. intel X86有哪些寄存器

  • 累加寄存器(AX)。用在算数运算
  • 基址寄存器(BX)。作为一个指向数据的指针(在分段模式下,位于段及寄存器DS
  • 计数寄存器(CX)。用于位移/循环指令和循环
  • 数据寄存器(DX)。用在算数运算和I/O操作
  • 堆栈指针寄存器(SP)。用于指向堆栈的顶部
  • 栈基址指针寄存器(BP)。用于指向堆栈的底部
  • 源变址寄存器(SI)。在流操作中用作源的一个指针
  • 目标索引寄存器(DI)。用作在流操作中指向目标的指针

    CF(bit 0)[Cary fag] 若算术操作产生的结果在最高有效位(mos-significant bit)发生进位或借位则将其置1,反之清零。这个标志指示无符号整型运算的溢出状态,这个标志同样在多倍精度运算(multiple-precision arithmetic)中使用。
    PF(bit 2)[Parity flag]如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零。
    AF(bit 4) [Adiust fiag]如果算术提作在结果的第3位发生进位或借位则将该标志置1,否则清零,这个标志在BCD(binary-code decimal)算术运算中被使用。
    ZF(bit 6)[Zero flag]若结果为0则将其置1,反之清零。
    SF(bit 7)[Sign flag] 该标志被设置为有符号整型的最高有效位。(0指示结果为正,反之则为负)
    OF(bit 11)[Overflow flag]如果整型结果是较大的正数或较小的负数,并且无法匹配目的操作数时将该位置1,反之清零,这个标志为带符号整型运耸指示溢出状态。

    2. X86架构的内存和寻址模式有哪些

==立即数寻址方式==

mov al, 5
mov eax, 231h

==寄存器寻址方式==

操作数放在寄存器中,指令指定寄存器号

mov ax, bx

==直接寻址方式==
操作数在存储器中,指令给出存储器的偏移地址

mov ax, [2000h]

==寄存器间接寻址==
操作数的地址在基址存储器或者变址存储器,而操作数则在存储器中

mov ax, [bx]

==基址变址寻址==

mov ax, [bx+si]
mov bx, [bp+si]

==寄存器相对寻址==

mov ax, [di+100h]

==相对基址变址寻址==

mov AX, [BX+SI+200H]

==相对基址比例变址寻址==

mov [EAX+EDI*2+15H], DX

3.在逆向中我们会遇到哪些常见的X86指令

数据传送指令

[!MOV]
mov Move(Opcodes: 88,89,8A,8B, 8C,8E, ...)mov指令将第二个操作数(可以是寄存器的内容、内存中的内容或值)复制到第一个操作数(寄存器或内存)。mov不能用于直接从内存复制到内存。

Examples

mov eax, ebx
mov byte ptr [eax], 5

[push]
push Push stack(Opcodes: FF, 89,8A,8B, 8C, 8E, ...)push指令将操作数压入内存的栈中,栈是程序设计中一种非常重要的数据结构,其主要用于函数调用过程中,其中ESP只是栈顶。在压栈前首先将ESP值减4(X86栈增长方向与内存地址编号增长方向相反),然后将操作数内容压入ESP指示的位置

Examples

push eax
push [eax]

[Pop]
pop- Pop stack
pop指令与push指令相反,它执行的是出栈的工作。它首先将ESP指示的地址中的内容出栈,然后将ESP值加4.其语法如下所示

Examples

pop edi
pop [ebx]

[Lea]
lea- Load effective address
lea实际上是一个载入有效地址指令,将第二个操作数表示的地址载入到第一个操作数(寄存器)中。

Examples

lea eax, [var]
lea edi, [ebx+4*esi]

逻辑计算指令&控制流指令

[Jz]
说明:如果零标志(ZF=1),则跳转到目标地址。
用途:通常在结果为零时进行跳转。

Examples

cmp eax, 0  ; 比较 eax 和 0
jz  target  ; 如果等于 0,跳转到 target

[Ja]
说明:如果无符号比较中,前一个操作数大于后一个操作数(CF=0 且 ZF=0),则跳转到目标地址。
用途:处理无符号数的大小比较。

Examples

cmp eax, ebx ; 比较 eax 和 ebx
ja   target  ; 如果 eax > ebx,则跳转到 target

[Jae]

说明:如果无符号比较中,前一个操作数大于或等于后一个操作数(CF=0),则跳转到目标地址。
用途:处理无符号数的“大于或等于”比较。

Examples

cmp eax, ebx ; 比较 eax 和 ebx
jae  target  ; 如果 eax >= ebx,则跳转到 target

[Jb]

说明:如果无符号比较中,前一个操作数小于后一个操作数(CF=1),则跳转到目标地址。
用途:处理无符号数的小于比较。

Examples

cmp eax, ebx ; 比较 eax 和 ebx
jb   target  ; 如果 eax < ebx,则跳转到 target

[jbe]

说明:如果无符号比较中,前一个操作数小于或等于后一个操作数(CF=1 或 ZF=1),则跳转到目标地址。
用途:处理无符号数的“小于或等于”比较。

Examples

cmp eax, ebx ; 比较 eax 和 ebx
jbe  target  ; 如果 eax <= ebx,则跳转到 target

[je]

说明:如果两个值相等(ZF=1),则跳转到目标地址。此指令是 jz 的同义词。
用途:在需要检测相等性时使用。

Examples

cmp eax, ebx ; 比较 eax 和 ebx
je   target  ; 如果 eax == ebx,则跳转到 target

4. 32位程序的调用约定

stdcall

  • 参数从右向左压入堆栈
  • 函数自身修改堆栈
    push 2; 第二个参数入栈
    push 1; 第一个参数入栈
    call function; 调用函数,注意此时自动把cs:eip入栈
push ebp; 保存ebp寄存器,该寄存器将调用来保存堆栈的栈顶指针,可以在函数退出是恢复
mov ebp, esp; 保存栈顶指针
mov eax, [ebp + 8H]; 堆栈中ebp指向位置之前依次保存右ebp,cs:eip,a,b,ebp +8指向a
add eax, [ebp + 0CH]; 堆栈中ebp + 12 处保存了b
mov esp, ebp; 恢复esp
pop ebp;
ret 8; 自动调整栈平衡,push几个参数就 ret 几个字节 2 * 4

显示调用stdcall

__attribute__((stdcall)) int a3(int a, int b, int c, int d)

{

    return 3 * a + 2 * b + 2 * c + d;

}

cdecl

  • 首先由右向左压入堆栈
  • 函数本身不清理堆栈,调用者负责清理堆栈
    push 1;
    push 2;
    call function; 
    add esp, 8; // 注意,这里调用者恢复堆栈 有两个参数所以加了8
push ebp; 保存ebp寄存器,该寄存器将调用来保存堆栈的栈顶指针,可以在函数退出是恢复
mov ebp, esp; 保存栈顶指针
mov eax, [ebp + 8H]; 堆栈中ebp指向位置之前依次保存右ebp,cs:eip,a,b,ebp +8指向a
add eax, [ebp + 0CH]; 堆栈中ebp + 12 处保存了b
mov esp, ebp; 恢复esp
pop ebp;
ret;

显示调用cdecl

__attribute__((cdecl)) int a1(int a, int b, int c, int d)

{

    return a + b + c + d;

}

fastcall

  • 函数第一个和第二个DWORD参数通过ecx和edx传递
  • 其他参数通过从右向左的顺序压栈
  • 被调用函数清理堆栈

显示调用fastcall

__attribute__((fastcall)) int a2(int a, int b, int c, int d)

{
    return a + b + 2 * c + d;
}

实验

apt install gcc-multilib g++-multilib libc6-dev-i386

example.c

#include <stdio.h>

__attribute__((cdecl)) int a1(int a, int b, int c, int d)

{
    return a + b + c + d;
}

__attribute__((fastcall)) int a2(int a, int b, int c, int d)

{
    return a + b + 2 * c + d;
}

__attribute__((stdcall)) int a3(int a, int b, int c, int d)

{
    return 3 * a + 2 * b + 2 * c + d;
}

int main()

{

    int a, b, c, d;

    a = 10;
    b = 20;
    c = 30;
    d = 40;

    a1(a, b, c, d);
    a2(a, b, c, d);
    a3(a, b, c, d);

    return 0;

}

Makefile

sample: example.c

    gcc -m32 -g -O0 $^ -o $@ # -m32 32位平台 -O0 表示不让编译器采用任何优化

.PHONY: clean
clean:

    rm sample


a1不负责清栈



a2 将第一个第二个参数压入edx,eax中,自己负责清栈



a3从右向左压栈

[/md]

免费评分

参与人数 18威望 +1 吾爱币 +35 热心值 +16 收起 理由
tony118 + 1 + 1 谢谢@Thanks!
junjia215 + 1 + 1 用心讨论,共获提升!
winwoo80 + 1 + 1 很用心
willJ + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
nekolzc + 1 感谢您的宝贵建议,我们会努力争取做得更好!
damingtianci + 1 我很赞同!
klmytwb + 1 + 1 谢谢@Thanks!
nonefree + 1 + 1 用心讨论,共获提升!
allspark + 1 + 1 用心讨论,共获提升!
Issacclark1 + 1 谢谢@Thanks!
我若化成风 + 1 + 1 谢谢@Thanks!
zhouxinzhe + 1 + 1 我很赞同!
thornjay + 1 + 1 我很赞同!
HXlyf + 1 热心回复!
qjsh + 1 + 1 谢谢@Thanks!
zhouzhiwei90 + 1 + 1 用心讨论,共获提升!
nishuidechali + 1 + 1 用心讨论,共获提升!
kof888 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

kof888 发表于 2025-1-22 06:15
感谢,这些对我这种新手很有帮助,收藏一下慢慢消化。

另外问一下,x86的寄存器才这么几个?我一直以为有10几个寄存器?
nishuidechali 发表于 2025-1-22 07:19
qq414816486 发表于 2025-1-22 07:33
tzblue 发表于 2025-1-22 07:56
基础知识,可以作为参考
wyd926 发表于 2025-1-22 08:24
基础是关键
zghsgi 发表于 2025-1-22 08:32
汇编很好用,可惜多年不会编程了
semmy 发表于 2025-1-22 08:40
刚上大学那会儿,觉得这玩意好难
kongson 发表于 2025-1-22 08:43
非常感谢大佬分享!
san4san 发表于 2025-1-22 08:50
非常感谢大佬分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-11 00:42

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表