常用汇编指令

指令 说明
JMP 修改EIP的值
CALL 修改EIP的值,将下一个指令的地址压入栈中,并减少ESP的值
RET 将栈顶内存写入EIP,并增加ESP的值,栈顶内存储存的是CALL执行前的下一步地址
CMP 等同于SUB,但结果不保存
TEST 同上,等同于AND

内存相关指令

MOV BYTE PTR DS:[0018FFF0],1

将立即数储存到0X0018FFF0开始的一字节空间,在写入内存时必须声明长度。

在汇编中的数据类型有BIT(1位),BYTE(1字节),WORD(2字节),DWORD(4字节)

MOV DWORD PTR DS:[0019FF74],EAX
将32位通用寄存器EAX的值写到0X0019FF74,写入的宽度必须和寄存器的宽度一致


MOVS指令

MOV 指令无法从内存写到内存

32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据。

寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register)其中S和D代表source和destination

它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。变址寄存器不可分割成8位寄存器。

1
2
3
MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
MOVS WORD PTR ES:[EDI],BYTE PTR DS:[ESI]
MOVS DWORD PTR ES:[EDI],BYTE PTR DS:[ESI]

可以简写成MOVSB,MOVSW,MOVSD,ES是extra segment的缩写,执行以上命令,会将寄存器ESI中指向内存的数据储存到EDI指向的内存中,执行完毕后EDI和ESI两个寄存器中的地址会自动增加,增加的数取决于附加数据的长度,以上三条指令分别会使变址寄存器中的值增加1、2、4

在使用时EDI必须作为储存附加段地址寄存器,ESI作为储存数据段地址的寄存器


例如有以下命令

MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

此时变址寄存器中指向的内存

执行完毕后两个变址寄存器的值增加了4,因为写入了4字节数据,内存往后移4字节。


STOS指令

将AI、AX、EAX的值储存到EDI指向的内存单元,例如数据长度为BYTE,则会将AI的值写入到EDI指向的内存

1
2
3
STOS BYTE PTR ES:[EDI]
STOS WORD PTR ES:[EDI]
STOS DWORD PTR ES:[EDI]

可以简写成STOSB、STOSW、STOSD

执行完毕后EDI的值增加(或减少,取决于DF标志位),增加的量取决于数据长度。


REP指令

REP(repeat)

按计数寄存器ECX中指定的次数重复执行字符串指令,每执行一次时ECX减一

1
2
3
4
MOV ECX,10
REP MOVSD

REP STOSD

以上第二行指令将ESI指向的内存数据(32位)写入到EDI寄存器,然后变址寄存器+4,此步骤重复16次 (指令中的10为16进制)
第三行将EAX指向的内存数据(32位)写入到EDI寄存器,然后EDI+4,此步骤重复16次


函数相关命令

使用寄存器传递参数

1
2
3
4
5
6
7
MOV ECX,1
MOV EDX,1
CALL 00418420

ADD ECX,EDX
MOV EAX,ECX
RET

堆栈传参

需要注意的是最后一个被压栈的是函数地址,所以取值的时候需要加上一个偏移量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PUSH 1
PUSH 2
PUSH 3
PUSH 4
PUSH 5
CALL 0x0040EF61


MOV EAX,DWORD PTR DS:[ESP+14]
ADD EAX,DWORD PTR DS:[ESP+10]
ADD EAX,DWORD PTR DS:[ESP+C]
ADD EAX,DWORD PTR DS:[ESP+8]
ADD EAX,DWORD PTR DS:[ESP+4]
RET