1.1.进制
进制的定义: 八进制的定义:由八个符号组成,分别是01234567逢八进一。 十进制的定义:由十个符号组成,分别是0123456789逢十进一。 N进制的定义:由N个符号组成,逢N进一。
1.2、进制的运算
八进制运算
代码语言:javascript复制2 3=5
2*3=6
4 5=11
4*5=24
277 333= 632
276*54= 162
237-54= 20250
234/4= 47
#八进制:0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27
八进制加法表
代码语言:javascript复制2 3=5
2*3=6
4 5=11
4*5=24
277 333= 632
276*54= 162
237-54= 20250
234/4= 47
#八进制:0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27
八进制加法表
八进制乘法表
1.3.二进制简写形式
计算机为什么使用二进制 计算机是需要用电的,电路只有两种状态: 1真(通电) 0假(未通电) 计算机中存储的任何文件、接收的任何指令都是由0和1组成的
二进制与十六进制
代码语言:javascript复制0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
0 1 2 3 4 5 6 7 8 9 A B C D E F
1.4.数据宽度
数据宽度 数学上的数字,是没有大小限制的,可以无限的大。但在计算机中,由于受硬件的制约,数据都是有长度限制的(我们称为数据宽度),超过最大宽度的数据会被丢弃。
计算机中常见的数据宽度:
1)位(BIT) 1位 2)字节(Byte) 8位 3)字(Word) 16位 4)双字(Doubleword) 32位
存储范围: 字节(Byte): 0 ~ 0xFF 字(Word): 0 ~ 0xFFFF 双字:0~ 0xFFFFFFFF 如果要存储的数据超过最大宽度,那么多余的数据将被丢弃!
1.5.无符号数有符号数
无符号数的编码规则
代码语言:javascript复制10011010
十六进制:0x9A
十进制:154
有符号数的编码规则
代码语言:javascript复制正数编码规则(第一位是0),如果是正数就和无符号数编码规则一样
00011010
负数编码规则(第一位是1)
10011010
1.6.原码反码补码
有符号数的编码规则 原码:最高位为符号位,其余各位为数值本身的绝对值 反码: 正数:反码与原码相同 负数:符号位为1,其余位对原码取反 补码: 正数:补码与原码相同 负数:符号位为1,其余位对原码取反加1
代码语言:javascript复制-1
原码:10000001
反码:11111110
补码:11111111 (负数在计算机里面是采用补码的形势存储的)
-7
原码:10000111
反码:11111000
补码:11111001 (负数在计算机里面是采用补码的形势存储的)
1.7.计算机不会做加法
1.8.位运算之加减乘除
4 5=?的运算过程
4-5=?的运算过程
1.9.汇编环境安装
下载DTdebug工具,打开后设置UDD和plugin的路劲。Options-->Appearance
1.10.通用寄存器
1、寄存器 存储数据: CPU>内存>硬盘 32位CPU: 8 16 32 64位CPU: 8 16 32 64
2、通用寄存器 32位通用寄存器: EAX ESP ECX EBP EDX ESI EBX EDI
3、MOV指令 <1> 立即数到内存 <2>寄存器到内存 <3>内存到寄存器
按F8单步运行
4.通用寄存器
1.11.内存
2、内存地址 <1>内存太大没法起名字,所以只能用编号。当我们想向内存中存储数据,或者从内存中读取数据时,必须用到这个编号,就像写信必须要写收信人地址一样。 <2>这个编号又称为内存地址(32位,前面0可以省略)。
3、往内存中写入值
代码语言:javascript复制MOV DWORD PTR DS:[19FF90],12345678
# DWORD表示四个字节长度
#PTR DS:[19FF90]表示内存地址
1.12.内存地址的五种形式
1、形式一: [立即数] 读取内存的值: MOV EAX,DWORD PTR DS:[Ox13FFC4] 向内存中写入数据: MOV DWORD PTR DS:[0x13FFC4],EAX
2、形式二: [reg] reg代表寄存器可以是8个通用寄存器中的任意一个 读取内存的值: MOV ECX,0x13FFD0 MOV EAX,DWORD PTR DS:[ECX] 向内存中写入数据: MOV EDX,0x13FFD8 MOV DWORD PTR DS:[EDX],0x87654321
3、形式三: [reg 立即数] 读取内存的值: MOV ECX,0x1 3FFD0 MOV EAX,DWORD PTR DS:[ECX 4] 向内存中写入数据: MOV EDX,0x13FFD8 MOV DWORD PTR DS:[EDX 0xC],0x87654321
4、形式四: [reg reg*{1,2,4,8}] 读取内存的值: MOV EAX,13FFC4 MOV ECX,2 MOV EDX,DWORD PTR DS:[EAX ECX4] 向内存中写入数据: MOV EAX,13FFC4 MOV ECX,2 MOV DWORD PTR DS:[EAX ECX4],87654321
5、形式五: [reg reg*{1 ,2,4,8} 立即数] 读取内存的值: MOV EAX,13FFC4 MOV ECX,2 MOV EDX,DWORD PTR DS:[EAX ECX4 4] 向内存中写入数据: MOV EAX,13FFC4 MOV ECX,2 MOV DWORD PTR DS:[EAX ECX4 4],87654321
1.13.存储模式
2、DTDEBUG内存窗口的使用 <1>分别以字节/字/双字形式来查看内存(db dw dd)
<2>向内存中写入四个字节的数据,并观察存储形式(大端存储/小端存储)
1.14.常用汇编指令
1、MOV指令 指令格式: 1、MOV r/m8,r8 r通用寄存器 2、MOV r/m16,r16 m代表内存 3、MOV r/m32,r32 ; imm代表立即数 4、MOVr8,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, imm16 9、MOV r32, imm32
2、ADD指令 指令格式: 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
3、SUB指令 指令格式: SUB r/m8, imm8 SUB r/m1 6,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、AND指令 AND r/m8, imm8 AND r/m16,imm16 AND r/m32,imm32 AND r/m16, imm8 AND r/m32, imm8 AND r/m8, r8 AND r/m16, r16 AND r/m32, r32 AND r8, r/m8 AND r16, r/m16 AND r32, r/m32
5、OR指令 OR r/m8, imm8 OR r/m16 ,imm16 OR r/m32,imm32 OR r/m16, imm8 OR r/m32, imm8 OR r/m8, r8 OR r/m16, r16 OR r/m32, r32 OR r8, r/m8 OR r16, r/m16 OR r32, r/m32
6、XOR指令 XOR r/m8, imm8 XOR r/m16,imm16 XOR r/m32 ,imm32 XOR r/m16, imm8 XOR r/m32, imm8 XOR r/m8, r8 XOR r/m16, r16 XOR r/m32, r32 XOR r8, r/m8 XOR r16, r/m16 XOR r32, r/m32
7、NOT指令 NOT r/m8 NOT r/m16 NOT r/m32
1.15.内存复制指令
1、MOVS指令:移动数据内存-内存 BYTENWORD/DWORD MOVS BYTE PTR ES:[EDJ,BYTE PTR DS:[ESI] 简写为: MOVSB MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] 简写为: MOVSW MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 简写为: MOVSD
例子: . MOV EDI,12FFD8 MOV ESI,12FFD0 MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 观察EDI的值 修改标志寄存器中D位的值,然后在执行下面的指令: MOV EDI,12FFD8 MOV ESI,12FFD0MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
2、STOS指令: 将AI/AX/EAX的值存储到[EDI]指定的内存单元 STOS BYTE PTR ES:[EDI] 简写为STOSB STOS WORD PTR ES:[EDI] 简写为STOSW STOS DWORD PTR ES:[EDI] 简写为STOSD
例子:
MOV EAX, 12345678 观察EDI的值 MOV EDI, 12FFC4 STOS BYTE PTR ES:[EDI] STOS WORD PTR ES:[EDI] STOS DWORD PTR ES:[EDI] 修改标志寄存器中D位的值,然后在执行下面的指令: MOV EAX, 12345678 观察EDI的值 MOV EDI, 12FFC4 STOS BYTE PTR ES:[EDI] STOS WORD PTR ES:[EDI] STOS DWORD PTR ES:[EDI]
3、REP指令: 按计数寄存器(ECX)中指定的次数重复执行字符串指令 MOV ECX,10 REP MOVSD REP STOSD
1.16.堆栈相关指令
1、什么是堆栈? 1)就是一块内存,操作系统在程序启动的时候已经分配好的,供程序执行时使用。 2)和数据结构的堆栈无关。 3)查看堆栈。
2、栈指针寄存器 ESP中存储了当前的堆栈用到哪里了
3、堆栈的使用 <1>存储数据 <2>修改栈顶指针
4、PUSH指令 <1>向堆栈中压人数据 <2>修改栈项指针ESP寄存器 指令格式: 1、PUSH r32 2、PUSH r16 3、PUSH m16 4、PUSH m32 5、PUSH imm8/imm1 6/imm32
5、POP指令: <1>将栈顶数据存储到寄存器/内存 <2>修改栈项指针ESP寄存器 指令格式:| 1、POP r32 2、POPr16 3、POP m16 4、POP m32
1.17.修改EIP的指令
1、JMP指令: MOV EIP,寄存器/立即数/内存 简写为 JMP寄存器/立即数/内存
2、CALL指令: PUSH下一行地址 MOV EIP,立即数/寄存器/内存 简写为: CALL立即数/寄存器/内存 与JMP唯--的区别: 在堆栈中存储Call指令下一-行地址
3、RET指令: ADD ESP,4 MOV EIP,[ESP-4]
简写为: RET
1.18.汇编眼中的函数
1、什么是函数 函数就是一系列指令的集合,为了完成某个会重复使用的特定功能。 例子:向寄存器中赋值
2、如何执行一个函数?即函数调用 <1>用JMP来执行函数 <2> 用CALL来执行函数
3、 什么是参数?什么是返回值? 例子:编写一个函数,能够得到任意2个整数的值。
1.19.堆栈平衡
什么是堆栈平衡? 1)如果要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入栈中的地址。 2)如果通过堆栈传递参数了,那么在函数执行完毕后,要平衡参数导致的堆栈变化。
1.20.JCC指令
1、JE, JZ 结果为零则跳转(相等时跳转) ZF=1 2、JNE, JNZ 结果不为零则跳转(不相等时跳转) ZF=0 3、JS 结果为负则跳转 SF=1 4、JNS 结果为非负则跳转 SF=0 5、JP, JPE 结果中1的个数为偶数则跳转 PF=1 6、JNP, JPO 结果中1的个数为偶数则跳转 PF=0 7、J0 结果溢出了则跳转 0F=1 8、JNO 结果没有溢出则跳转 0F=0
9、JB, JNAE 小于则跳转(无符号数) CF=1 10、JNB, JAE 大于等于则跳转(无符号数) CF=0 11、JBE, JNA 小于等于则跳转(无符号数) CF=1 or ZF=1 12、JNBE, JA 太于则跣转(无符号数) CF=0 and ZF=0中 13、JL, JNGE 小于则跳转(有符号数) SF≠OF
14、JN, JGE 大于等于则跳转(有符号数) SF=OF 15、JLE, JNG 小于等于则跳转(有符号数) ZF=1 or SF≠0F 16、JNLE, JG 因于则来转(有符号数) ZF=0 and SF=OF
1、标志寄存器:EFLAGS
2、CF (bit 0) [Carry fiag] 若算术操作产生的结果在最高有效位(most-significant bit)发生进位或借位则将其置1,反之清零。 这个标志通常用来指示无符号整型运算的溢出状态。
例: MOV AL,0xFE MOV AL,0x7F ADD AL,2 或者 SUB AL ,0xFF
3、PF(bit 2) [Parity flag] 如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零。
利用PF可进行奇偶校验检查: 需要传输"11001110",数据中含5个"1", 所以其奇校验位为"0",同时把"110011100"传输给接收方,接收方收到数据后再- - 次计算奇偶性,"110011100"中仍然含有5个"1",所以接收方计算出的奇校验位还是"0",与发送方一致,表示在此次传输过程中未发生错误
例子: MOV AL,OCE ADDAL,0
4、AF(bit 4) [Adjust Flag] 如果算术操作在结果的第3位发生进位或借位则将该标志置1,否则清零。 这个标志在BCD(binary-code decimal)算术运算中被使用。
5、ZF(bit 6) [Zero flag] 若结果为0则将其置1,反之清零。 经常与CMP或者TEST等指令-起使用:
例1:判断2个值是否相等
MOV EAX, 100 MOV ECX, 100 CMP EAX, ECX (CMP指令相当干SUB指令.但是相减的结果并不保存到第一个操作数中)
例2:判断某个值是否为0 TEST EAX,EAX (TEST指令相当于AND指令,但是与的结果并不保存到第-一个操作数中)
6、SF(bit 7) [Sign flag] 该标志被设置为有符号整型的最高有效位。 (0指示结果为正,反之则为负) 例子: MOV AL ,0x7F MOV AL ,0xFE ADD AL,2 ADDAL,2
7、OF(bit 11) [Overflow flag] 溢出标志OF用于反映有符号数加减运算所得结果是否溢出。
可以这样理解: 如果是无符号数运算,是否溢出看CF位。 如果是有符号数运算,是否溢出看OF位。 例子: MOV AL ,0x7F ADD AL,2
8、DF(bit 10) [Direction Flag] 这个方向标志控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)。设置DF 标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使 得串指令自动递增。 STD以及CLD指令分别用于设置以及清除DF标志。