汇编指令集与cpu指令集是什么关系?
它们是对应的吗? 为什么高级程序编译时会先转换为汇编指令然后再转成机器码?
关注者
129被浏览
56,0316 个回答
汇编是助记符,因为人要自己去记机器码实在太伤了,所以用一些稍微好看的的符号记一下。这里面有这么几个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。
所以还是有区别的(但是区别非常非常小,你也可以手写这三条指令来完成同样的功能)。