寄存器
存储cpu中的数据
32位通用寄存器
32位 |
16位 |
8位 |
EAX |
AX |
AL |
ECX |
CX |
CL |
EDX |
DX |
DL |
EBX |
BX |
BL |
ESP |
SP |
AH |
EBP |
BP |
CH |
ESI |
SI |
DH |
EDI |
DI |
BH |
8位寄存器在16位寄存器中,而16位寄存器在32位寄存器中。
简单来说
32位寄存器就是一整个
16位寄存器就是32的一半 15-0这部分
8位寄存器分高位和低位,分别代表15-8 7-0,如下图
做个实验就明白了
将32位寄存器全部写满数据
对16位寄存器调试
可以看到更改的数据是后面四个
对8位高低寄存器调试,可以看到ah是在eax寄存器的后34位改变的,al是后两位改变的
od添加两个指令
f8执行,eax的值变成了1 又把eax的值给了edx
内存
写立即数到内存
mov byte ptr ds:[内存窗口的已申请的16进制],1 byte < word < dword 字节大小 mov byte ptr ds:[0019FB90],20
写寄存器到内存
mov byte ptr ds:[0019FB90],eax
读内存到寄存器
mov eax,byte ptr ds:[0019FB90]
内存地址的五种表示方式
形式1
立即数 0019FB90
形式2
[reg] 代表任意寄存器
形式3
[reg+立即数]
形式4
[reg+reg*{1,2,4,8}]
形式5
[reg+reg*{1,2,4,8}+立即数]
数据的存储模式
大段模式:数据高位在低位,数据地位在高位 小段模式:数据低位在低位,数据高位在高位
db 内存地址 查看一个字节 dw 内存地址 查看两个字节 dd 内存地址 查看四个字节
⼤⼩端的使⽤场景
1、Intel的80×86系列芯⽚使⽤⼩端存储模式
2、ARM芯⽚默认采⽤⼩端,但可以切换为⼤端
3、MIPS芯⽚采⽤⼤端,但可以在⼤⼩端之间切换
4、在⽹络上传输的数据普遍采⽤的都是⼤端
0x11223344 11是高位 44是低位
在内存地址中 90<93内存地址,所以是小段模式
0019FF90 44
0019FF91 33
0019FF92 22
0019FF93 11
mov 移动数据
mov eax,1 将1存储到eax中 mov eax,edx 将edx的值存储到eax
add 数据相加
add eax,1 eax加1结果给eax
sub 数据相减
sub eax,1 eax减1结果给eax
and 作用按位与运算
按位与
作用:只将某一位变成0,而其他位保持不变
使用:谁要变0,谁就和0与
and就是与运算,两个数按二进制位相与,全1为1,有0为0,常用于把低位清零
or 按位或运算
or eax,edx
按位或
作用:只将某一位变成1,而其他位保持不变
使用:谁要变1,谁就和1或
xor 异或运算 一样为0 不一样为1
xor eax,ecx
not 异或运算 一样为1 不一样为0
not eax,ecx
movs 移动数据,内存-内存
movs byte ptr es:[EDI],byte ptr ds:[ESI] movs word ptr es:[EDI],word ptr ds:[ESI] movs dword ptr es:[EDI],dword ptr ds:[ESI] 简写 movsb movsw movsd
EFL 标志寄存器
DF的值 由第十位决定
为0时,则EDI ESI +1 +2 +4
为1时,则EDI ESI -1 -2 -4
stos指令 将al/ax/eax的值存储到edi指定的内存单元
stos byte prt es:[EDI] stos word prt es:[EDI] stos dword prt es:[EDI] 简写 stosb stosw stosd
rep指令,按计数寄存器ECX中指定的次数重复执行字符串指令
mov ecx,10rep movsd rep stosd
堆栈
ESP栈指针寄存器
push指令 向堆栈压入数据,修改斩顶指针ESP寄存器
相当于mov sub -4
push 3 push eax push dword prt ds:[18FFA4]
pop指令 将斩顶数据存储到寄存器,修改栈顶ESP寄存器
相当于mov add +4
pop ecx pop 3
修改EIP指令 下一次要执行的指令
jmp指令 跳转
jmp 004F11 jmp 10 jmp eax
call指令
修改EIP的值
call指令结束后,下一行地址存到堆栈中
同时ESP的值 -4
call 004F11 call eax
ret指令
把当前栈顶的值放到EIP,ESP +4 ret
函数
指令的集合
函数的调用
jmp 或 call
小案例 两数相加
001 mov ecx,1 002 mov edx,2 003 call 009 008 add ecx,edx 009 mov eax,ecx 010 ret
堆栈平衡
如果要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在ret指令之前,ESP指向的是我们压入栈中的地址。
如果通过堆栈传递参数 了,那么在函数执行完毕后,要平衡参数导致的堆栈变化。
ESP寻址
001 push 1 002 push 2 003 call 007 004 add esp,8 007 mov eax,dword prt ss:[esp+4] 008 mov eax,dword prt ss:[esp+8] 009 ret
EBP寻址
开辟新的内存空间 esp ebp整体移动,等函数调用结束在回到原位
001 push 1 002 push 2 003 call 007 004 add esp,8 007 push ebp 008 mov ebp,esp 009 sub esp,10 010 mov eax,dword ptr ss:[ebp+8] 011 mov eax,dword ptr ss:[esp+C] 012 mov esp,ebp 013 pop ebp 014 ret
jcc指令
标志寄存器
CF 第0位,表示无符号数运算的溢出状态,溢出为1,反之为0
溢出了 cf为1
mov al,0xFE add al,2
PF 如果结果的最低有效字节包含偶数个1位,则为1,反之为0
mov al,0xce add al,0
AF 如果算数操作在结果的第三位发生进位或借位则将该标志置1,否则清零
ZF 若结果为0,则为1,反之为0
mov eax,100 mov ecx,100 cmp eax,ecx cmp与sub类似,但想减的结果并不保存到第一个操作数中 test eax,ecx
SF 该标志被设置为有符号整型的最高有效位(0 指示结果为正,反之则为负)
mov al,0x7F add al,2 mov al,0xFE add al,2
OF 反映有符号数加减运算所得结果是否溢出
如果无符号运算,溢出看cf位
如果有符号运算,溢出看of位
mov al,0x7F add al,2
JCC指令 |
中文含义 |
检查符号位 |
JZ/JE |
若为0则跳转; |
ZF=1 |
若相等则跳转 |
ZF=1 |
|
JNZ/JNE |
若不为0则跳转; |
ZF=0 |
若不相等则跳转 |
ZF=0 |
|
JS |
若为负则跳转 |
SF=1 |
JNS |
若为正则跳转 |
SF=0 |
JP/JPE |
若1出现次数为偶数则跳转 |
PF=1 |
JNP/JPO |
若1出现次数为奇数则跳转 |
PF=0 |
JO |
若溢出则跳转 |
OF=1 |
JNO |
若无溢出则跳转 |
OF=0 |
JC/JB/JNAE |
若进位则跳转; |
CF=1 |
若低于则跳转; |
CF=1 |
|
若不高于等于则跳转 |
CF=1 |
|
JNC/JNB/JAE |
若无进位则跳转; |
CF=0 |
若不低于则跳转; |
CF=0 |
|
若高于等于则跳转; |
CF=0 |
|
JBE/JNA |
若低于等于则跳转; |
ZF=1或CF=1 |
若不高于则跳转 |
ZF=1或CF=1 |
|
JNBE/JA |
若不低于等于则跳转; |
ZF=0而且CF=0 |
若高于则跳转 |
ZF=0而且CF=0 |
|
JL/JNGE |
若小于则跳转; |
SF != OF |
若不大于等于则跳转 |
SF != OF |
|
JNL/JGE |
若不小于则跳转; |
SF = OF |
若大于等于则跳转; |
SF = OF |
|
JLE/JNG |
若小于等于则跳转; |
ZF != OF 或 ZF=1 |
若不大于则跳转 |
ZF != OF 或 ZF=1 |
|
JNLE/JG |
若不小于等于则跳转; |
SF=0F 且 ZF=0 |
若大于则跳转 |
SF=0F 且 ZF=0 |