汇编语言与其相应的机器语言有多相似?

How similar is assembly language to its corresponding machine language?

经常听到或读到这样的评论:“汇编程序实际上是一种机器代码,但使用的是符号而不是直接的二进制代码”。

我的问题是:“一般来说,这种肯定有多少真实性?”

这是一个例子,使用 y86。

add %rdi, %rsi

变成类似

的样子
00 01 02

基本上,00是操作码add的字节表示。当计算机看到 add 时,它知道将接下来的两个字节解释为寄存器(这在 x86 中 稍微 更复杂)。 0102 分别是字节 'names' 或寄存器 %rdi%rsi 的编码。

这个例子的某些部分可能不能完全反映现实,但这基本上是机器码和汇编的对应关系。指令是操作码 + 1-5 个字节,根据操作码有不同的解释。

如果您从机器代码的“纯文本”表示开始(例如,opcodes/numbers 替换为助记符,addresses/numbers 替换为标签);然后大多数汇编器也:

a) 允许在操作数中使用更复杂的表达式(例如,允许类似“mov eax,(1234*5+6)/7 的内容,其中汇编程序计算“mov eax,882”指令的正确值)。

b) 有允许您编写宏等的预处理器。这通常包括条件代码,有时它的功能足以让您创建一种新语言 and/or 高级语言结构(例如想象“while " 和 "endwhile" 宏)。

c) 可以auto-select最优化的编码。例如,如果指令可以用 32 位立即操作数或符号扩展为 32 位的 8 位立即操作数进行编码;然后汇编程序可能会查看操作数并确定较短的符号扩展编码是否有效。

所有这些都对源代码维护产生了巨大的影响——例如如果您在某处添加一些指令,则无需手动重新计算 call/jump/branch 目标和数据访问的所有 addresses/offsets;您可以在一个地方执行“#define COST_OF_CHEESE 123”,以便以后轻松更改(而不必在使用该值的所有地方找到);等等