二进制到汇编:进制,原码反码补码,位运算,通用寄存器,内存一套打通

1.语言


1.1 机器语言

人和人沟通的桥梁:语言
人与计算机打交道 --> 学习计算机的语言 --> 什么是机器语言

#我们目前主流的电子计算机!
状态: 01
#最早的程序员:穿孔卡带!
加 0100 0000
减 0100 1000
乘 0100 1000 0100 1000
除 0100 1000 1100 1000

1.2 汇编语言

这些复杂的机器语言的简化 --> 助记符:汇编语言 --> 人能够理解的语言转换成为机器能够理解的语言

加 INC -编译器-> 0100 0000
减 DEC           0100 1000
乘 MUL           0100 1000 0100 1000
除 DIV           0100 1000 1100 1000

离程序的本质:隔阂
汇编一般用于底层的编写,单片机…

1.3 C语言

加 A+B -编译器-> 0100 0000
减 A-B           0100 1000
乘 A*B           01001000 0100 1000
除 A/B           0100 1000 1100 1000

1.4 学习思路

image-20220728210206078

image-20220728205915915

2.进制


2.1 学习进制的障碍

  • 十进制 --> 人类天然的选择就是十进制,十个指头 --> 跳出固有思维的方法

  • 每一种进制都是完美的,都有自己的计算方式

2.2 进制类型

  • 1进制

    逢一进一,结绳记事

-2进制

逢二进一,计算机

-8进制

逢八进一,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 1
1 1 1
1 1 1 1
......

#二进制
0 1
10 11
100 101
110 111
1000 1001

# 三进制
0 1 2
10 11 12
20 21 22
100 101 102
110 111 112
120 121 122
......

# 七进制
0 1 2 3 4 5 6
10 11 12 13 14 15 16
20 21 22 23 24 25 26
......
60 61 62 63 64 65 66
100 101 102 103 104 105 106
...... 

2.3 进制的本质

  • 就是一组符号,逢几进几

  • 真实十进制:0 1 2 3 4 5 6 7 8 9 --> 10

    我的十进制:0 2 4 6 a o e f k q --> 20 (对应真实的10)

  • 加密解密:程序员 —— 破解程序的人 --> 进制的加密

    数字量一大,总是有规律的

  • 问题: 1 + 1 = 3 是对的吗? --> 用进制来回答这个问题

3.进制怎么运算


运算的本质就是 查数

八进制表:

01234567
1011121314151617
2021222324252627

八进制的乘法表:

1 * 1 = 11 * 2 = 21 * 3 = 31 * 4 = 41 * 5 = 51 * 6 = 61 * 7 = 7
2 * 2 = 42 * 3 = 62 * 4 = 102 * 5 = 122 * 6 = 142 * 7 = 16
3 * 3 = 103 * 4 = 143 * 5 = 173 * 6 = 223 * 7 = 25
4 * 4 = 204 * 5 = 244 * 6 = 304 * 7 = 34
5 * 5 = 315 * 6 = 365 * 7 = 43
6 * 6 = 446 * 7 = 52
7 * 7 = 61

八进制的加法表:

1 + 1 = 2
1 + 2 = 32 + 2 = 4
1 + 3 = 42 + 3 = 53 + 3 = 6
1 + 4 = 52 + 4 = 63 + 4 = 74 + 4 = 10
1 + 5 = 62 + 5 = 73 + 5 = 104 + 5 = 115 + 5 = 12
1 + 6 = 72 + 6 = 103 + 6 = 114 + 6 = 125 + 6 = 136 + 6 = 14
1 + 7 = 102 + 7 = 113 + 7 = 124 + 7 = 135 + 7 = 146 + 7 = 157 + 7 = 16
# 用八进制计算下面结果
277 + 333 = 632
276 * 54 = 20250
237 - 54 = 163  # 减法的本质就是加法 --> 237 + (-54)
234 / 4 = 47 # 除法的本质:除数乘以那个数最接近的结果即可

结论:无论是什么进制,本身都是有一套完美的运算体系的,我们都可以通过列表的方式将它计算出来

4.二进制


为什么学习理解二进制:

  1. 计算机使用二进制
  2. 寄存器、内存、位,底层的每一位都是有含义的 --> 汇编入门理解的基础

硬操作:达到极限了 --> 软操作的提升:追求语言的极限——并发语言

电子计算机:

# 二进制: 0 和 1
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 

5.数据宽度


计算机内存是有限制的 --> 给数据增加数据宽度

5.1 强类型语言

C,C++,Java都需要定义数据的类型 --> 计算机底层需要我们给这些数据定义宽度

单位大小
位(bit)0 - 1
字节(byte)0 - 0xFF
字(word)0 - 0xFFFF
双字(dword)0 - 0xFFFFFFFF

在计算机中,每个数据都需要给它定义类型 --> 即给它定义宽度,在内存中的宽度

5.2 弱类型语言

弱类型语言不需要去定义类型,直接 let var 定义,不需要区分类型 --> 这是因为编译器帮我们做了

6.有符号数和无符号数


6.1 无符号数规则

你这个数字是什么,那就是什么

二进制数: 1 0 0 1 1 0 1 0
转成十六进制:0x9A
转成十进制:154

6.2 有符号数规则

最高位是符号位:1代表负数,0代表正数

二进制数: 1 0 0 1 1 0 1 0
--> 如何进行转换 --> 涉及到原码、反码和补码

7.原码反码补码


有符号数的编码规则

7.1 原码

最高位为符号位,其余位 等于 这个数的绝对值的对应位

7.2 反码

  1. 正数:反码和原码相同
  2. 负数:符号位一定是1,其余位对原码取反

7.3 补码

  1. 正数:补码和原码相同
  2. 负数:符号位一定是1,反码 + 1
1
#原码 0 0 0 0 0 0 0 1
#反码 0 0 0 0 0 0 0 1
#补码 0 0 0 0 0 0 0 1

-1
#原码 1 0 0 0 0 0 0 1
#反码 1 1 1 1 1 1 1 0
#补码 1 1 1 1 1 1 1 1

-7
#原码 1 0 0 0 0 1 1 1
#反码 1 1 1 1 1 0 0 0
#补码 1 1 1 1 1 0 0 1

十进制加法: 3 + 5
#转成二进制运算
        1 0
      1 0 1
    --------
    1 0 0 0

如果看到一个数字,二进制的,需要先了解它是有符号数还是无符号数。

计算机的存储是按照补码的方式来存储的

8.位运算


计算机现在是可以存储所有的数字(整数,浮点数,字符)的。

8.1 为什么学习位运算

很多底层的调试器需要通过 位 来判断CPU的状态

8.2 位运算分类

8.2.1 与运算( and & )

全 1 为 1,否 则 为 0

#与运算
1011 0001
1101 1000
----------
1001 0000

8.2.2 或运算( or | )

全 0 才 0,否 则 为 1

#或运算
1011 0001
1101 1000
----------
1111 1001

8.2.3 异或运算( xor ^ )

不 同 为 1,相 同 为 0

#异或运算
1011 0001
1101 1000
----------
0110 1001

8.2.4 非运算( 单目运算符 not ~)

0 变 1,1 变 0

#非运算
1011 0001
----------
0100 1110

8.2.5 位运算(移动位)

左移:shl <<

高 位 溢 出,低 位 补 0

#所有二进制位全部左移若干位,高位就丢弃了,低位补0
0000 0001
#左移一位
0000 0010      

右移:shr >>

低位移除,符号位与高位一致

#所有二进制位全部右移若干位,低位就丢弃了,高位与符号位一致
1000 0001      
#右移两位
1110 0000

int a = -1;
printf("%d\n",a>>2);

二进制、位运算 --> 加减乘除

9.位运算实现加减乘除


计算机只认识 0 和 1

基本数学运算是建立在 加减乘除 基础上 --> 探究玩计算机加减乘除会发现 计算机只会做加法

9.1 加法

4 + 5 -->
#十进制转成二进制运算
0000 0100
0000 0101
----------
0000 1001
#以上加法过程,计算机是不会直接加的,这是我们人的计算方式

那么计算机是怎么操作的?

#计算机的实现原理
0000 0100
0000 0101
#第一步:异或,如果不考虑进位(即当异或出的结果全为1的时候),则可以直接出结果
0000 0100
0000 0101
----------- 异或
0000 0001

#第二步:与运算,判断进位,如果与运算结果全为0,说明没有进位
0000 0100
0000 0101
----------- 与
0000 0100

#第三步:将与运算的结果,左移一位,因为与运算结果中如果出现了1,说明有进位
0000 0100
--> 左移一位
0000 1000

#第四步:将 第一步的异或结果 与 第三步的移位结果 进行异或
0000 0001
0000 1000
------------ 异或
0000 1001

#第五步:对 第四步用来异或的两个数 进行与运算,目的是进行结果的确定(判断进位,如果与运算结果全为0,说明没有进位)
0000 0001
0000 1000
------------ 与
0000 0000

#因此最终结果就是与运算为0的结果的上一个异或结果

9.2 减法

4 + (-5)
-5 --> 原码: 1000 0101  -->  反码: 1111 1010  -->  补码: 1111 1011 
#因为在计算机底层,减法本质就是加法运算,因此运算步骤和加法一样

#第一步:异或,如果不考虑进位(即当异或出的结果全为1的时候),则可以直接出结果
0000 0100
1111 1011
---------- 异或
1111 1111  #全为1,说明没有进位,则可以直接出结果

#第二步:与运算,目的是进行结果的确定(判断进位,如果与运算结果全为0,说明没有进位)【对应上面的第五步】
0000 0100
1111 1011
----------- 与
0000 0000

#因此结果就是 1111 1111,变成16进制就是ff,变成10进制就是-1

9.3 乘法

x * y ,就是 y个x相加,因此本质还是加法

9.4 除法

x / y ,本质就是减法,就是 x 中最多能够减去多少个 y,而减法的本质还是加法

因此得出结论:计算机只会做加法

机器语言就是位运算,都是电路来实现的 --> 这就是计算机最底层的本质

通过机器语言可以来实现加法计算器,设计电路…

10.汇编语言环境说明


通过 指令 来代替我们的二进制编码

image-20220729011513601

  • 通过汇编指令可以给计算机发一些操作,然后让计算机执行。
  • 编译器的发展,让我们远离了底层。但真正底层的大佬,几乎都是最原始的IDE。
  • 在学习汇编前,需要先掌握环境的配置:
    1. Vc6(程序到汇编的理解)
    2. OD(反编译工具)
    3. 抓包工具
    4. 加密解密工具

学汇编不是为了写代码,是为了 理解程序的本质

image-20220729012629403

汇编入门:了解汇编和程序的对应关系,程序的本质即可

image-20220729012822832

11.通用寄存器


寄存器:

存储数据:CPU > 内存 > 硬盘

32位CPU:寄存器有 8 16 32 位

64位CPU:寄存器有 8 16 32 64 位

通用寄存器:可以存储任何东西

32位的通用寄存器只有8个,存值的范围 0 - FFFFFFFF,对于二进制来说,直接修改值

计算机如何向 寄存器 存值 --> mov指令

mov  存的地址,存的数
mov  存的地址1,存的地址1

可以将数据写入到寄存器,可以将寄存器中的值写到寄存器

计算机的核心:计算力

不同的寄存器:

32位(FFFFFFFF)16位(FFFF)8位(FF)
EAXAXAL
ECXCXCL
EDXDXDL
EBXBXBL
ESPSPAH
ENPNPCH
ESISIDH
EDIDIBH

注意:八位的寄存器,L低8位,H高八位

除去这些通用寄存器之外,其他的寄存器每一位都有自己特定的功能

12.内存


寄存器很小,不够用 --> 数据放到内存 --> 会买的内存条
在32位操作系统中,每个应用程序进程都有4GB的内存空间,但这是空头支票

image-20220729110623287

程序真正运行的时候,才会用到物理内存。

1B = 8bit
1KB = 1024B
1MB =1024KB
1GB = 1024MB

4G的内存,4096MB --> 最终计算为位,就是这个可以存储的最大容量

内存地址存一个数 --> 占用的大小,数据宽度,存到哪里?

计算机中内存地址很多,空间很大 --> 就需要给每个空间分配一个地址 / 名字。

image-20220729110525554

这些给内存起的编号,就是我们的内存地址。

32位8个16进制的值。32位:寻址能力是4GB。
FFFFFFFF+1 = 100000000,最大的值。

位是怎么限制内存大小的。
100000000内存地址*8 --> 位:800000000 --> 转换为10进制/8 --> 4,294,967,296字节
按照规则/1024,最终发现就是4GB
所以每个内存地址都有一个编号。

image-20220729110316912

数据宽度: byte word dword

不是任意的地址都可以写东西的,申请使用的。只有程序申请过的内存地址我们才可以使用。

#汇编如何向内存中写值。
mov 数据宽度 内存地址,1
#例如:在0x19FF70的内存地址存放一个数据宽度为byte的值为4
mov byte ptr ds : [0x19FF70],4  

--> 传递的值的大小一定要和数据宽度相等

image-20220729111501588

内存地址有多种写法

  • ds : [ 0x19FF70 + 4 ] 内存地址偏移
  • ds : [ eax ] 将寄存器的值写入到内存
  • ds : [ eax + 4 ] 寄存器偏移
  • 数组底层
    1. ds : [ reg + reg * { 1 , 2 , 4 , 8 } ]
    2. ds : [ reg + reg * { 1 , 2 , 4 , 8 } + 4 ] 偏移
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是谢添啊

感谢你的支持,我会继续加油的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值