assembly - 相同的汇编指令但不同的机器指令

标签 assembly x86 nasm disassembly

我正在玩 x86 ISA,当我尝试使用 nasm 将一些汇编指令转换为机器指令时,我发现了一些有趣的事情。

mov [0x3412],al 
mov [0x3412], bl
mov [0x3412], cl
mov [0x3412], dl

1 00000000 A21234                  mov [0x3412], al
2 00000003 881E1234                mov [0x3412], bl
3 00000007 880E1234                mov [0x3412], cl
4 0000000B 88161234                mov [0x3412], dl

如您所见,mov [0x3412], al是规则的异常(exception)。
另外,我发现了 mov [0x3412], al映射到两个不同的机器指令。
root@localhost:~/asm$ ndisasm 123
00000000  88061234          mov [0x3412],al
00000004  A21234            mov [0x3412],al

除了这条特殊指令,x86 中是否还有其他汇编指令映射到多个机器指令?

最佳答案

您所观察到的是英特尔对 8088 处理器的设计考虑之一的产物。为了与 8088 处理器保持兼容,当今基于 x86 的处理器推进了其中一些设计考虑,尤其是与指令集相关的设计考虑。尤其是英特尔决定,8088 应该以牺牲性能为代价提高内存利用率。他们创建了一个可变长度的 CISC 指令集,它有一些特殊的编码来限制一些指令的大小。这与许多使用固定长度指令但可以实现更好性能的基于 RISC 的体系结构(如较旧的摩托罗拉 88000)不同。
速度与可变或固定长度指令集之间的权衡是因为处理器需要更多时间来解码用于实现一些较小指令编码的复杂可变长度指令。英特尔 8088 也是如此。
在较早的文献(大约 1980 年)中,更好地利用空间的考虑更为突出。我的答案中与 AX 寄存器相关的信息来自我书架上的一本名为 8088 Assembler Language Programming: The IBM PC 的书。 ,但是有些信息可以在 this 等在线文章中找到。 .
从在线文章中,此信息非常适用于 AX(累加器)和其他通用寄存器(如 BX、CX、DX)的情况。

AX is the "accumulator'';

some of the operations, such as MUL and DIV, require that one of the operands be in the accumulator. Some other operations, such as ADD and SUB, may be applied to any of the registers (that is, any of the eight general- and special-purpose registers) but are more efficient when working with the accumulator.


BX 是“基本”寄存器;

it is the only general-purpose register which may be used for indirect addressing. For example, the instruction MOV [BX], AX causes the contents of AX to be stored in the memory location whose address is given in BX.


CX 是“计数”寄存器。

The looping instructions (LOOP, LOOPE, and LOOPNE), the shift and rotate instructions (RCL, RCR, ROL, ROR, SHL, SHR, and SAR), and the string instructions (with the prefixes REP, REPE, and REPNE) all use the count register to determine how many times they will repeat.


DX 是“数据”寄存器;

it is used together with AX for the word-size MUL and DIV operations, and it can also hold the port number for the IN and OUT instructions, but it is mostly available as a convenient place to store data, as are all of the other general-purpose registers.



正如您所看到的,英特尔打算将通用寄存器用于各种用途,但它们也可以用于特定用途,并且通常对与之相关的指令具有特殊含义。在您的情况下,您观察到的事实是 AX 被视为 蓄能器 .英特尔考虑到了这一点,并为许多指令添加了特殊的操作码,以更有效地存储完整指令。您通过 MOV 找到了这个指令(带有 AX、AL),但它也适用于 ADC , ADD , AND , CMP , OR , SBB , SUB , TEST , XOR .当与 AL、AX 一起使用时,这些指令中的每一条都有更短的操作码编码,需要少一个字节。您也可以使用更长的操作码对 AX、AL 进行编码。在你的情况下:
00000000  88061234          mov [0x3412],al
00000004  A21234            mov [0x3412],al
是相同的指令,但具有两种不同的编码。
这是一个很好的 HTML x86 instruction set reference可在线获取,但 Intel 提供了非常详细的 instruction reference适用于 IA-32(i386 等)和 64 位架构。

关于assembly - 相同的汇编指令但不同的机器指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32450167/

相关文章:

c - 汇编语言中的 getchar()

c - 在内联 x86 程序集中是否未定义整数溢出?

assembly - 汇编中的尾递归

c - 弹出 x86 堆栈以访问函数 arg 时出现段错误

c - 访问 C 文件中的汇编宏函数/指令

linux - 位于进程虚拟地址空间中的其他线程的堆栈在哪里?

c++ - 编写一个简单的 Bootloader HelloWorld - 错误函数打印字符串

linux - 如何检查给定 shellcode 执行的命令?

linux - 使用 x86 Material 学习 64 位操作系统上的汇编?

c++ - 使用非x86架构上的非AVX指令移位xmm整数寄存器值