熊猫のReverse课堂 x86汇编笔记
常用24条指令
- NOP:无操作指令,执行时不改变任何状态,常用于占位或调试。
- PUSH x:将值x压入栈中,栈指针(ESP)先减去数据大小,然后存储数据。
- POP x:将栈顶的数据弹出到x中,栈指针(ESP)递增,指向下一个数据。
- CALL x:将下一条指令的地址压入栈中,并将指令指针(EIP)设置为x,跳转到x处执行。
- RET:从栈中弹出返回地址到EIP,若为
RET x
,则ESP增加x字节。 - MOV 目的, 源:将源操作数的值复制到目的操作数中。
- LEA x1, x2:将x2的地址加载到x1中,常用于获取变量的地址。
- ADD x1, x2:将x2的值加到x1中,结果影响标志寄存器(EFLAGS)。
- SUB x1, x2:将x2的值从x1中减去,结果同样影响EFLAGS,不能同时使用内存操作数。
- JMP x:无条件跳转到地址x,
JMP -2
表示无限循环。 - JCC x:根据条件跳转到x,条件由EFLAGS决定。
- CMP x1, x2:比较x1和x2的大小,设置EFLAGS以反映比较结果。
- TEST x1, x2:通过计算两个操作数的逻辑与位运算实现比较操作,根据结果设置EFLAGS
- AND x1, x2:按位与操作,将结果存储在x1中。
- OR x1, x2:按位或操作,将结果存储在x1中。
- XOR x1, x2:按位异或操作,常用于清零,
XOR EAX, EAX
将EAX清零。 - NOT x1:按位取反操作,将结果存储在x1中。
- SHL x1, x2:逻辑左移操作,将x1左移x2位,右侧补0。
- SHR x1, x2:逻辑右移操作,将x1右移x2位,左侧补0。
- IMUL/MUL:
IMUL
用于有符号数乘法,MUL
用于无符号数乘法。 - IDIV/DIV:
DIV
用于无符号数除法,IDIV
用于有符号数除法,商和余数分别存储在EAX和EDX中。 - REP STOS:前缀
REP
表示重复执行STOS
操作,通常用于初始化内存。 - REP MOVS:重复执行
MOVS
操作,通常用于内存拷贝。 - LEAVE:用于从子函数返回时清理栈,等价于
MOV ESP, EBP; POP EBP
。
常用寄存器:
EAX (累加寄存器):
- 用于算术运算和I/O操作的累加器,常用于存储函数返回值。
EBX (基址寄存器):
- 通常用于存储数据的基地址,常在数组和数据结构的访问中使用。
ECX (计数寄存器):
- 用于循环计数和字符串操作,特别是在
REP
指令中。
- 用于循环计数和字符串操作,特别是在
EDX (数据寄存器):
- 用于存储乘法和除法运算的高位结果,或作为I/O操作的额外数据寄存器。
ESI (源索引寄存器):
- 通常用于指向源数据的地址,特别是在字符串操作中。
EDI (目的索引寄存器):
- 通常用于指向目标数据的地址,特别是在字符串操作中。
EBP (基指针寄存器):
- 用于指向当前栈帧的基地址,常用于函数调用和局部变量的访问。
ESP (栈指针寄存器):
- 指向当前栈顶的位置,所有栈操作(如PUSH和POP)都通过此寄存器进行。
EIP (指令指针寄存器):
- 指向下一条将要执行的指令的地址,自动更新以指向程序的执行流。
EFLAGS (标志寄存器):
- 存储运算结果的状态标志(如零标志、进位标志、溢出标志等),用于控制程序的执行流。
段寄存器
CS (代码段寄存器):
- 指向当前执行代码的段,包含指令的地址。
DS (数据段寄存器):
- 指向默认数据段,通常用于访问程序中的全局变量和静态数据。
SS (栈段寄存器):
- 指向当前栈的段,配合ESP寄存器使用,管理函数调用和局部变量。
ES (附加段寄存器):
- 用于字符串操作的附加数据段,通常在某些指令中作为目标段。
FS 和 GS (额外段寄存器):
- 用于存储特定用途的数据段,常用于线程局部存储和系统调用。
eg:
REP STOS
指令用于重复存储操作,通常用于初始化内存。
REP STOS DWORD PTR ES:[EDI]
的含义如下:
- REP:前缀,表示后续的指令将被重复执行,重复的次数由
ECX
寄存器的值决定。 - STOS:存储操作指令,用于将
EAX
寄存器的值存储到目标地址。 - DWORD PTR:指示操作数的大小为双字(4字节)。
- ES:[EDI]:表示目标地址为段寄存器
ES
指向的内存地址,具体位置由EDI
寄存器指定。
这条指令的功能是将 EAX
寄存器中的值存储到 ES
段中由 EDI
指向的内存地址,并且这个操作会重复 ECX
次。每次存储后,EDI
会自动增加4(因为是双字存储),以指向下一个存储位置。
假设 EAX
中的值为 0x12345678
,ECX
的值为 5
,EDI
指向的地址为 0x1000
,执行 REP STOS DWORD PTR ES:[EDI]
后,内存中的内容将变为:
0x1000: 0x12345678
0x1004: 0x12345678
0x1008: 0x12345678
0x100C: 0x12345678
0x1010: 0x12345678
EDI
在每次存储后自动增加4,直到 ECX
计数为0为止。
执行模型
- 栈
- 程序的栈是当前进程的内存地址空间中的一块内存区域
- 栈在内存的位置(起始地址)因操作系统不同而不同
- 栈帧
- 栈帧是当前执行的函数(如函数f)使用的那块栈空间程序执行进入f后,ESP和EBP指向的内存地址之间的内存区域被称为f的栈帧
- 一般也将f的参数传递、部分寄存器暂存、返回地址暂存等占用的内存空间也算作f的栈帧