【发布时间】:2018-01-12 00:20:43
【问题描述】:
我开始学习汇编,这对我来说看起来不合逻辑。
为什么我不能在一个寄存器中使用多个高字节?
我了解rax->eax->ax的历史原因,所以让我们关注新 64位寄存器。例如,我可以使用r8 和r8d,但为什么不能使用r8dl 和r8dh? r8w 和 r8b 也是如此。
我最初的想法是我可以同时使用 8 个 r8b 寄存器(就像我可以同时使用 al 和 ah 一样)。但我不能。并且使用r8b 会使完整的r8 寄存器“忙碌”。
这引发了问题 - 为什么?如果您不能同时使用其他部分,为什么只需要使用寄存器的一部分?为什么不只保留r8 而忘记下部?
【问题讨论】:
-
如何使用“仅
r8”将单个字节写入内存?除了r8b不会使r8“忙”之外,高56 位仍然存在,不知道你让你怎么想。它只是不能作为单个 8b 寄存器直接访问,仅此而已。以及为什么没有更高位的寄存器别名:有没有想过指令是如何编码成机器代码的?现在添加足够的位来编码所有新的变体,每条指令都像 +1B = 太贵了。这是相关的dsasmblr.com/accessing-and-modifying-upper-half-of-registers -
允许写入 AH 或部分寄存器会导致性能下降。这就是why most x64 instructions zero the upper part of a 32 bit register 和why sometimes modern compilers use add instead of inc 的原因
-
我会把答案再扩展一点......通常你不需要直接访问寄存器的高位。如果您有两个 8 位变量,则只需使用两个寄存器(例如
al, cl)。使用al, ah是对原始 8086 设计的充分利用,当然有时在创建 256B 介绍时很方便,但对于一般编译器(大约 95% 以上的软件是由编译器产生的),这没什么价值,无论如何,他们必须有管理备用寄存器短缺的机制,这样他们就可以忍受只能从底部通过特定大小访问的寄存器。 -
还有一件事(tm):
mov BYTE PTR result, r8...好吧,我们可以讨论这种助记符的有效性(英特尔的原始语法不会这样,它是英特尔的mov [address],r8b,但是一些智能汇编器可以处理你的),但最终归结为指令编码,即 CPU 已知哪些指令。 x86/x64 CPU 可以进行直接寻址或rip-相对寻址(目标参数),但受影响内存的大小不是其中的一部分,也不是mov [mem],r指令操作码的一部分,它被编码在源操作数中,当r8使用时,这意味着要写入 8 个字节。
标签: assembly x86 64-bit x86-64 cpu-registers