第一章 进制
引言:
进制跟我们生活是息息相关的,比如 时钟,星期 等,那么计算机也离不开进制,计算机是通过二进制进行操作和运算的。
我们为什么要学习进制?
方便我们了解计算机,了解计算机的运行,为以后的学习打下基础。
什么才是正确的学习方法?
忘掉呆板的十进制!说到进制,其时大家都会,只是生活中的运用把其它的进制都丢弃了,只留下十进制,这一章主要是带我们了解各种进制,找回应有的记忆。
本章必须要掌握的知识点:
- 各种进制的书写方法
- 进制间的运算
- 计算机中负数的表示
- 布尔代数
本章常犯的错误:
- 总是以十进制为依托去考虑其他进制
- 其他进制间判断大小时先转换成十进制
- 负数与符号位
4.数据进制
本节主要内容:
- 了解进制
- 各种进制的书写方法
老唐语录:
现在请一个同学上来写出 10 进制的 0-100
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
100
大家看着上面的的数字说一句话:
小陶 say: 有 101 个数
小胡 say: 十进制从 0 到 100。
……
其实这就是小学入学考试,只要写出 0-100 就可以参加学习我们的课程。
下面我来给十进制下个定义:
十进制是由 0、1、2、3、4、5、6、7、8、9 十个符号组成,逢十进一。
你们给九进制下个定义:
九进制定义:九进制是由 0、1、2、3、4、5、6、7、8 九个符号组成,最小是 0,最大是 8,逢九进一。
练习:
用九进制写出十进制的 101 个元素:
0 1 2 3 4 5 6 7 8
10 11 12 13 14 15 16 17 18
20 21 22 23 24 25 26 27 28
30 31 32 33 34 35 36 37 38
40 41 42 43 44 45 46 47 48
50 51 52 53 54 55 56 57 58
60 61 62 63 64 65 66 67 68
70 71 72 73 74 75 76 77 78
80 81 82 83 84 85 86 87 88
100 101 102 103 104 105 106 107 108
110 111 112 113 114 115 116 117 118
120 121
现在给七进制下个定义:
七进制是由 0、1、2、3、4、5、6 七个符号组成,最小是 0,最大是 6,逢七进一。
练习:
用七进制写出十进制的 101 个元素:
0 1 2 3 4 5 6
10 11 12 13 14 15 16
20 21 22 23 24 25 26
30 31 32 33 34 35 36
40 41 42 43 44 45 46
50 51 52 53 54 55 56
60 61 62 63 64 65 66
100 101 102 103 104 105 106
110 111 112 113 114 115 116
120 121 122 123 124 125 126
130 131 132 133 134 135 136
140 141 142 143 144 145 146
150 151 152 153 154 155 156
160 161 162 163 164 165 166
200 201 202
现在给十一进制下个定义:
十一进制是由 0、1、2、3、4、5、6、7、8、9 还差一个符号,用 X 也行,用 A 也行,
共十一个符号组成,最小是 0,最大是 X(或 A),逢十一进一。
练习:用十一进制写出十进制的 101 个元素:
0 1 2 3 4 5 6 7 8 9 A
10 11 12 13 14 15 16 17 18 19 1A
20 21 22 23 24 25 26 27 28 29 2A
30 31 32 33 34 35 36 37 38 39 3A
40 41 42 43 44 45 46 47 48 49 4A
50 51 52 53 54 55 56 57 58 59 5A
60 61 62 63 64 65 66 67 68 69 6A
70 71 72 73 74 75 76 77 78 79 7A
80 81 82 83 84 85 86 87 88 89 8A
90 91
现在给三进制下个定义:三进制是由 0、1、2 共三个符号组成,最小是 0,最大是 2,逢三进一。
练习:
用三进制写出十进制的 101 个元素:
0 1 2
10 11 12
20 21 22
100 101 102
110 111 112
120 121 122
200 201 202
210 211 212
220 221 222
1000 1001 1002
1010 1011 1012
1020 1021 1022
1100 1101 1102
1110 1111 1112
1120 1121 1122
1200 1201 1202
1210 1211 1212
1220 1221 1222
2000 2001 2002
2010 2011 2012
2020 2021 2022
2100 2101 2102
2110 2111 2112
2120 2121 2122
2200 2201 2202
2210 2211 2212
2220 2221 2222
10000 10001 10002
10010 10011 10012
10020 10021 10022
10100 10101 10102
10110 10111 10112
10120 10121 10122
10200 10201
其实学计算机很简单,就是扳着手指头数,如果不是数出来,是算出来的都是错误的想法。数的本质是数出来的。
比如:2+2 = 4 我们可以用手指头一个一个数出来。
课后理解:
各种进制如表 1-1:
表 1-1:1-11 进制表示
进制 实例
1 0,00,000,0000,00000,000000…
2 0,1,10,11,100,101,110,111,1000…
3 0,1,2,10,11,12,20,21,22,100…
4 0,1,2,3,10,11,12,13,20,21,22…
5 0,1,2,3,4,10,11,12,13,14,20…
6 0,1,2,3,4,5,10,11,12,13,14…
7 0,1,2,3,4,5,6,10,11,12,13,14…
8 0,1,2,3,4,5,6,7,10,11,12,13…
9 0,1,2,3,4,5,6,7,8,10,11,12…
10 0,1,2,3,4,5,6,7,8,9,10,11,12…
11 0,1,2,3,4,5,6,7,8,9,A,10,11…
进制其实是 N 种符号组成的。
课后总结:
进制是由元素组成的,N 进制就是有 N 个元素组成,逢 N 进一
课后练习:
- 在纸上用 1 到 16 进制分别描述 100 个数
- 写一到十六进制,每进制 0-99
- 0 到 16 进制,每个进制写 100 个数。
1.2 进制运算
本节主要内容:
- 二进制的好处
- 进制间的运算
老唐语录:
十进制是大家小学时就会的:
0,1,2,3,4,5,6,7,8,9
那么九进制大家也应该都会:
0,1,2,3,4,5,6,7,8
十进制可以加减乘除,那么九进制照样可以加减乘除,直接算出结果,十一进制也可以。既然小于十进制都会,大于十进制都会,那就是说 N 进制都会。难道 N 进制都会,唯独不会二进制吗?
既然你们都会的话,书上为什么还要教二进制呢?还用进制间转换吗?你们可以看一下书上,有十进制转二进制,二进制转十进制,不是多此一举吗?三进制可以直接算出结果,九进制也可以直接算出结果,为什么二进制不可以呢?任何一种进制,他自身就是一个完美的体系结构,直接能加减乘除开方。
练习:
九进制加法:
7+8=16
九进制根本不需要去转换,可以直接算出结果,十进制也是,和其他进制没有关系,自成一个体系结构。任何进制都可以直接加减乘除。那么,同样的,三进制,二进制,八进制,十六进制都是一个完美的体系结构,都可以自己加减乘除,直接算出结果,如果谁去转换成二进制,那说明不懂。二进制可以直接加减乘除算结果,把结果拿来用就可以了。比如:你说你有“110”块钱不行吗?非要用十进制的吗?如果需要加减,可以直接加减,九进制可以直接加减,为什么二进制不能呢?既然加减乘除都可以,为什么还要去转换呢?现在懂了没有?大家理解所有进制了吗?
小桃 say:“懂了。”
小胡 say:“会了。”
二进制就是由 0 和 1 共两个符号组成,最小是 0,最大是 1,逢二进一,就学完了。
那现在我们给 N 进制下个定义:
N 进制就是由 0、1、2、3、4……N-1 共 N 个符号组成,逢 N 进一。
我们说过了,人类只会数数,不会加减,所以说我们用进制不能用的太大,因为十进制有十个符号,相互之间加减是我们能记住的。二进制就更简单,只有两个符号,两个之间相互加减,都是可以记住的,为什么计算机用二进制?因为二进制最简单,需要记住的东西最少,人类不会计算,当然计算机更不会计算。所以说他只能用最简单的记忆方法来算,因为十进制需要记住的符号太多了。
比如在十进制中,5+4=9,2+7=9,1+8=9,3+6=9,2+8=10,两两相加,符号太多
了,很麻烦,相比较而言,二进制要简单的多。严格的说,他只有两个结果 0 和 1,所以非
常简单。而其他进制太复杂,三进制,四进制,五进制,六进制都很复杂,所以说基本都不
用。人类最常用的是十进制,因为人类有十个手指头,数起来很方便。最方便的数数工具,
就是手指。人类天生就会使用十进制,当然也有民族使用五进制的,因为五进制数起来也很
方便,一个手五个手指头,一个手专门去数。现在大家都懂了进制了吧?
练习:
用一百进制从 0 写到十进制的 101?现在大家自己在纸上写,或者谁上来写。
小刘 say:“后面咋整?”
老唐 say:“随便你,不是学过了吗?九进制会了,十进制会了,十一进制会了,也就
是说大于十进制的都会。小于十进制的都会。难道就不会一百进制吗?”
小李 say:“用什么来表示?”
老唐 say:“随便。”
小桃 say:“写到一百零一只进了一次”
老唐 say:“是啊。”
其实我们学到 0,1,2,3,4,5,6,7,8,9 是阿拉伯人的符号。零,一,二,三……
是中国人的符号,仅仅是个符号而已。
练习:
用一进制从 0 写到十进制的 20,结绳记事用的就是一进制。
0
00
000
0000
……
阴阳八卦就是二进制,宇宙中最和谐最完美的进制就是二进制。有和无,白和黑,无和
点(点可以构成画,画可以构成所有)
练习:
用二进制从零写到十进制的 100。
0 1
10 11
100 101
110 111
1000 1001
1010 1011
1100 1101
1110 1111
10000 10001
10010 10011
10100 10101
10110 10111
11000 11001
11010 11011
11100 11101
11110 11111
100000 100001
100010 100011
100100 100101
100110 100111
101000 101001
101010 101011
101100 101101
101110 101111
110000 110001
110010 110011
110100 110101
110110 110111
111000 111001
111010 111011
111100 111101
111110 111111
1000000 1000001
1000010 1000011
1000100 1000101
1000110 1000111
1001000 1001001
1001010 1001011
1001100 1001101
1001110 1001111
1010000 1010001
1010010 1010011
1010100 1010101
1010110 1010111
1011000 1011001
1011010 1011011
1011100 1011101
1011110 1011111
1100000 1100001
1100010 1100011
1100100
练习:
九进制加减法
765-567
注:借一位是 9
练习:
七进制加法
654+321
进制的加减法都会了吧,现在我们来练习乘法
练习:
十进制乘法
8*9
练习:
五进制乘法
3*4
进制间的乘法都会了吧,那现在这道题给你们 10 分钟做出来
练习:
十一进制乘法
789A*A987
注:这个运算比较复杂,因为我们没有掌握它的乘法表,我们只知道十进制乘法表。现
在我们来编写其他进制乘法表。
二进制
11 = 1
三进制
11 = 1
21=1 22=11
四进制
11=1
21=2 22=10
31=3 32=12 33=21
五进制
11=1
21=2 21=4
31=3 32=11 33=14
41=4 42=13 43=22 44=31
六进制
11=1
21=2 22=4
31=3 32=10 33=13
41=4 42=12 43=20 44=24
51=5 52=14 53=23 54=32 55=41
七进制
11=1
12=2 22=4
13=3 23=6 33=12
14=4 24=11 34=15 44=22
15=5 25=13 35=21 45=26 55=34
16=6 26=15 36=24 46=33 56=42 66=51
九进制
11=1
21=2 22=4
31=3 32=6 33=10
41=4 42=8 43=13 44=17
51=5 52=11 53=16 54=22 55=27
61=6 62=13 63=20 64=26 65=33 66=40
71=7 72=15 73=23 74=31 75=38 76=46 77=54
81=8 82=17 83=26 84=35 85=44 86=53 87=62 88=71
十二进制
11=1
21=2 22=4
31=3 32=6 33=9
41=4 42=8 43=10 44=14
51=5 52=a 53=13 54=18 55=21
61=6 62=10 63=16 64=20 65=26 66=30
71=7 72=12 73=19 74=24 75=2b 76=36 77=41
81=8 82=14 83=20 84=28 85=34 86=40 87=48 88=54
91=9 92=16 93=23 94=30 95=39 96=46 97=53 98=60 99=69
a1=a a2=18 a3=26 a4=34 a5=42 a6=50 a7=5a a8=68 a9=76
aa=84
b1=b b2=1a b3=29 b4=38 b5=47 b6=56 b7=65 b8=74 b9=83
ba=92 bb=101
课后理解:
小陶 say:
我的理解:
我们可以通过十进制的乘法,从中摸索出规律:
456456
先进行个位相乘:66=36,进 3 余 6,等等,我们怎么知道 66=36? 是通过 99 乘
法表得到的。同样除法也是如此。找到这个规律,我们就清楚接下来该做什么了:
七进制:
456456=?
我们把七进制的乘法表写出来:
11 = 1
12 = 2
22 = ?在 12 的基础上加 2 为 4
23 = ?在 22 的基础上加 2.
这样,乘法演变成加法。所以很快得出七进制的乘法表:
11 = 1
12 = 2 22 = 4
13 = 3 23 = 6 33 = 12
14 = 4 24 = 11 34 = 15 44 = 22
15 = 5 25 = 13 35 = 21 45 = 26 55 = 34
16 = 6 26 = 15 36 = 24 46 = 33 56 = 42 6*6 = 51
小胡 say:
计算机只会加法,现实中为了计算方便所以建立了乘法表。
课后疑问:
111-111 = ?
有的人说等于 0。那么,如果我使用 0 作为一进制的符号:
00 + 000 = 00000
000 - 00 = 0,
那么 000 - 000 = ?
说明:
其实我们不用纠结于算数的结果,111-111 = 空,这个空可以用其他符号代替,只要不
是该进制使用过的符号即可.
课后总结:
课后练习:
- 对照 99 乘法表,建立 66 乘法表。
- 将 16 进制的元素用 2 进制的元素下定义
- 把 16 进制的元素和二进制对比,发现其中的规律
1.3 十六进制与数据宽度
本节主要内容:
- 进制间的运算
- 计算机计数与数学计数的区别
- 圆圈实现数字循环
- 计算机中负数的表示
老唐语录:
进制现在理解了吗?
在自然界都只有二进制存在。有二进制已经足够了,完全没必要有其他进制。其实自然界也是按这个发展的。学过生物的都知道细胞的分裂。没有说细胞一次性分成三个细胞,四个细胞的吧?只有一个细胞一次分成两个细胞,两个细胞再分成四个细胞,然后八个细胞。无论是单细胞还是多细胞,都是一个变二个,两个变四个,都是按二进制来的。呈二进制的指数增长。而不是十进制的指数增长,更不是其他进制的。十进制只是人类特殊创造的。二进制有个问题,虽然很方便。也可以做很大,你看二进制书写很麻烦。
1111111111111111111111111111111,也就是说二进制表示现实生活中的数,比如你家里多少钱的时候,也并不需要多少位。二进制表示生活中的数也是很短的,并不是很长。32 位,已经很大了,4 个 G。我们说人类特别喜欢用十进制去写。比如 256,使用二进制写会很长(100000000B),你用二进制写会很长。既然你用二进制写太长了,要书写简化,我们书写简化一下二进制。比如二进制我们书写:10101010111010
太长了,我们两位两位的书写,我们用个符号来表示,随便一个符号,比如用 B 来表示。有没有发现,两位两位的书写,最多出现四种可能是吧,00,01,10,11。这四种可能,那么两位两位的书写很方便啊,随便用四个符号代替就行。虽然说二进制有点长,但二进制毕竟是宇宙中最简单的。人类毕竟不习惯,为什么?因为太长。我们两位两位的书写。两位最多要求0,1,2,3.再没别的值了吧。也就是说只要定义四种符号去书写他就可以了。那我们还是觉得长,那好。我们三位三位的书写。那三位最多的可能呢?100,101,110,111 最多只有八种,那我们用 A,B,C,D,E,F,G,H,去表示。010 在这是 C 是吧。111 是 H是吧,010 是 C,101 是 F,这个 010 是 C,CFCHC。那好了,我们也可以同理,我们照样可以四位四位的书写。也可以五位五位的书写。六位六位的书写,七位七位的书写。但是有个问题有没有发现。我们四位四位的书写,就会发现一个问题,符号会越来越多。1000,1001,1010,1011,1100,1101,1111,I,J,K,L,M,N,O。不需要排顺序,只要你使用这十六种符号表示这十六种值就可以。那好了,我们查表。1010,是 K,1011是 L,1010 是 K,0010 是 C,CKCK。导致多位多位的书写。整体变得很短了。问题就是这边要记的符号越来越多了。是不是啊?那当然你还可以五位五位的书写。五位五位书写更短了是吧?那现在要记多少个符号啦,每多一位,符号要增一倍。两位两位的书写只要记 4个符号。三位三位书写八个符号。四位四位书写 16 个符号。五位五位书写 32 个符号。六位六位书写 64 个符号。如果七位七位书写呢?那就 128 个符号了。那为什么当初不让你们用一百进制,那就是符号太多,记不住。人类只会记和数,不会算。二进制的书写对于人类来说毕竟是太长了,所以我们采用简单的方法。就是说,两位两位,三位三位,四位四位,或者五位五位,六位六位,七位七位的书写。到底你喜欢多少位书写呢?看你喜欢记的符号多还是少呢?比如:7 位 7 位的书写,你要记 128 个符号;八位八位的书写,你要记 256个符号。如果你基本功扎实,记得这么多符号,那你写的时候就要容易一点。比如:你的文学功底比较深厚,字学的比较多,词语比较多,成语比较多,那你写的文章就漂亮,并且简短,精炼。那这样,只要你符号记得足够多,那么你书写起来就简短精炼。当然,你符号记得越少,你写的就越长。“记流水账嘛。”如果你字都不会写,就是写的再长,都是反复的这么说来说去,没什么内涵,也没什么文采。二进制有两种,二进制本身是一种,还有一种是二进制的书写形式。书写形式有很多种:一位一位的书写,两位两位的书写,还是三位三位的书写,看你书写形式。我们现在书写 A,B,C,D,我是两位两位的书写,自然这个 D 是 11,C 是 10,B 是 01,
A 是 00。这两种书写形式表示的含义是一样的。上面是书写形式,下面是本质形式。当然本质形式也是其中一种书写形式。也就是说一个汉字他可以有草书,隶书。当然一个二进制也有很多种书写形式。本身二进制这东西只有一个,但是名字有很多种。比如:一个人有几个名字,一个地方有几个名字,一个物体拍照片可以拍很多张,但是你都认识他。当然了,
你也可以一位一位的书写,我用 A 表示 0,B 表示 1,就是 BBABBAAA……这也是二进制的
书写形式。你可以另外定义两个符号,未必要用用原来的 0 和 1。另定义两个符号用 A 和 B
两个符号。也可以两位两位的书写,用 ABCD 来表示。或者是三位三位的书写。
那到底是几位几位的书写更方便呢?
其实很简单。就是因为在全世界阿拉伯数字的符号最简单,我们就不应该用 ABCD 这个符号去表示。我们到底使用 1 位 1 位,2 位 2 位还是 3 位 3 位 4 位 4 位 5 位 5 位书写呢,很简单,我们找这符号,这个符号不能太多,256,128,64,32,都显得多了,就算不多,那我们讨论到底多少适合,我们喜欢阿拉伯数字的符号,那我们就用阿拉伯人的符号来表示。阿拉伯人的符号太完美了,所以我们不能使用三位三位的书写,因为会浪费两个 8 和 9,太可惜了。所以我们一定要大于三位三位的书写。因为我们不要浪费这个符号。就使用四位四位的书写,才能保证把阿拉伯人的符号全部用上。那四位的书写,少了几个符号,那用谁的符号呢?我们发现其实英国人也很聪明,英国人的符号也不错。少几个符号我们用英国人的符号补上去。毕竟英国人没有古印度人聪明,我们补太多的符号,不便于记忆,所以使用四位四位的书写。这不是十六进制,这是四位四位的书写二进制。跟十六进制没有一点关系。你只要简单的记住这十六个符号来表示这十六种值就可以了。
以后写二进制四位四位的书写:
二进制从 0000 写到 1111
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
然后改成 16 个符号。
如果按照这种新的书写方式,那你们发现如果要进位的话,要满 16 才进位。中国古代就知道用二进制数,并知道四位四位的书写。这就是我们平时说的半斤八两,其实就是二进制四位四位的书写导致的结果。你们用过算盘没有?我们平时只用下面四个珠子,上面一个珠子,为什么上面两个珠子,下面五个珠子?这就是二进制,喜欢四位四位的书写,最小值是 0,最大值是 15,下面加上上面值为 15,不拨的时候 0,全拨的时候 15。这就是最早的计算机。有的银行现在仍然使用算盘,加减法还是算盘快,乘除法计算机快。现在开始练习二进制的两种书写方式:一位一位的书写,四位四位的书写。数学上的数,无论多长,都能表示出来,是没有宽度的。算盘宽度是有限的。凡是涉及到机器上的数,宽度总是有限的,计算机中的数是用电路表示的,计算机成本是有限的,所以表示宽度是有限的。
这里为了书写方便我们只写 8 个位:
-1=0-1
00000000
-00000001
计算机在计算数之前,要规定这个数有多宽。-1 是 0xFF。
例:从 0,写到-50。
例:写 4 位,最大值与最小值可以交汇到一点,形成一个圆。
课后理解:
在数学运算中,数值的大小(即宽度)是没有限制的,比如
100000*100000=10000000000。在计算机中,在对数值进行运算前要先规定其宽度,再
进行运算.比如给定的一个数 0x123456789ABC,如果规定它的宽度为 32 位(这里指的
32 通常是二进制的 32 位),那么该数值的有效值为 0x56789ABC.如果运算结果超过其宽
度将被略去,只保留有效位。
例:设给定的数值宽度为 8 位(二进制),则可以表示的最大值为 0xFF(11111111B)。
此时,0x81+0x80= 1000 0001B+ 1000 0000B= 1 0000 0001(B) = 0000 0001
(B) = 0x1。图 1-2 显示了计算机常用的数值宽度
如上图所示,字节(Byte)占据 8 位二进制宽度;字(Word)占据 16 位二进制宽度;
双字(Doubleword)占据 32 位二进制宽度;四字(Quadword)占据 64 位二进制宽度。
在计算机的数值运算中,不仅要规定数值的宽度,同样要设置数值的符号和精确度。比
如正数,负数和浮点数。针对这种情况,计算机将数值定义为有符号或无符号类型:当为有
符号类型时,最高位作为符号位,最高位为 1,表示负数,反之为正数,见图 1-3:
有符号数值大小,见表 1-2:
课后总结:
计算机是定宽的。
课后练习:
2,4,16 进制,每进制最大 32 位,写出 8 个主要点
1.4 逻辑运算
本节主要内容:
- 布尔代数与二进制的关系
- 布尔代数的运算
- VC++6.0 的使用
老唐语录:
上节我们讲到,计算机是定宽的
比如: 一个二进制数 1111 1111 1111 1111B
我们用四位,四位书写的式 FFFF 这样比较简单
今天我们讲,计算机除了算术运算外,还有逻辑运算,只有二进制才能进行逻辑运算。
逻辑运算中只有错与对,成与败两个结果(也就是 0 和 1)。
或运算:
0+0=0
0+1=1
1+1=1(1+1=2 不等于 0,就是 1)
“+”等价于“或”,计算机中使用“|”符号代替。汇编语言使用“OR”代替
与运算:
00=0
01=0
10=0
11=1
“*”等价于“与”,计算机中使用“&”符号代替。汇编语言使用“AND”代替
异或运算:
0-0=0
1-0=1
0-1=1
1-1=0
“-”等价于“异或”,计算机中使用“^”符号代替。汇编语言使用“XOR”代替
三种运算在生活中怎样存在?
说明:看图 1-5,这是一个串联电路图,只有两个开关同时按下时,灯泡才会亮。
异或运算电路如图 1-6:
课后理解:
小陶 say:
或运算(|):只要有一个是 1,就是 1,其它为 0
与运算(&): 两个为 1 才是 1,其它为 0
异或运算(^):相同的为 0,不同的为 1
小胡 say:
看了楼主的理解,我懂了
课后总结:
二进制实现了逻辑运算和算术运算的统一。
课后练习:
1.2、4、6 进制,每个进制写 32 位。0-FFFFFFFF
2.写 10 个寄存器,背熟顺序
第二章 寄存器与汇编指令
引言
想要了解计算机,首先要了解的便是 cpu,cpu 是计算机最核心的部件,因为计算机
的所有指令都是由 cpu 处理,而 cpu 的核心部件之一是寄存器。这一章我们就来认识一下
寄存器以及寄存器是如何工作的。
本章必须要掌握的知识点:
- 8、16、32 位通用寄存器
- 寄存器与内存的区别
- 汇编语言的基础指令
本章常犯的错误:
- 内存的存储格式
- 溢出标志位(OF)的理解
- pop 与 push 指令的理解
2.1 通用寄存器
本节主要内容:
- 8/16/32 位通用寄存器
- 汇编指令
老唐语录:
计算机最经典的指令就是移动指令:mov ecx,eax;
主要记住这 8 个寄存器:
eax
ecx
edx
ebx
esp
ebp
esi
edi
mov 指令可以任意移动这 8 个寄存器。
在 mov ecx,eax 中,后面的是源,前面的是目标,中间是逗号,不区分大小写。寄存器间相互移动。
如果计算机只有移动指令的话,那么什么事也干不了。mov 是操作码,两个寄存器是操作数,操作码除了 mov 之外还有很多,你可以替换:加,ADD;减,SUB;与,AND;或,OR;异或,XOR;非,NOT。
比如:add eax,ecx。当然了,操作码不仅仅只有这几个,还有很多很多,只要搞清楚操作数是任意两个寄存
器,当然可以是同一个寄存器。比如 or esi,esi:将 esi“或”esi 并将结果赋给 esi。操作数除了寄存器之外,
还可以是一个数,只要保证是 32 位即可。8 个寄存器是分段的。比如算盘,我们可以只用一半,或者四分之一。
eax 可以分成四部分:eax 共 0-31,其中 0-7 位叫做 AL,8-15 位叫做 AH。整个 0-15位又称为 AX。AL:low;AH:high。ecx,edx,ebx 也是一样的,如图 2-1。
32 位寄存器有自己的编号,16 位寄存器也有属于自己的独立的编号。当然,他们是重叠的,当改变了 32 位的寄存器,相应的 16 位寄存器也会跟着改变。同样,也有 8 位的寄存器,第 0 号 AL,第 1 号,CL,DL,BL,AH,CH,DH,BH。顺序不能乱。当然还有两个寄存器:EIP 和 EFLAGS(又称为 EFL),8 号和 9 号寄存器,EIP 有 16 位,叫做 IP。EFL 的 16 位称为 FL。这两个寄存器使用相对较少。
练习:
除了 EIP 和 EFL 之外,其他寄存器都是可用的,使用 MOV,ADD,SUB……等指令做练习,比如 XOR AL,BH,后面随便跟两个寄存器,用逗号隔开,当然,前后宽度要一样。而不可以是 XOR AL,BX。后面的寄存器可以改成立即数。
课后理解:
通用寄存器即 cpu 常用的寄存器。Intel 手册给出了通用寄存器的功能:通用目的寄存器(General-Purpose Registers)主要实现逻辑和算术运算、地址计算和内存指针。
步不会停歇的,之后将 16 位寄存器都扩充了一倍,于是 32 位寄存器出现了,当然这里只
截至 32 位,64 位和 128 位寄存器留给大家思考。
32 位通用目的寄存器的指定用途如下:
·EAX:累加器(Accumulator)
·ECX:计数(Counter)
·EDX:I/O 指针
·EBX:DS 段的数据指针
·ESP:堆栈(Stack)指针
·EBP:SS 段的数据指针
·ESI:字符串操作的源(Source)指针;SS 段的数据指针
·EDI:字符串操作的目标(Destination)指针;ES 段的数据指针
以上只是让大家对寄存器的缩写的含义了解一下,毕竟使用一样东西,不明白其中的道
理,实在不高明,而且这东西是老外发明的,按中式逻辑很难猜出来。
课后疑问:
问题:EIP 在不断变化,我们不但要有命令去操作这些寄存器,还需要区分当前用的是哪一条命令,下一次再用哪一条命令。
回答:cpu 具有判断指令长度和预处理指令的功能。
为什么你写的寄存器顺序是 EAX,ECX,EDX,EBX……而不是 EAX,EBX,ECX,EDX……,不是更容易记住?
回答:其实我也想,可是 Intel 的技术员不这么认为,他们就是这么定义寄存器顺序的。了解寄存器的顺序和编号,对后面将要介绍的汇编指令和硬编码尤为重要。
课后总结:
汇编就是在“寄存器与寄存器”或者“寄存器与内存”之间来回移动数据。
课后练习:
32,16,8 位寄存器用 mov add AND sub or xor not 演算
2.2 内存
本节主要内容:
- 寄存器与内存的区别
- 寄存器,内存
- 内存修改
老唐语录:
快速算盘叫做寄存器。慢速的称为内存。其实他们的结构差不多,都是定宽的,最重要的一点,寄存器速度非常快,价格非常昂贵,所以在 CPU 内部。做的数量也很有限。常用的只做了 8 个:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI。内存速度慢,很便宜,所以数量做的非常庞大。寄存器做的数量非常少,就可以为每个寄存器取个名字。而内存数量太庞大了,没办法给每一个都取上名字,所以只能编号。最后重要的是内存中寄存器的编号是32 位的。这也是我们现在的计算机叫 32 位计算机的主要原因。如果按寄存器的宽度是 32位的话,是不对的,因为还有很多寄存器是大于 32 位的。我们通用的 8 个是 32 位的。而内存地址是固定的 32 位。以前的计算机之所以称为 16 位计算机,就是因为他的内存单元编号是 16 位的。
我们学过的指令 MOV,能操作寄存器和内存。所以说,汇编可以用一句话概括:汇编就是在寄存器和寄存器或寄存器和内存之间来回移动数据。就是指数据在内存和寄存器间来回流动,流动的多了,代表程序很复杂,比如office 等一些大型软件。
mov eax,0x401000//给 eax 初始化MOV 也可以改成 ADD(加),SUB(减),XOR(异或),OR(或),AND(与)。
后面的操作数为源操作数,前面的操作数为目标操作数,最开始是操作码。其实 ADD……这些也是移动指令:把源加上目标然后移动到目标操作数里面去。前面表示操作方式,后面表示寄存器和寄存器或寄存器和内存,但是只能出现一个内存。
比如:ds:[]里面写个数,表示内存单元。ptr 指的是指针 point。word 是两个字节,还有 byte 是一个字节,dword 是四个字节。
写法:byte/word/dword ptr ds:[32 位的数]。
其实[]里面不但可以写具体的一个数,还可以写某一个寄存器的值。方括号的通用格式:reg+reg数+立即数,只要这个值算出来指向哪一个内存单元,
就是那个内存单元(现在先记住,不要管为什么,后面会讲)。
第一个寄存器叫做 BASE 寄存器(8 个寄存器都可以),第二个寄存器是 INDEX 也是 8个寄存器之一,后面乘一个数 scale(1,2,4 或 8,也就是 2 的 0 次方,2 的 1 次方,2的 2 次方,2 的 3 次方),后面再加一个数(DISP)。
BASE+INDEX(1,2,4,8)+DISP 可以是有以下五种组合
BASE
INDEX*(1,2,4,8)
DISP
BASE+INDEX×(1,2,4,8)
BASE+INDEX×(1,2,4,8)+DISP
每一种组合都可以。
我们只有把最简单的东西用熟了,才能熟能生巧。
练习:
mov eax,ds:[0x401000+8*eax+eax];这个可以执行吗?
cpu 实现了将地址赋给寄存器:LEA 指令把方括号里面内存的编号给目标寄存器:load
effective address。
当一个值不好确定宽度时,使用 dword ptr 或者 word ptr,byte ptr,源可以是内存或寄存器,也可以是立即数,但是目标不能是立即数。两方都可以是内存,但是内存只能在一个地方出现。两边的数据宽度要一样。所以指令是由操作码和操作数组成,操作码是表明我想干什么。复杂的指令也是由简单的指令组合而成。
课后理解:
内存同样由许多寄存器组成,但是此寄存器非彼寄存器,速度不及通用寄存器的几十分
之一,宽度为 8 位。见图 2-3:
如图 2-3,为了区别内存和 cpu 内部的寄存器,我们将内存中的寄存器打上“[]”,专业术语称之为“地址”。图中的内存大小从 0 到 0xFFFFffff,也就是说有 0xFFFFffff 个内存寄存器存在,内存地址从 0-0xFFFFffff。
注:此处 0xFFFFffff 写法为何不写成 oxFFFFFFFF?
十六进制不区分大小写,这样写是为了便于识别,我们可以很清楚的看出有 8 个 F。
内存地址的用处是什么?
当用户运行程序时,cpu 需要不停地去从存储区取代码和数据,这样非常耗时,于是cpu 先将可能用到的代码和数据从存储区全部放入内存,再从内存中取数据和代码。看似多了一个过程,但是从内存中获取比存储区快得多,所以节省了很多时间。
我们如何使用内存地址呢?我们通过实例来了解。
将 32 位数 0x12345678 存入内存中的 0x12FFB8 地址处:
说明:我们从图 2-4 可以看出:数值的高位存储在内存地址中的高位。
内存地址的表示方法有哪些?
内存地址的表示方法有很多,除了上图中的表示方法外,还有其他四种表示方法。
以下是内存地址表示方法的组成成员:
·位移(Displacement) - 8 位、16 位或 32 位值
·基(Base) - 通用目的寄存器
·索引(Index) - 除 ESP 外的通用目的寄存器
·比例因子(Scale Factor) - 1,2,4 或 8
下列五种地址模式为常用组合(图 2-3):
·位移
·基
·基 + 位移
·(索引×比例因子)+ 位移
·基 + (索引×比例因子)+ 位移
为什么只有五种表示方法,而且比例因子还有限制?
极有可能的原因是(猜测):计算机只识别机器语言,所以我们要将内存地址的表示方法翻译成机器语言才能得到执行。组合越多,翻译起来越麻烦,cpu 的技术员们只好订个规矩:只能使用五种表示方法,否则一律不识别。
练习:
用实例表示以上五种组合方式。
1.[0x234791]//vc6 不支持
2.[reg]
3.[reg+0x10234]
4.[reg+reg*{1,2,4,8}]
5.[reg+reg*{1,2,4,8}+0x1234]
注:reg 表示通用寄存器。
课后疑问:
- scale 可以是其他值吗?
回答:不可以 - 如果算出的内存地址结果超过 32 位会怎样?
回答:如果结果超过 32 位溢出,则计算机只取 32 位。
课后总结:
内存的通用格式:reg+reg*数+立即数
课后练习:
练习复杂地址表达形式的操作如: lea [eax +eax*0x02+0x12548],eax
2.3 汇编指令
本节主要内容:
- 内存地址
- 汇编语言的基础指令(push、pop、call)
老唐语录:
复合指令:
lea esp,[esp-4]
mov [esp],eax
使用 vc6 调试观察内存的变化:
这两条指令的组合就是我们学的新指令:push eax。
mov eax,[esp]
lea esp,[esp+4]就是指令 pop eax。
练习:
将 eax 替换成其他 7 个寄存器并测试
总结:
pop ERX 也可以理解为:
lea esp,[esp+4]
mov ERX,[esp-4]
所以 pop esp 可以简化为
lea esp,[esp+4]
mov esp,[esp-4]
练习:
在 VC6 中单步过程时,可以在代码窗口右键 go to disassmbly,一步一步运行,并观察 eip 变化。
其实 eip 一直在变化。在 80x86CPU 中,eip 寄存器指向的是将要执行代码的位置,
代码本身也是数据,也是由二进制构成。
Intel 指令的长度不同,最短的只占一个字节,最长 15 个字节。
比如:
xchg eax,eax
mov eax,0x1234567
通过 VC6 中的汇编窗口,右键 code bytes,可以看见指令的二进制内容。
xchg eax,eax 又称为 nop。
数据包含代码,代码只是数据的一部分,eip 指向的位置才称为代码。
前面提到计算机和数学(算盘)的不同点是计算机是定宽的。
第二个不同点是数学中的算盘只负责存储数据,并是由人操作的,而计算机相当于有两个算盘,其中一个存储数据,另一个负责操作算盘。操作和运算本身也是代码,并存在于内存中。但是代码本身不能存放在寄存器,只能放在内存中,只有数据可以放在寄存器中。但是专门有一个寄存器负责指向执行代码(操作算盘的人在哪里,在内存中的哪个位置)。eip 是寄存器,所以他的值可以被改变。计算机取名字是有规则的,以字母、数字或下划线组成,并且不以数字开始。
mov eax,offset 标号名(标签);用名字的时候要加个 offset,其实就是立即数
每个地方都可以取个标签,如:
lab: mov eax,ecx
mov ecx,offset lab
既然汇编指令就是在寄存器和内存间移动指令,那么我们可以使用 mov 来修改 eip:
mov eip,寄存器/立即数
简写为 (取别名):
jmp 寄存器/立即数
此外,
push offset lab
mov eip,eax
lab :…
称为 call eax
ret 就是
lea esp,[esp+4]
mov eip,[esp-4]//jmp [esp-4]
的简写形式。
ret 后面可以加一个数 0x04,0x08……这个数是两个字节的宽度:
ret IW,比如 ret 0x4
课后理解: