底层原理基础01
语言
人和人沟通需要语言 人和计算机沟通 需要学习计算机的语言
什么是机器语言?
进制
进制?
1进制 逢1进一 结绳记事
2进制 逢2进一 计算机
八进制 逢8进一 八个符合组成 0 1 2 3 4 5 6 7
10进制 逢10进一 十个符号组成 0 1 2 3 4 5 6 7 8 9
16进制 逢16进一 十六个符号组成 0 1 2 3 4 5 6 7 8 9 a b c d e f
问题 你真的理解进制了吗? 1 + 1 = 3 对不对 如果你可以使用进制来解答这个问题 那么你就学会了
十进制 0 1 2 3 4 5 6 7 8 9
小刘的十进制 0 1 2 3 4 5 a b c d
加密解密 程序员 破解程序的人 是进制的加密
但是 数字量一大 总是有规律的
进制怎么运算
八进制加法表
| 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=11 | ||
| 1+6=7 | 2+6=10 | 3+6=11 | 4+6=12 | 5+6=12 | 6+6=13 | |
| 1+7=10 | 2+7=11 | 3+7=12 | 4+7=13 | 5+7=13 | 6+7=14 | 7+7=15 |
八进制乘法表
| 1*1=1 | 1*2=2 | 1*3=3 | 1*4=4 | 1*5=5 | 1*6=6 | 1*7=7 |
|---|---|---|---|---|---|---|
| 2*2=4 | 2*3=6 | 2*4=10 | 2*5=12 | 2*6=14 | 2*7=16 | |
| 3*3=11 | 3*4=14 | 3*5=17 | 3*6=22 | 3*7=25 | ||
| 4*4=20 | 4*5=24 | 4*6=30 | 4*7=36 | |||
| 5*5=31 | 5*6=36 | 5*7=43 | ||||
| 6*6=44 | 6*7=52 | |||||
| 7*7=61 |
运算的本质就是查数 根据对应的88乘法表来查数
二进制
二进制
0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111
二进制这样写很麻烦 二进制能否简写 十六进制
0 1 2 3 4 5 6 7 8 9 a b c d e f
数据宽度
计算机 内存 给数据增加数据宽度
C C++ Java都需要定义数据的类型 计算机的底层需要我们给这些数据定义宽度
位 0 1
字节 0 0xFF
字 0 0xFFFF
双字 0 0xFFFF FFFF
在计算机中 每一个数据都需要给它定义数据类型 给它定义宽度 在内存中的宽度
有符号数 和 无符号数
数据都是有宽度的 每个数据代表什么意思呢? 二进制
0 1 0 1 0 1 0 1
规则 二进制解码增加一个规则?
无符号规则 -->
你这个数字是什么 那就是什么
1001 1010 十六进制 0x9A
有符号规则 -->
最高位是符号位 1 (负数) 0 (正数)
1001 1010 如何转换?
原码反码补码
有符号数的编码规则
原码 最高位是符号位 对其他的位进行本身的绝对值就行
反码
- 正数 反码和原码相同
- 负数 符号位一定是1 其余位对源码取反
补码
- 正数 补码和原码相同
- 负数 符号位一定是1 反码+1
测试
6
# 原码 0 0000 0110
# 反码 1 1111 1001
# 补码 1 1111 1010
-6
# 原码 1 0000 0110
# 反码 1 1111 1001
# 补码 1 1111 1010
# 2进制的标志
2 10
4 100
8 1000
FF 255 1111 1111
如果看到一个二进制的数字 需要了解它是有符号数还是无符号数
位运算
位运算
2*8最高效的计算方式
很多底层的调试器 需要通过位来判断CPU的状态
与运算 ( and & ) --> 二目运算符 需要两个数字进行运算
1011 0001
1101 1000
---------- 与运算
1001 0000
或运算 ( or | ) --> 二目运算符 需要两个数字进行运算
1011 0001
1101 1000
----------- 或运算
1111 1001
异或运算 ( xor ^ ) --> 二目运算符 需要两个数字进行运算
不一样就是1 一样就是0
1可以理解为 亮灯 0可以理解为 不亮灯
1011 0001
1101 1000
----------- 异或运算
0110 1001
非运算 (not ~ ) --> 单目运算符
0就是1 1就是0
1101 1000
----------- 非运算
0010 0111
将原码变成反码的过程
通过这些可以完成加减乘除 通过位运算来实现加减乘除
位运算 ( 移动位 左移*2 右移/2)
左移 (shl <<)
0000 0001 所有的二进制位全部左移若干位 高位丢弃 , 低位补0
0000 0010
右移 (shr >>)
0000 0001 所有的二进制位全部右移若干位 低位丢弃 , 高位补0,1(符号位决定) 如果是负数就补1 正数补0
00000 000
0000 0010
00000 001
int a = 10;
printf("%d\n",a>>2);
位运算的加减乘除
4+5=?
# 计算机是怎么操作的
0000 0100
0000 0101
---------- 加法 但是计算机是不会直接加的 这样的加法过程是我们人自己加的
0000 1001
# 计算机的实现原理
# 第一步 异或 如果不考虑进位 异或就可以直接出结果
0000 0100
0000 0101
---------- 异或
0000 0001
# 第二步 与运算 判断进位 如果与运算结果为0 没有进位
0000 0100
0000 0101
---------- 与
0000 0100
# 第三步 将与运算的结果 左移一位 进位结果 0000 1000
0000 0100
---------- 左移<<
0000 1000
# 第四步 异或 将第一步异或的结果 第三步左移一位的结果 进行异或运算
0000 0001
0000 1000
---------- 异或
0000 1001
# 第五步 与运算 判断进位 如果与运算结果为0 没有进位
0000 0001
0000 1000
---------- 与
0000 0000
# 所以最终的结果就是 与运算为0的结果的上一个异或运算
4 + 5 = 9
0000 0100 + 0000 0101 = 0000 1001 = 9
4-5=?
# 计算机是怎么操作的
4+(-5)
0000 0100
1111 1011 0000 0101 取反加一 1111 1010 1111 1011
---------- 减法 但是计算机是不会直接减的 这样的加法过程是我们人自己加的
1111 1111 ff
---------- 补码
1000 0001
# 狂神思路
4+(-5)
0000 0100
1111 1011
---------- 减法
1111 1111
0000 0100
1111 1011
---------- 异或 如果不考虑进位 异或可以直接出结果
1111 1111
0000 0100
1111 1011
---------- 与 判断进位 如果与运算结果为0 没有进位
0000 0000
最终结果 1111 1111 HEX ff DEC -1
乘法 本质是加法 x*y y个x相加
除法 本质是减法 x/y x能减去多少个y
计算机只会做加法
机器语言就是位运算 都是电路来实现的 这就是计算机的底层本质
通过机器语言来实现加法计算器 设计电路
汇编语言
通过指令来代替我们的一些二进制编码
通过汇编指令可以给计算机发一些操作, 然后让计算机执行
编译器的发展 底层的大佬 几乎都是最原始的IDEA
学习C语言的正确方式 用linux学 使用vim编辑器 通过gcc来执行
学习底层需要去使用古老的东西
在学习汇编之前 需要先掌握环境的配置 1. Vc6(程序到汇编的理解) 2. OD 3. 抓包工具 4. 加密解密工具
学汇编不是为了写代码 是为了理解程序的本质
32位 64位 本质架构区别不大 寻址能力增强
可以直接学习32位的汇编
汇编入门 了解汇编和程序的对应关系 程序的本质即可
操作系统内核

浙公网安备 33010602011771号