如果我在rbx寄存器中有一个地址,并使用如下指令:
mov rax, [rbx+1]
字符串rbx+1在运行时是在硬件中计算的吗?如果是的话,是使用了一些寄存器还是有一个专用的硬件?我想做同样的指令,但用一个符号,而不是像这样的寄存器,
string: db "I'm lost", 0 mov rax, [string+1]
型将允许在编译时完成计算,因为它已经在内存中保留了一个位置。而rbx将是更多的变量,直到运行时才知道。
xzabzqsa1#
所有的CPU,甚至是最初的8086,都有一些临时缓冲区与架构寄存器分开。8086使用主ALU进行地址数学,所以add ax, [bx + si + 1]需要使用临时存储;地址数学不会影响BX或RBX寄存器中的软件可见值。像8086这样的旧CPU通过运行一系列内部微码指令来处理简单的x86指令,而现代CPU则将mov eax, [rbx+1]这样的指令解码为单个微操作(uop),用于加载执行单元。(它们在流水线阶段之间仍然有缓冲,甚至还有一些临时寄存器供xchg eax, ecx等指令使用;在Intel上,这是一个3-uop指令,类似于mov internal_tmp, ecx/mov ecx, eax/mov eax, internal_tmp。)
add ax, [bx + si + 1]
mov eax, [rbx+1]
xchg eax, ecx
mov internal_tmp, ecx
mov ecx, eax
mov eax, internal_tmp
**现代CPU有专用的地址生成单元(AGU)作为加载和存储地址执行单元的一部分,与它们的ALU执行单元分开。**参见https://realworldtech.com/sandy-bridge/10的框图。
相关:
rbx
[rbx+1]
[rbx]
请注意,莱亚是单独的动物;它的结果被写入寄存器,不用于加载或存储,因此现代CPU在ALU执行单元上仅将其作为移位和加法指令来运行。(由于支持它的一些ALU不支持移位部分,或者仅支持一个加法,这取决于CPU型号。参见Using LEA on values that aren't addresses / pointers?-尽管这是真的,不管整数值是否发生在有效指针上。
x6492ojm2#
操作数[rbx+1]表示一个有效的寻址模式。如果不是,那么汇编程序会发出一个错误,因为它不知道如何处理它,因为它涉及到一个寄存器,其值只有在运行时才知道。寻址模式在运行时由硬件解析,它们不会修改指令中可见的寄存器之外的任何寄存器。操作数[string+1]为(据我所知)* 不是 * 一个有效的寻址模式。但这没关系,因为你的汇编程序知道如何处理它:string的地址在汇编期间是已知的,因此汇编器使用该地址加1来计算实际地址,并用[actual_address]替换[string+1],这是一种有效的寻址模式。在理论上,汇编器可以(实际上可能会这样做)允许整个表达式代替+1,只要表达式可以在汇编时进行评估,一切都很好。[string+bx+1]也是如此;严格地说,这不是一种有效的寻址模式,但汇编程序知道如何将汇编时已知的所有偏移量合并组合成一个偏移量,从而得到[computed_offset+bx],这是一种有效的寻址模式。
[string+1]
string
[actual_address]
[string+bx+1]
[computed_offset+bx]
2条答案
按热度按时间xzabzqsa1#
所有的CPU,甚至是最初的8086,都有一些临时缓冲区与架构寄存器分开。8086使用主ALU进行地址数学,所以
add ax, [bx + si + 1]
需要使用临时存储;地址数学不会影响BX或RBX寄存器中的软件可见值。像8086这样的旧CPU通过运行一系列内部微码指令来处理简单的x86指令,而现代CPU则将
mov eax, [rbx+1]
这样的指令解码为单个微操作(uop),用于加载执行单元。(它们在流水线阶段之间仍然有缓冲,甚至还有一些临时寄存器供xchg eax, ecx
等指令使用;在Intel上,这是一个3-uop指令,类似于mov internal_tmp, ecx
/mov ecx, eax
/mov eax, internal_tmp
。)**现代CPU有专用的地址生成单元(AGU)作为加载和存储地址执行单元的一部分,与它们的ALU执行单元分开。**参见https://realworldtech.com/sandy-bridge/10的框图。
相关:
rbx
值是从另一个加载转发的,Ice Lake之前的英特尔CPU实际上会推测[rbx+1]
值与[rbx]
在同一个页面中。这将指针追踪(例如链表和二叉树)的加载使用延迟从通常的5个周期减少到4个周期,让TLB访问更快开始。请注意,莱亚是单独的动物;它的结果被写入寄存器,不用于加载或存储,因此现代CPU在ALU执行单元上仅将其作为移位和加法指令来运行。(由于支持它的一些ALU不支持移位部分,或者仅支持一个加法,这取决于CPU型号。参见Using LEA on values that aren't addresses / pointers?-尽管这是真的,不管整数值是否发生在有效指针上。
x6492ojm2#
操作数
[rbx+1]
表示一个有效的寻址模式。如果不是,那么汇编程序会发出一个错误,因为它不知道如何处理它,因为它涉及到一个寄存器,其值只有在运行时才知道。寻址模式在运行时由硬件解析,它们不会修改指令中可见的寄存器之外的任何寄存器。操作数
[string+1]
为(据我所知)* 不是 * 一个有效的寻址模式。但这没关系,因为你的汇编程序知道如何处理它:string
的地址在汇编期间是已知的,因此汇编器使用该地址加1来计算实际地址,并用[actual_address]
替换[string+1]
,这是一种有效的寻址模式。在理论上,汇编器可以(实际上可能会这样做)允许整个表达式代替+1,只要表达式可以在汇编时进行评估,一切都很好。[string+bx+1]
也是如此;严格地说,这不是一种有效的寻址模式,但汇编程序知道如何将汇编时已知的所有偏移量合并组合成一个偏移量,从而得到[computed_offset+bx]
,这是一种有效的寻址模式。