我考虑了很久,要讲汇编,机器码是无论如何绕不过去的。从细节上讲的讲机器码和汇编指令是区别很大,但不关注细节的情况下,区别又不那么完全。通常在有上下文支撑,且没有歧义前提下,“机器码”和“指令”会混用、“汇编指令”和“指令”。
我所知道的,最古老的可执行文件,是在打过孔的纸带。比如有孔的地方表示1,没孔的地方表示0,计算机运行的程序,就是这一系列的0和1组成的二进制数串。过了这么多年,存储介质虽然经历了多轮的升级,但本质并没有变化,还是0和1组成的二进制数串。
按照目前的计算机工业标准:
每8个二进制位,构成一个“字节”。
每2个字节,即16个二进制位,组成一个“半字”
每4个字节,即32个二进制位,组成一个“字”
每8个字节,即64个二进制位,组成一个“双字”
字节,是计算机单次操作数据的最小单位,计算机单次操作的数据,必然是字节的整数倍。
比如,一个龙芯架构的机器码,是4个字节。
有些爱抬杠的同学,肯定会不服气,我将来就设计一个字节为9bit的电脑。但是我要说,工业标准摆在那里,也许不是最好的,你非要在工业标准之外圈地自萌,让大家重新习惯你的标准,当然也不是不可能成功,除非你的东西不可替代,否则成功概率很小。
图 3‑1 龙芯架构指令的编码格式(部分)
龙芯架构的机器码格式,由两部分构成:操作码(opcode)和地址码;少部分的机器码,只有操作码。
操作码,可以理解为运算器或者控制器的地址,个别操作码可能隐含操作数的地址。
地址码,可以理解为操作数的地址,还可以在继续分类为:源数据地址、目的数据地址。
所以一条机器指令的功能就可以理解为:
- 将操作码片选的运算器或控制器的输入端,与总线连接;将源数据地址所片选的存储单元,与总线连接;
- 运算器、控制器接收数据后,关闭上述片选,按照设计逻辑,将运算结果放入输出端。
- 将操作码所片选的运算器或控制器的输出端,与总线相连;将目的数据地址所片选的存储单元,与总线相连;
- 数据进入目的存储单元后。
指令中还有一个很重要的概念,就是寻址方式:即通过指令中的地址,找到操作数。因为存在立即寻址方式(指令中包含操作数本身),所以这里的是地址,而不是地址码,再强调一次,操作数的地址,可以是地址码,也可以隐含在操作码里。
比如相对跳转指令,操作码隐含目的数据地址是PC寄存器,也隐含源数据地址是指令后半段的立即数。
那么一条机器码的功能,就可以大体上理解为:把源数据地址中的数据,送入操作码所片选的运算器或控制器,运算结果放入目的数据地址。