汇编
一、进制
1、十进制
十进制的定义:由十个符号组成,分别是0 1 2 3 4 5 6 7 8 9 逢十进一
2、八进制
八进制的定义:由八个符号组成,分别是0 1 2 3 4 5 6 7 逢八进一
3、十六进制
十六进制的定义:由十六个符号组成,分别是0 1 2 3 4 5 6 7 8 9 A B C D E F
4、二进制与十六进制的关系
任意一个十六进制的符号对应四位二进制的数
二、计算机与数字的关系
1、计算机中的任何信息,比如一张图片、一部视频或者、 一首歌曲, 最终都是以二进制的形式进行存储的。
2、计算机采用二进制的形式存储数据,主要有两方面的原因:
- 二进制就足够
- 受硬件制约
三、数据宽度
1、数学上的数字,是没有大小限制的,可以无限的大。但在计算机中,由于受硬件的制约,数据都是有长度限制的(我们称为超过最多宽度的数据会被丢弃)
2、 4位宽度表示:假设计算机只能存储4位2进制数
3、 8位宽度表示:假设计算机只能存储8位2进制数
4、16位宽度表示:假设计算机只能存储16位2进制数
5、 32位宽度表示:假设计算机只能存储32位2进制数
四、计量单位
BYTE 字节 8BIT
WORD 字 16BIT 2字节
DWORD 双字 32BIT 4字节
五、二进制的逻辑运算
1、or运算(有一个为1就是1)
10110100
or 10001101
___________________
10111101
2、and运算(两个都是1才是1)
10110100
and 10001101
________________
10000100
3、 xor运算(不一样为1)
10110100
xor 10001101
________________
00111001
4、not运算(1是0,0是1)
not 10110100
________________
01001011
5、计算机计算2+3
# 第一步进行异或操作
0010
xor 0011
_____________
0001
# 第二步将0001和0011进行与操作
0001
and 0011
_____________
0010
# 第三步将0010左移一位进行判断,如果为0000,0001就是结果,不是进行第四步
0010 << 1 = 0100
# 第四步将0001和0100进行异或操作
0001
xor 0100
————————————
0101
# 第五步0001和0100进行与操作,然后左移一位进行判断
0001
and 0100
————————————
0000
0000 << 1 = 0000
所以答案是0101为5
6、获取某个值的第N位的值
如: 8F
10001111
and 00001000
___________________
00001000
7、最简单的加密算法
要加密的数据: 2015 00100000 00010101
01010100 01010100
密钥: 54 ——————————————————
加密后的结果: 01110100 01000001
74 41
01110100 01000001
01010100 01010100
——————————————————
00100000 00010101
解密后的结果: 20 15
六、32位通用寄存器指定用途
寄存器 主要用途
EAX 累加器
ECX 计数
EDX I/0指针
EBX DS段的数据针
ESP 堆栈指针
EBP SS段的数据指针
ESI 字符串操作的源指针; SS段的数据指针
EDI 字符串操作的且标指针; ES段的数据指针
七、基本指令
1、界面窗口
2、mov 指令
1、MOV r/m8,r8 r通用寄存器
2、MOV r/m16,r16 m中代表内存
3、MOV r/m32,r32 imm代表立即数
4、MOV r8,r/m8 r8代表8位通用寄存器
5、MOV r16,r/m16 m8代表8位内存
6、MOV r32,r/m32 imm8代表8位立即数
7、MOV r8, imm8
8、MOV r16, im16
9、MOV r32, imm32
MOV目标操作数,源操作数
作用:拷贝源操作数到目标操作数
1、源操作数可以是立即数、通用寄存器、段寄存器、或者内存单元.
2、目标操作数可以是通用寄存器、段寄存器或者内存单元.
3、操作数的宽度必须一样.
4、源操作数和目标操作数不能同时为内存单元.
3、SUB指令
SUB AL,imm8
SUB AX, imm16
SUB EAX, imm32
SUB r/m8,imm8
SUB r/m16, imm16
SUB r/m32, imm32
SUB r/m16,imm8
SUB r/m32,imm8
SUB r/m8,r8
SUB r/m16,r16
SUB r/m32,r32
SUB r8,r/m8
SUB r16, r/m16
SUB r32, r/m32
4、ADD指令
ADD AL, imo8
ADD AX, imm16
ADD EAX, imm32
ADD r/m8,imm8
ADD r/m16, imm16
ADD r/m32, imm32.
ADD r/m16,imm8
ADD r/m32,imm8 .
ADD r/m8,r8
ADD r/m16,r16
ADD r/m32,r32
ADD r8,r/m8
ADD r16,r/m16
ADD r32,r/m32
5、ADN指令
6、OR指令
7、XOR指令
8、NOT指令
八、寄存器与内存的区别
1、寄存器位于CPU内部,执行速度快,但比较贵。
2、内存速度相对较慢,但成本较低,所以可以做的很大。
3、寄存器和内存没有本质区别,都是用于存储数据的容器,都是定宽的。
4、寄存器常用的有8个: EAX、ECX、 EDX、 EBX、ESP、EBP、ESI、 EDI。
5、计算机中的几个常用计量单位: BYTE WORD DWORD
BYTE 字节 = 8(BIT) .
WORD 字 = 16(BIT)
DWORD 双字 = 32(BIT)
1KB = 1024 BYTE
1MB = 1024 KB
1GB = 1024 MB
6、内存的数量特别庞大,无法每个内存单元都起-一个名字,所以用编号来代替,我们称计算机CPU是32位 或者64位,有很多书上说之所以叫32位计算机是因为寄存器的宽度是32位,是不准确的,因为还有很多寄存器是大于32位的。计算机内存的每一个字节会有一个编号(即内存编号的单位是字节),如下:
0x00000000
0x00000001
0x00000002
·········
·········
·········
0xFFFFFFFF
32位计算机内存寻址最大范围:
FFFFFFFF + 1 = 100000000 = 42949672Q6 BYTE = 4194304 kb = 4096 MB = 4 GB
但是可以拓展最大内存
九、内存
mov dword ptr ds: [0x0012FF34], 0x12345678
mov eax, dword ptr ds: [0x0012FF34]
dword :要读/写多少 此时是4字节
byte == 1字节 word == 2字节
ptr: Point代表后面是一个指针(指针的意思就是里面存的不是普通的值,而是个地址)
ds: 段寄存器先不用管记住就行
0x0012FF34:内存编号,必须是32位的前 面0可以省略
注意:地址编号不要随便写,因为内存是有保护的,并不是所有的内存都可以直接读写(需要特别处理),建议地址编号写成esp的值
十、寻址公式
1、寻址公式一
读取内存的值:
MOV EAX, DWORD PTR DS: [0x12FFC4]
MOV EAX, DWORD PTR DS: [0x12FFC8]
向内存中写入数据:
MOV DWORD PTR DS: [0x12FFC4],eax
MOV DWORD PTR DS: [0x12FFC8], ebx
获取内存编号:
LEA EAX, DWORD PTR DS: [0X12FFC4]
LEA EAX, DWORD PTR DS: [ESP+8]
2、寻址公式二
读取内存的值:
MOV ECX, 0x12FFD0
MOV EAX, DWORD PTR DS: [ECX]
向内存中写入数据:
MOV EDX, 0x12FFD8
MOV DWORD PTR DS: [EDX] , 0x87654321
获取内存编号:
LEA EAX, DWORD PTR DS: [EDX]
MOV EAX, DWORD PTR DS: [EDX]
3、寻址公式三
读取内存的值:
MOV ECX, 0x13FFD0
MOV EAX, DWORD PTR DS: [ECX+4]
向内存中写入数据:
MOV EDX, 0x13FFD8
MOV DWORD PTR DS: [EDX+0xC], 0x87654321
获取内存编号:
LEA EAX, DWORD PTR DS: [EDX+4]
MOV EAX, DWORD PTR DS: [EDX+4]
4、寻址公式四([reg+reg* {1,2, 4, 8}])只能乘1,2,4,8其中一个
读取内存的值:
MOV EAX, 13FFC4
MOV ECX, 2
MOV EDX, DWORD PTR DS: [EAX+ECX*4]
向内存中写入数据:
MOV EAX, 13FFC4
MOV ECX, 2
MOV DWORD PTR DS: [EAX+ECX*4], 87654321
获取内存编号:
LEA EAX, DWORD PTR DS: [EAX+ECX*4]
5、寻址公式五([reg+reg* {1, 2, 4, 8]+立即数])
读取内存的值:
MOV EAX, 13FFC4
MOV ECX, 2
MOV EDX, DWORD PTR DS: [EAX+ECX*4+4]
向内存中写入数据:
MOV EAX, 13FFC4
MOV ECX, 2
MOV DWORD PTR DS: [EAX+ECX*4+4], 87654321
获取内存编号:
LEA EAX, DWORD PTR DS: [EAX+ECX*4+2]
十一、pushad和popad
pushad 保存寄存器
popad 恢复寄存器
十二、堆栈
push 栈顶减4(不一定是4,也可能是2),入栈
pop 栈顶加4(不一定是4,也可能是2),出栈
十三、练习
1、先下断点,断点下的位置是窗口弹出
bp MessageBoxA
当输入错误的账号密码时,会弹窗,此时会断下来
2、找到调用函数的位置
当一个函数刚开始执行时,栈顶存储的调用函数返回的地址
3、在账号密码错误时,在下一个断点
4、找到调用函数的位置
5、在跳到弹出成功和失败的位置下断点
6、修改标志寄存器ZF位,并执行
7、为了下次随便输入账号密码也能成功登录将je改为jmp,并保存
十四、标志寄存器
1、CF位(无符号运算时)
进位标志CF(Carry F1ag) :如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。
11111111
add 00000001
-------------
00000000
一个8位的数字相加或相减,影响了第九位(进位或借位),CF位值为1
遇到的坑:
2、PF位
奇偶标志PF(Parity Flag):奇偶标志PF用于反映运算结果中“1 ”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。
遇到的坑:
3、AF位
在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:
(1)、在字操作时,发生低字节向高字节进位或借位时;
(2)、在字节操作时,发生低4位向高4位进位或借位时。
4、ZF位
零标志2F (Zero Flag):零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。
5、SF位
符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。
6、OF位
溢出标志0F (Overflow FISg): ``
溢出标志0F用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。
最高位进位与溢出的区别:
进位标志表示无符号数运算结果是否超出范围.
溢出标志表示有符号数运算结果是否超出范围.
遇到的坑:
比如80-48
mov al,8 0
sub al,40
相当于
Mov AL,80
ADD AL, OC0
1000 0000
1100 0000
符号位有进位: 1
最高有效数值位向符号位产生的进位: θ
1 xor θ == 1 所以 0F=1
十四、扩展指令
1、ADC指令
ADC指令:带进位加法
格式: ADC R/M, R/M/IMM
两边不能同时为内存宽度要一样
ADC AL, CL
ADC BYTE PTR DS:[12FFC4],2
ADC BYTE PTR DS:[12FFC4], AL
2、SBB
SBB指令:带借位减法
格式: SBB R/I, R/M两边不能同时为内存 宽度要一样
SBB AL,CL
SBB BYTE PTR DS: [12FFC4], 2
SBB BYTE PTR DS:[12FFC4], AL
3、XCHG
XCHG 交换数据
格式: XCHG R/M, R/M
两边不能同时为内存宽度要一样
XCHG AL,CL
XCHG DWORD PTR DS: [12FFC4], EAX
XCHG BYTE PTR DS:[12FFC4], AL
4、MOVS指令
MOVS指令:移动数据 内存-内存
BYTE/WORD/DWORD
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]
5、STOS指令
STOS指令:将A1/AX/EAX的值存储到[EDI]指定的内存单元
MOV EAX, 12345678
MOV EDI, 12FFC4
STOS BYTE PTR ES: [EDI]
STOS RORD PTR ES: [EDI]
ST0S DAORD PTR ES:[EDI]
6、REP指令
REP指令:按计数寄存器(ECXL) 中指定的次数重复执行字符串指令
十五、JCC
1、jmp
JMP指令:修改EIP的值
JMP 寄存器/立即数
2、call
3、ret
4、CMP
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结果并不保存到第一个操作数中。只是根据相减的结果来改变零标志位的,当两个操作数相等的时候,零标志位置1。
5、test
指令格式: TEST R/M, R/M/IMN
该指令在一定程序上和CMP指令时类似的,两个数值进行与操作,结果不保存,但是会改变相应标志位.
6、JCC
JE, JZ | 结果为零则跳转(相等时跳转) | ZF=1 |
---|---|---|
JNE,JNZ | 结果不为零则跳转(不相等时跳转) | ZF=0 |
JS | 结果为负则跳转 | SF=1 |
JNS | 结果为非负则跳转 | SF=0 |
JP,JPE | 结果中1的个数为偶数则跳转 | PF=1 |
JNP,JPO | 结果中1的个数为偶数则跳转 | PF=0 |
J0 | 结果溢出了则跳转 | 0F=1 |
JNO | 结果没有溢出则跳转 | 0F=0 |
JB,JNAE | 小于则跳转(无符号数) | CF=1 |
JNB, JAE | 大于等于则跳转(无符号数) | CF=0 |
JBE, JNA | 小于等于则跳转(无符号数) | CF=1 or ZF=1 |
JNBE, JA | 大于则跳转 (无符号数) | CF=0 and ZF=0 |
JL,JNGE | 小于则跳转(有符号数) | SF≠OF |
JNL,JGE | 大于等于则跳转(有符号数) | SF=0F |
JLE, JNG | 小于等于则跳转(有符号数) | ZF=1 or SF≠OF |
TNLB,TG | 大于则跳转(有符号数) | ZF=0 and SF=OF |
十六、堆栈平衡
1、外平栈
2、函数
计算机的函数,是一个固定的一个程序段,或称其为一个子程序,它在可以实现固定运算功能的同时还带有一入口和一个出口,所谓的入口,就是函数所带的各个参数,我们可以通过这个入口,把函数的参数值代入子程序,供计算机处理,所谓出口,就是指函数的计算结果,也称为返回值,在计算机求得之后,由此口带回给调用它的程序。.