【滴水基础】1.汇编语言(上)
一:进制
1进制的定义:由1个符号组成(不一定为数字1,可以是其它字符a\b\c等),逢1进1
0=0;1=1;2=11;3=111;4=1111
2进制的定义:由2个符号组成(不一定为数字0、1,可以是其它字符a\b\c等),逢2进1
0=0;1=1;2=10;3=11;4=100;5=101;6=110;7=111;8=1000;
3进制的定义:由3个符号组成(不一定为数字0、1、2,可以是其它字符a\b\c\d等),逢3进1
0=0;1=1;2=2;3=10;4=11;5=12;6=20;7=21;8=22;9=100;10=101;11=102;12=110;13=111;14=112;15=120;16=121;17=122;18=200;19=201;20=202
7进制的定义:由7个符号组成(不一定为数字0、1、2、3、4、5、6,可以是其它字符a\b\c\d等),逢7进1
0,1,2,3,4,5,6,
10,11,12,13,14,15,16(13)
20,21,22,23,24,25,26(20)
问题:1+1=3对吗?
答:进制定义不同,如果十进制定义为:0,1,3;则1+1=3
应用:进制的加密解密
二:进制运算
进制本质:查数(每一个进制都有自己独立的体系)
八进制的运算:
0,1,2,3,4,5,6,7
10,11,12,13,14,15,16,17(15)
20,21,22,23,24,25,26,27(23)
2+3=5:从2向后查3个数
2*3=6:2个3或者3个2,在3后面再查3个数
4+5=11:从4往后再查5个数
4*5=24:4个5或者5个4
总结:
(1) 进制的本质是查数
(2) 十进制运算轻松的原因:十进制加减乘除表
八进制的加法表:
1+1=2
1+2=3 2+2=4
1+3=4 2+3=5 3+3=6
1+4=5 2+4=6 3+4=7 4+4=10
1+5=6 2+5=7 3+5=10 4+5=11 5+5=12
1+6=7 2+6=10 3+6=11 4+6=12 5+6=13 6+6=14
1+7=10 2+7=11 3+7=12 4+7=13 5+7=14 6+7=15 7+7=16
八进制乘法表:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=11
1*4=4 2*4=10 3*4=14 4*4=20
1*5=5 2*5=12 3*5=17 4*5=24 5*5=31
1*6=6 2*6=14 3*6=22 4*6=30 5*6=36 6*6=44
1*7=7 2*7=16 3*7=25 4*7=34 5*7=43 6*7=52 7*7=61
277+333=?
7向后移动3位为12,故进1个bit位;第二个bit位同样12+1为13,向前进1个bit位;2+3+1=6,故277+133=632
236-54=?
6向前移动4位为2,13向前移动5位为6,2向前移动1位为1,故236-54=162
276*54=?
4个6=十进制的24/八进制的30;4个7=十进制28/八进制34;4个2=10;根据bit位添加0,则 30+340+1000=1370(这里是八进制相加);
同理,5个6=36;5个7=43;5个2=12,根据bit位置添加0,则36+430+1200=466+1200=1666;
同理,根据bit位置添加0,16660+1370=?,6+7=15,3+6=11,1+6=7,再次根据bit位置添加0:
即150+1100+7000+10000=1250+7000+10000=10250+10000=20250
234/4=?
230/4=40余34(先23转化为十进制19除以4为4余3);34(转换十进制24+4=28)/4=7,则234/4=40+7=47
问题:计算机为什么要使用2进制:
计算机信号在物理层的传输是通过电信号,而电信号受到硬件的制约,只有正负极。
二进制的书写:
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
为什么要使用十六进制:
一个十六进制,相当于4比特的2进制,可以更好的显示汇编
三:数据宽度
数据宽度定义:在计算机中,由于硬件制约,超过最长宽度的数据会被丢弃。
计算机常用的数据宽度:
(1) 位(比特):bit 大小:1 bit 十六进制表示:0-1
(2) 字节:byte 大小:8bit 十六进制表示:0-FF
(3) 字:word 大小:16bit 十六进制表示:0-FFFF
(4) 双字:doubleword 大小:32bit 十六进制表示:0-FFFFFFFF
四:有符号数、无符号数
背景:不同格式的文件,如exe、txt等都会转化为2进制进行存储,那么如何从计算机中存储的二进制数据中,区分出原始文件的不同格式?
(1) 无符号数编码规则:和传统的十六进制一样
(2) 有符号数编码规则:
例如:对于十六进制进行解析:0x1A 000 000
无、有符号解析(最高位为0,无符号和有符号解析相同):
00001 1010 0000 0000 0000 0000 0000 0000
如果是负数0x9A:
无符号解析:1001 1010(最高位1,十进制:16*9+10=154)
有符号解析:1001 1010(最高位1为负数,十进制:-(2^4+2^3+2^1)=-26)
有符号数的取值范围:
五:原码、反码、补码
有符号数编码规则:
(1) 原码:最高位为符号位,其余数值为本身的绝对值
(2) 反码:
(3) 补码:
例如(以字节为单位):
6=》0000 0110;原码=反码=补码
-1=》原码:1000 0001
反码:1111 1110 补码:1111 1111
计算机对于数据的存储方式:
例如(十六进制表示):
char x=1,在内存中存储为01
char x=-1,在内存中存储为FF
假设数据宽度为1byte=8bit(现实一般为32位,即1dword):
无符号数:0,1,2……FF(十进制:[0,255])
有符号数:
正数:0……7F
负数:FF……80
计算机的取值宽度(1byte):
计算机的取值宽度(1dword):
总结:
(1) 了解计算机如何存储整数,那么浮点数、字母、汉字是如何存储?
答:C语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit, double数据占用64bit。无论是单精度还是双精度在存储中都分为三个部分:
符号位(Sign) : 0代表正,1代表为负
指数位(Exponent): 用于存储科学计数法中的指数数据,并且采用移位存储
尾数部分(Mantissa):尾数部分
其中,float存储方式:
double存储方式:
1:计算机如何存储英文字符:
ASCLL:对英文字母和符号进行了编码,总计28个
LATIN-1:兼容ASCLL,同时对欧洲符号进行编码,总共有256个
2:计算机如何存储中文字符:
GB2312:兼容ASCLL,对常用6000多汉字进行了编码
GBK:对两万多汉字进行了编码,兼容GB2312
BIG5:兼容ASCLL,台湾繁体字编码
3:Unicode:对世界上主流国家常用的语言进行了编码,兼容ASCLL,不兼容GB2312,GBK。。。。
具体存储方案:UTF-8 UTF-16 UTF-32
(2) 计算机只认识二进制,如何进行加减乘除的运算
答:通过位运算来计算
六:计算机不会做加法
为什么要学习位运算:1.有些功能需要通过位运算,如调试器等2.高等的四则运算
(1)与运算(and):两个位都为1时,结果才为1
—在电路图中表现为串联电路
(2)或运算(or):只要1个1就为1
—在电路图中用并联表示
(3)异或运算(xor):不一样的时候为1
—在电路图中表现为交叉电路图
(4)非运算(not):0就是1,1就是0,是单目运算(只需要1个数就可以运算)。
—1101 1000
—not(~) 0010 0111
(5)左移(<<):各二进制位全部左移若干位,高位丢弃,低位补0
—shl(<<) 1101 1000
—左移2位:0110 0000
(6)右移(>>):各二进制位全部右移若干位,低位丢弃,高位补0或者补符号位1
—shl(>>) 1101 1000
—右移2位:0011 0110
—int:整形,宽度为32bit
—unsigned:无符号数
—%d\n:输入输出的格式字符串,这里表示以10进制表示,\n为换行
—a>>2:整型变量a向右移动2个bit
—int:默认为有符号数
—最高位为1,则补1(注意:2个bit都补1)
总结:计算机只能做位运算,即加减乘除都无法直接计算
七:位运算之加减乘除
4+5=?的运算过程
—总结:在不考虑进位的情况下,异或的结果等于相加的结果
—例如:下面极端情况相等
—step1:异或
—step2:判断是否存在进位(判断是否都为1,都为1才有进位)
—通过与运算(and)来判断
—step3:将异或运算的结果和与运算的结果(左移1bit),再次异或
—step4:再次判断是否存在进位(通过与运算判断)
—这里还是判断step1和step2(左移1bit)的值
—这里全为0,故不存在进位
—总结:
4-5=?的运算过程
—4-5=4+(-5)
—注意:负数在计算机中以补码的形式存储
—(-5)原码:1000 0101;反码:1111 1010;补码1111 1011
—step1:异或
— step2:与运算(不存在进位)
—迭代结束
—4-5=4+(-5)=FF=-1
总结:
(1) 乘法运算本质:X*Y=Y个X相加
(2) 除法运算本质:X/Y=X能减去多少个Y
(3) 任何复杂运算本质=四则运算=加减法=位运算
八:汇编学习环境的搭建
学习汇编的目的:
—开发:了解c语言和汇编的关系
—安全:了解汇编和二进制的关系(前者也需要了解)
DTDebug下载:https://www.bcdaren.com/download
DTDebug界面:
—如果F8失效,加上Fn一起按即可
—要以管理员打开,然后需要配置路径才不会报错
—随意打开一个exe文件,pause表示程序暂停
进来后可以稍微拖动拖动界面,变成自己喜欢的分布,大致分为四个区域:
1、左上为反汇编代码区
2、右上角为寄存器区
3、左下角为内存区
4、右下角为堆栈区
—写入代码,按F8单步步过
—寄存器内容改变
—EIP指向反汇编窗口中,cpu即将执行的程序地址
九:通用寄存器
计算机存储数据(读取速度逐渐下降):cpu > 内存 > 硬盘
—根据cpu的类型不同,提供不同的数据存储
—32位cpu:8bit/16bit/32bit
—64位cpu(2005之后都是64位cpu):8bit/16bit/32bit/64bit
32位通用目的寄存器的指定用途如下:
—不能超过32位,超过部分会被丢弃
EAX:累加器(Accumulator),一般存储调用函数的结果
ECX:计数器(Counter),REP重复执行的时候判断执行次数
EDX:I/O指针,数据寄存器(data)
EBX:DS段的数据指针,基址寄存器(base)
ESP:栈顶指针寄存器(Stack pointer)
EBP:栈底指针寄存器(base pointer)
ESI:字符串操作的源地址(Source index)指针
EDI:字符串操作的目标地址(Destination index)指针
汇编的本质:通过指令,让数据在寄存器/内存/堆栈中来回流动
MOV指令:
—立即数到寄存器:
—向EAX存入1:mov eax,1
—向ECX存入1:mov ecx,1
—寄存器到寄存器
—将eax的内容存入edx:mov edx,eax
eax可以分成4个部分:eax共0~31(32位), ecx,edx,ebx寄存器类似
—其中0~7位叫作AL,low表示低位
—8~15位叫作AH,high表示高位
—整个0~15位又称为AX
—32位的寄存器有8个,分别是:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI,每个寄存器都有一个编号,分别是:0号,1号,2号,3号等。
—16 位寄存器也有属于自己的独立的编号。当然,他们是重叠的,当改变了 32 位的寄存器,相应的 16 位寄存器也会跟着改变。
—同样8位寄存器,第 0 号 AL,第 1 号,CL,DL,BL,AH,CH,DH,BH。
—当然还有两个寄存器:EIP 和 EFLAGS(又称为 EFL),8 号和 9 号寄存器
—EIP 有 16 位,叫做 IP。EFL 的 16 位称为 FL。这两个寄存器使用相对较少。
通用寄存器即 cpu 常用的寄存器,主要实现逻辑和算术运算、地址计算和内存指针。
—注意:只有EAX,ECX,EDX,EBX存在八位寄存器
—注意:反汇编界面是十六进制
—可以明显看到高位、低位的变化
—寄存器之间的数据传输,数据的位数必须一样
—如,8位寄存器只能和8位寄存器之间传输,这里8位寄存器赋值16位寄存器就会报错
—应该改为:mov bx,cx
作者:沙漠里的鲸 https://www.bilibili.com/read/cv19200539/ 出处:bilibili