汇编指令集与cpu指令集是什么关系?

它们是对应的吗? 为什么高级程序编译时会先转换为汇编指令然后再转成机器码?
关注者
129
被浏览
56,031

6 个回答

汇编是助记符,因为人要自己去记机器码实在太伤了,所以用一些稍微好看的的符号记一下。这里面有这么几个point:

1. 一个汇编指令会对应多种不同的机器码,比如MOV指令,实际编码的时候是分8位 16位 32位 64位,是寄存器->寄存器 内存-> 寄存器 寄存器->内存, 内存又要考虑各种寻址方式,变成机器码的时候都有出入,所以汇编实际上还有一定程度的抽象,把一组含义接近的机器码统一成一个指令

2. 不是所有机器码都能找到汇编何其对应的,因为存在一个指令边界的问题:每条指令不只是一个byte,所以使用机器码的时候,完全可以jmp到别的指令的中间开始执行,这种情况要用汇编来表示是很困难的。

3. 具体到编译器,把生成编译器汇编代码 汇编器生成机器码两者分开是有好处的,因为这样你的编译器就不用处理汇编器那一坨复杂的编码的逻辑了

4. 当然完全可以编译器不产生汇编,直接生成机器码,印象中tcc就是这么干的

可能用RISC的指令集解释更清楚一点。

比如常年用来教学(以及部分机顶盒/路由器)使用的MIPS指令集,其指令为定长。比如你是32位,MIPS32的指令集每条指令都是32bit的。

那么会出现很多问题。比如你不能直接产生一个32bit的立即数赋值给某寄存器。但是人去编写/高级语言生成的时候,很容易出现类似的指令。

比如最常见的

li rx imm32

意味将立即数imm32赋值给rx

这不是一条MIPS的cpu指令,其长度超过了32bit,但是确实一条MIPS汇编指令,因为汇编器会将其拓展成

li rx hi_16
sll rx rx 0
addiu rx lo_16

三条cpu指令,每条都是32bit长。分别意为

将hi_16位赋值给rx,将rx左移16位,将rx加上lo_16。

所以还是有区别的(但是区别非常非常小,你也可以手写这三条指令来完成同样的功能)。