什么是机器语言
- 计算机只认识0和1,机器语言就只包括0和1,很难。
什么是汇编语言
- 一些指令集,依靠编译器可以将汇编语言转化为机器语言。
什么是高级语言
- c、c++等,更加贴合人类的思维方式。仍然需要编译器进行转化为机器语言。高级的实质上就是编译器变得高级了。c和c++本质上是没有区别的,只是编译器做了更多的事情。
学习环境
- vc6,其他的也可以,不过只要是做底层的人一定是使用的是vc6的开发环境,因为越高版本的开发环境在编译的时候添加的额外代码越多,不利于我们的学习,因此,我们选择的开发环境是vc6
进制
-
为什么要学习进制,以及进制学习的误区
为了更好的理解计算机,需要对进制有更加深入的认识,学习进制的时候往往需要先转成十进制,这就是误区
-
进制的定义
n进制的本质定义:由
任意n个符号
组成,逢n进1。思考1+1=3对吗:如果我们定义十进制的时候用的是这种定义方式:0 1 3 2 …分别代表真正十进制中的 0 1 2 3…那么1+1=3是成立的。 -
进制的计算
进制的计算的实质就是查数比如:1+2就是从1开始数2个数,就是1+2的结果。我们在进行十进制的加减乘除计算的时候,实际上就是加法,乘法表的原因,因此在计算其他进制的时候,先做加法,乘法表,然后分位进行计算即可。
-
二进制的简写形式
-
计算机为什么使用二进制
计算机是需要电的,电路状态只有1 真(通电) 0 假(未通电)
-
16进制就可以看成2进制的简写形式,16进制有4位,因此2个二进制数就是一个字节
作业:
熟练掌握16进制和二进制之间的转换
A:1010
D:1101
E:1110
B:1011
F:1111
C:1100
9:1001
8:1000
7:0111
6:0110
5:0101
4:0100
2:0010
1:0001
3:0011
数据宽度
在计算机中,由于硬件的制约,数据都是有长度限制的(我们称为数据宽度), 超过最多宽度的部分会被丢弃
计算机中常见的数据宽度
-
位(bit):只能存0或者1
-
字节(byte): 1byte = 8bit,而1个16进制可以使用4bit来表示,因此可以存储的数据宽度是0-0xFF
-
字(word): 1word = 16bit , 因此word可以存储的数据宽度是0-0xFFFF
-
双字(Doubleword):1doubleword = 32bit 因此doubleword可以存储的数据宽度是0-0xFFFFFFFF
-
一旦计算机存储的数据超过最大宽度的时候,那么多余的部分会被丢弃
有符号数和无符号数
在内存中如果存在一个字节的空间,其存储的值如下,请问这些数据代表的是什么意思呢?
bit | bit | bit | bit | bit | bit | bit | bit |
---|---|---|---|---|---|---|---|
0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
答案:无法确定,因为计算机只认识0和1,不管是视频文件和文本文件或者是图片文件,其存储的本质都是0和1,因此只知道某一字节的值,是不能确定其存储的是什么的。需要根据相应的编码规则来进行解析。
- 情况一:上面的1个字节的空间存储的是一个无符号整数
对于一个无符号数来说,其值是什么,就存什么,因此上面一个字节的内存空间存储的是数:0x55
- 情况二:上面的1个字节的空间存储的是一个有符号整数
如果是一个有符号的整数的话,看二进制最高位是0还是1, 1代表负数,0代表正数,如果是正数的话,它的编码规则和无符号数是一样的(是什么存什么),因此代表的是:0x55
如果最高为是1的话,代表的是负数,其编码规则就变了,在讲这个编码规则之前先看几个概念。
原码、反码、补码
-
原码:最高位为符号位,其余各位为数值本身的绝对值
-
反码:
- 正数:反码与原码相同
- 负数:符号位 为1,其余位对原码取反
-
补码:
1. 正数:补码与原码相同
- 负数:符号位不变,其余位对原码取反后+1(也就是补码+1)
重点:当指定在一个内存空间中存储的是有符号的数时,实际上存储的是这个数的补码形式,无论这个数是正还是负。
计算机中的位运算
计算机不会进行加减乘除运算,也不认识这些运算符,所有的运算都是基于位运算来实现的,计算机中的位运算有以下几种:
- 与运算:两个位均为1时,结果才是1
1011 0001
and(&) 1101 1000
-----------------------
1001 0000
- 或运算:有1为1
1011 0001
or(|) 1101 1000
-----------------------
1111 1001
- 异或运算:相同为0,不同为1
1011 0001
xor(^) 1101 1000
-----------------------
0110 1001
- 非运算:按位取反,1的反是0,0的反是1(只需要一个操作数,又称为单目运算)
not(~) 1011 0001
-----------------------
0100 1110
- 左移:高位丢弃,低位补0
shl(<<) 1011 0001 左移两位
-----------------------
1100 0100
- 右移:低位丢弃,高位补0或者符号位
在汇编中,右移有两种:
1. shr:低位舍弃,高位补0
2. sar:低位舍弃,高位补符号位
在c语言中,右移符号只有一种:>>
1.这样定义a时,其右移是高位补0
unsigned int a = 10
那么右移的计算如下
0000 0000 0000 0000 0000 0000 0000 1010 >> 2:
0000 0000 0000 0000 0000 0000 0000 0010
2.这样定义a时,其右移是高位补符号位
int a = 10 // 默认有符号的
那么右移的结果就是:
0000 0000 0000 0000 0000 0000 0000 1010 >> 2:
0000 0000 0000 0000 0000 0000 0000 0010 // 这里高位补的就是符号位而不是0
计算机如何计算加减乘除
- 计算加法原理(举例说明)
// 4 + 5 = ?
1、计算 异或 值(假设数据宽度是1字节):如果不存在进位的话,那么异或值就是加法值
0000 0100
xor 0000 0101
----------------
0000 0001
2、判断是否有进位情况,以及进位的位置:进位只可能发生在都是1的情况下,因此可以使用与运算来判断进位位置
0000 0100
and 0000 0101
----------------
0000 0100
3、如果与运算的结果不是0,那么就存在进位情况,那么异或结果不是异或值,那么需要再次将异或值与进位之后的值(也就是与运算的结果左移一位)做重复加法运算,直到与运算结果是0为止
0000 0001
xor 0000 1000
---------------------
0000 1001
4、再次做与运算
0000 0001
and 0000 1000
-----------------
0000 0000
5、与运算结果为0,因此异或结果就是加法结果,也就是4 + 5 = 0000 1001 也就是十进制的9
- 减法的本质就是做加法
// 4 - 5 =4 + (-5) 同样假设数据宽度为1字节
// -1在内存中存储的是FF也就是1111 1111 同理得:-2:FE -3:FD -4:FC -5:FB
0000 0100
xor 1111 1011
------------------
1111 1111
0000 0100
and 1111 1011
------------------ // 与运算结果是0 因此4-5=1111 1111 也就是10进制中的-1
0000 0000
- 乘除法的本质也是做加法
汇编语言
我们主要学习32位汇编也就是x86, 64位cpu与32位cpu相比并没有整体架构的变化,因此x86汇编是x64汇编学习的基础。
通用寄存器
在计算机中有三个地方可以存储数据,1.cpu 2.内存 3.磁盘,寄存器就是cpu中存储数据的地方
寄存器的大小取决于cpu的位数,比如你的cpu是32位的话,那么它提供的寄存器就有32位的,16位的,8位的,如果你的cpu是64位的话,那么它提供的寄存器就有8位, 16位,32位,64位的这四种类型。
-
通用寄存器
-
通用寄存器(32位cpu提供三种类型的寄存器,除了这几种通用寄存器之外的寄存器都有某种特定的功能)
-
对于不同类型的寄存器实际上就是同一个寄存器我们可以按照它的不同的段来使用。
32位通用寄存器 16位通用寄存器 8位通用寄存器 EAX AX AL EBX BX BL ECX CX CL EDX DX DL EBP BP CH ESP SP AH EDI DI BH ESI SI DH -
通用寄存器的使用
-
mov指令:
- 1.可以将一个立即数(普通的数)存到寄存器中 :mov ecx, 2
- 2.也可以把其他寄存器中的值存到寄存器中:mov edx,eax:就是将eax寄存器中的值存到edx寄存器中。
-
-