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

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

1.语言


1.1 机器语言

人和人沟通的桥梁:语言

人与计算机打交道 --> 学习计算机的语言 --> 什么是机器语言

#我们目前主流的电子计算机!
状态: 0 和 1
#最早的程序员:穿孔卡带!
加 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 学习思路

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.进制怎么运算


运算的本质就是 查数

八进制表:

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 * 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 = 10 3 * 4 = 14 3 * 5 = 17 3 * 6 = 22 3 * 7 = 25
4 * 4 = 20 4 * 5 = 24 4 * 6 = 30 4 * 7 = 34
5 * 5 = 31 5 * 6 = 36 5 * 7 = 43
6 * 6 = 44 6 * 7 = 52
7 * 7 = 61

八进制的加法表:

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
# 用八进制计算下面结果
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.汇编语言环境说明


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

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

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

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

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)
EAX AX AL
ECX CX CL
EDX DX DL
EBX BX BL
ESP SP AH
ENP NP CH
ESI SI DH
EDI DI BH

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

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

12.内存


寄存器很小,不够用 --> 数据放到内存 --> 会买的内存条

在32位操作系统中,每个应用程序进程都有4GB的内存空间,但这是空头支票

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

1B = 8bit

1KB = 1024B

1MB =1024KB

1GB = 1024MB

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

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

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

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

32位8个16进制的值。32位:寻址能力是4GB。

FFFFFFFF+1 = 100000000,最大的值。

位是怎么限制内存大小的。

100000000内存地址*8 --> 位:800000000 --> 转换为10进制/8 --> 4,294,967,296字节

按照规则/1024,最终发现就是4GB

所以每个内存地址都有一个编号。

数据宽度: byte word dword

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

#汇编如何向内存中写值。
mov 数据宽度 内存地址,1
#例如:在0x19FF70的内存地址存放一个数据宽度为byte的值为4
mov byte ptr ds : [0x19FF70],4  
--> 传递的值的大小一定要和数据宽度相等

内存地址有多种写法

  • 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 ] 偏移


相关文章
|
20天前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
39 6
|
6月前
|
存储 程序员 存储控制器
【读书笔记】汇编语言(第四版)第二章 寄存器
【读书笔记】汇编语言(第四版)第二章 寄存器
|
6月前
汇编语言(第四版) 实验一 查看CPU和内存,用机器指令和汇编指令编程
汇编语言(第四版) 实验一 查看CPU和内存,用机器指令和汇编指令编程
102 1
8086 汇编笔记(十):标志寄存器
8086 汇编笔记(十):标志寄存器
|
5月前
|
编译器
8086 汇编笔记(六):更灵活的定位内存地址的方法
8086 汇编笔记(六):更灵活的定位内存地址的方法
|
7月前
|
存储
8086 汇编笔记(二):寄存器(内存访问)
8086 汇编笔记(二):寄存器(内存访问)
|
7月前
|
存储
8086 汇编笔记(一):寄存器
8086 汇编笔记(一):寄存器
|
6月前
|
程序员 索引
逆向学习汇编篇:内存管理与寻址方式
逆向学习汇编篇:内存管理与寻址方式
61 0
|
6月前
|
存储 C语言
C语言---求一个整数存储在内存中的二进制中1的个数--3种方法
C语言---求一个整数存储在内存中的二进制中1的个数--3种方法
|
7月前
|
存储 算法
【三种方法】求一个整数存储在内存中二进制中的1的个数附两道课外练习题
【三种方法】求一个整数存储在内存中二进制中的1的个数附两道课外练习题
51 0