gpt4 book ai didi

assembly - 为什么我可以在寄存器中访问较低的 dword/word/byte 但不能访问较高的 dword/word/byte?

转载 作者:行者123 更新时间:2023-12-04 16:26:53 26 4
gpt4 key购买 nike

我开始学习汇编程序,这对我来说似乎不合逻辑。

为什么我不能在一个寄存器中使用多个高字节?

我了解rax的历史原因-> eax -> ax ,所以让我们关注新的 64 位寄存器。例如,我可以使用 r8r8d ,但为什么不r8dlr8dh ? r8w也是如此和 r8b .

我最初的想法是我可以使用 8 r8b同时注册(就像我可以同时处理 alah)。但我不能。并使用 r8b制作完整 r8注册“忙”。

这就提出了一个问题——为什么?如果不能同时使用其他部分,为什么只需要使用寄存器的一部分?为什么不只保留 r8忘记下半部分?

最佳答案

why can't I use multiple higher bytes in a register



指令的每个排列都需要在指令中编码。原始 8086 处理器支持以下选项:
instruction     encoding    remarks
---------------------------------------------------------
mov ax,value b8 01 00 <-- whole register
mov al,value b4 01 <-- lower byte
mov ah,value b0 01 <-- upper byte

因为 8086 是 16 位处理器,所以三个不同的版本涵盖了所有选项。
在 80386 中添加了 32 位支持。设计人员有一个选择,要么添加对 3 组额外寄存器(x 8 个寄存器 = 24 个新寄存器)的支持,并以某种方式为这些找到编码,要么保留大部分内容与以前一样。

以下是设计师选择的内容:
instruction     encoding           remarks
---------------------------------------------------------
mov eax,value b8 01 00 00 00 (same encoding as mov ax,value!)
mov ax,value 66 b8 01 00 (prefix 66 + encoding for mov eax,value)
mov al,value (same as before)
mov ah,value (same as before)

他们只是添加了一个 0x66前缀将寄存器大小从(现在)默认的 32 位更改为 16 位加上 0x67前缀来改变内存操作数的大小。就这样离开了。

否则就意味着 加倍指令编码的数量或为每个"new"部分寄存器添加三个六个新前缀。
到80386出来的时候 全部 指令字节已经被占用,所以没有新前缀的空间。这个操作码空间已经被像 AAA 这样的无用指令吃掉了。 , AAD , AAM , AAS , DAA , DAS SALC . (这些已在 X64 模式下被禁用以释放急需的编码空间)。

如果您只想更改寄存器的较高字节,只需执行以下操作:
movzx eax,cl     //mov al,cl, but faster   
shl eax,24 //mov al to high byte.

But why not two (say r8dl and r8dh)



在最初的 8086 中有 8 个字节大小的寄存器:
al,cl,dl,bl,ah,ch,dh,bh  <-- in this order.

索引寄存器、基指针和堆栈寄存器没有字节寄存器。

在 x64 这被改变了。如果有 REX前缀(表示 x64 寄存器)然后 al..bh (8 regs) 编码 al .. r15l . 16 regs 包括。来自 rex 前缀的 1 个额外编码位。这增加了 spl , dil , sil , bpl ,但不包括任何 xh注册。 (当不使用 xh 前缀时,您仍然可以获得四个 rex regs)。

And using r8b makes the complete r8 "busy"



是的,这称为“部分寄存器写入”。因为写作 r8b更改部分,但不是全部 r8 , r8现在被分成两半。一半变了,一半没变。 CPU 需要加入两半。它可以通过使用额外的 CPU 周期来执行工作,或者通过向任务添加更多电路以便能够在单个周期内完成它来实现此目的。
后者在硅方面很昂贵,在设计方面很复杂,它还增加了额外的热量,因为要做额外的工作(每个周期做更多的工作 = 产生更多的热量)。见 Why doesn't GCC use partial registers?了解不同的 x86 CPU 如何处理部分寄存器写入(以及稍后读取完整寄存器)。

if I use r8b I can't access upper 56 bits at the same time, they exist, but unaccessible



不,他们不是 unaccessible .
mov  rax,bignumber         //random value in eax
mov al,0 //clear al
xor r8d,r8d //r8=0
mov r8b,16 //set r8b
or r8,rax //change r8 upper without changing r8b

你用口罩加 and , or , xornot and改变寄存器的一部分而不影响它的其余部分。

真的从来不需要 ah ,但它确实导致了 8086 上更紧凑的代码(以及更有效的可用寄存器)。编写 EAX 或 RAX 然后分别读取 AL 和 AH(例如 movzx ecx, al/ movzx edx, ah )作为解包字节的一部分有时仍然很有用。

关于assembly - 为什么我可以在寄存器中访问较低的 dword/word/byte 但不能访问较高的 dword/word/byte?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45500399/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com