汇编的由来
本来的时候,计算机只能识别010101数字,然后可以通过二极管的开和关表示0、1,但是这样和计算机交互非常困难,
所以就将所有操作简化成助记词,也就是汇编语言
# 加法 INC --> 经过汇编编译器 转换成计算机01指令
# 减法 DEC
# 乘法 MUL
# 除法 DIV
进制
进制?
1进制:一进一,结绳记事 1 1
2进制:二进一, 0 1 0 11 计算机
8进制:八进一 8个符号组成:0 1 2 3 4 5 6 7
10进制:10进一 10个符号组成:0 1 2 3 4 5 6 7 8 9
16进制: 16进一 16个符号组成:0 1 2 3 4 5 6 7 8 9 a b c d e f
测试
# 一进制 1~20
1
1 1
1 1 1
...
# 三进制 1~20
1 2 10
11 12 20
21 22 100
101 102 110
111 112 120
121 122 1000
1001 1002
# 七进制 1~20
0 1 2 3 4 5 6
10 11 12 13 14 15 16
20 21 22 23 24 25 26
# 为什么还有十六进制?
二进制 十六进制
0001 0000 10
1100 0011 C3
也就是说,如果将一个二进制数从右往左,分成4 比特为一组的形式,分别将每一组的值转换成十六进制数,
就可以得到这个二进制数所对应的十六进制数。
十六进制 3 F 8
二进制 0011 1111 1000
正如前面所说的,从事计算机的学习和研究(包括咱们马上就要进行的汇编语言程序设计),不可避免地要与二进制数打交道,而且有时还必须针对其中某些比特进行特殊处理。这个时候,如果想保留二进制数的直观性,同时还要求写起来简短,十六进制数是最好的选择
1 + 1 = 3 对
十进制: 0 1 2 3 4 5 6 7 8 9
我的十进制:0 2 4 6 8 a w c q k
进制加密!!!
进制怎么运算
# 八进制计算下面的结果
2 + 3 =
2 * 3 =
4 * 5 =
# 运算的本质就是查数
# 以前的加减法和乘除法是逢十进一
# 那么在八进制下,就是逢八进一
347
74 +
--------
423
二进制
计算机使用二进制 0 1 物理极限:摩尔定律
量子计算机:
传统的计算机:集成的电路!01 硅晶片
量子计算机的单位:昆比特。(量子比特!)量子的两个状态
光子:正交偏振方向
磁场:电子的自旋方向
量子计算机!提高计算机的计算力
量子比特、量子叠加态、量子纠缠、
回到电子计算机
数据宽度
C 和 C++ Java 都需要定义数据的类型。计算机底层需要我们给这些数据定义宽度
位 0 1
字节 0-0xFF
字 0-0xFFFF
双字 0-0xFFFFFFFF
有符号数、无符号数
数据都是有宽度的。每个数据代表什么意思呢?
0 1 0 1 0 1 0 1
规则
解析一个音频:MP3解码格式,不同的规则
给二进制解码,给一个规则
无符号数规则
你这数字是什么就是什么
1 0 0 1 1 0 1 0 十六进制:0x9A 十进制:154
有符号数规则
最高位是符号位 1(负数) 0(正数)
1 0 0 1 1 0 1 0 如何转换
原码补码反码
编码规则
有符号的编码规则
原码:最高位符号位,对其它的位进行本身的绝对值即可
反码:
- 正数:反码和原码形同
- 负数:符号位一定是1,其余位对原码取反
补码:
- 正数:补码和原码相同
- 负数:符号位一定是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
如果看到一个二进制,需要了解它是有符号还是无符号的
计算机底层,存储负数是存它的补码的
F = 1111
位运算
与运算(and &)
# 两个都为1,结果为1
1001 0011
1010 1101 &
--------------
1000 0001
或运算(or | )
# 只要有1个1,结果为1
1001 0011
1010 1101 |
--------------
1011 1111
异或运算( xor ^ )
# 不一样就是1
1001 0011
1010 1101 ^
--------------
0111 1110
非运算(单目运算符 not ~ )
# 0就是1 1就是0
1010 1101 ~
--------------
0101 0010
通过这些可以完成加减乘除!位运算来实现加减乘除
位运算(移动位 )
左移( shl <<)
1 << 1
0000 0001
所有二进制全部左移若干位,高位丢弃,低位补0
0000 0010
右移(shr >>)
1 >> 1
0000 0001
所有二进制全部右移若干位,高位补0,低位丢弃(根据符号决定)
0000 0000
int a = 10;
printf("%d\n",a>>2)
位运算的加减乘除
4 + 5
# 计算机的实现原理 加法
#第一步,异或,不考虑进位,可直接出结果
0000 0100
0000 0101 ^
--------------
0000 0001
#第二步,与运算(判断进位,如果与运算结果为0,就说明没有进位)
0000 0100
0000 0101 &
--------------
0000 0100
# 第三步,讲与运算的结果向左移一位, 0000 1000 #进位的结果
因为进位了,所以都要左移一位
# 第四步,再异或一次,第一次异或结果和与运算的结果异或
0000 0001
0000 1000 ^
-------------
0000 1001
# 第五步,将上一步操作再与运算一次,判断是否有进位
0000 0001
0000 1000 &
-------------
0000 0000
# 所以最终的结果就是与运算为0的结果上一个异或运算
# 4 - 5
# 也就是 4 + (-5)
#计算机是没有减法的
0000 0100
1111 1011 ^
-------------- #异或,不考虑进位,可直接出结果
1111 1111 # ff=-1
0000 0100
1111 1011 &
-------------- # 判断进位,如果与运算结果为0,就说明没有进位
0000 0000
# 所以最终的结果就是与运算为0的结果上一个异或运算
1111 1111
乘法: x * y :也就是 x 个 y相加,还是加法
除法:x / y :也就是x能减去多少个y,还是加法
汇编语言
通过汇编指令可以给计算机发一些操作,然后让计算机执行
学习汇编之前,先掌握环境
1.VC6
2.OD
通用寄存器
寄存器
存储数据:CPU ----内存-----硬盘
32位CPU 8 16 32
64位CPU 8 16 32 64
通用寄存器
# 32位的通用寄存器只有八个
存值的范围:0 ~~ FFFF FFFF
对于二进制来说,直接修改值
计算机如果向寄存器存值·
mov指令
# 可以在寄存器存值
mov 存的地址,存的数
# 可以将寄存器的值存入寄存器
mov 要存的地址1,存数的地址
# F8执行
不同的寄存器
F*8 FFFF FF
32位 16位 8位
EAX AX AL
ECX CX CL
EDX DX DL
EBX BX BL
ESP SP AH
ENP NP CH
ESI SI DH
EDI DI BH
8位:L第八位,H高八位
除了通用寄存器之外,其它的寄存器每一位都有自己特定的功能
内存
寄存器很小,不够用,所以说数据放到内存里
每个应用程序都有4GB的内存空间,空头支票
程序真正运行的时候,才会用到物理内存
内存地址
计算机内存地址很多,空间很大,每个空间分配一个地址
地址很多,
所以每个内存地址都有一个编号,可以通过这个编号进行存值
内存如何存值?
数据宽度: byte word dword
地址的位置:0xFFFFFFFF
不是任意的地址都可以写东西,需要申请使用
# 汇编如何向内存写值
mov 数据宽度 内存地址,1
#例子
mov byte ptr ds:[0x19FF70],1
内存地址有多种写法
ds:[0x19FF70+4] 偏移量
ds:[eax] 将寄存器中值写入内存
ds:[eax+4] 寄存器偏移
数组[]
ds:[reg+reg*{1,2,4,8}]
ds:[reg+reg*{1,2,4,8}+3] 偏移