5

我对指令大小和可寻址空间有点困惑(我认为指令大小应该与地址位大小相同,我没有在我的位置找到足够的解释如果我是正确的,那么在理论上,如果我们在32位体系结构(RISC风格)中有2^32个可寻址单元(字节)的内存,4字节大小的加载指令如何保存操作码以及地址?32位IR保持加载指令?(RISC风格32位架构)

+0

你甚至可以有*的指令没有*地址位,取决于你想让你的寻址方式有 – harold

+0

你假设一条指令可以编码来自任意绝对地址的负载。有一些技巧可以使跳转变得更加灵活,但是代码通常不需要*来包含可能非常遥远的数据的硬编码地址。 –

+0

那么,通常我们无法使用即时模式访问任何任意地址? – Saravanan

回答

1

通过限制可以在范围内表示的值的数量,可以在4字节指令内对32位立即值进行编码。

ARM通过对8位立即数进行编码,再加上一个指定旋转的附加4位字段来完成此操作。 CPU通过取这8位并计算4位字段指示的次数来计算立即数。

2

对于存储器访问指令,指令通常使用带偏移量的地址寄存器。东西的形式:load R1, [R2 + 8]。 ARM,x86,MIPS和其他许多提供这种模式。通常可以选择使用PC作为地址寄存器,以便能够获取代码旁边的常量。

对于跳转指令,除了使用地址寄存器外,通常还有一个偏移跳转,它不使用任何寄存器,而是向前或向后跳转X指令。偏移量通常在范围内受到限制,并且可能会偏移一定的数量(限制为地址倍数2,4 ...),因此它可以放入一个小的立即数操作数中。
MIPS也使用绝对跳转和相对跳转之间的混合:j指令跳转到绝对地址,但是在当前指令的区域中。确切地说,立即地址缺少一些高位(以便它可以适合),并且使用当前PC的高位代替。

1

还有一个技巧(ARM也使用这个版本):如果指令地址必须是4字节对齐的,不要包含2个最低位 - 它们必须为零。你现在有2位操作码。

而有些处理器根本不支持绝对地址,只是较长的相对偏移量。那些系统使用蹦床进行更长的跳跃。

3

你假设一条指令可以从任意的绝对地址编码一个负载。这在x86上也是如此,即使在64位模式下也是如此(但是有一个特殊的操作码用于从64位绝对地址加载,没有位移或索引寄存器,并且dest必须是rax)。

在大多数RISC架构中,绝对地址的加载通常使用两条mov-immediate指令来设置寄存器的上半部分和下半部分,然后使用该寄存器作为加载地址。

例如,

int a; 
int foo(void) { return a; } 

compiles to (ARM gcc 4.8.2 on godbolt)

foo(): 
    movw r3, #:lower16:.LANCHOR0 @ tmp113, 
    movt r3, #:upper16:.LANCHOR0 @ tmp113, 
    ldr r0, [r3] @, a 
    bx lr @ 
a: 
    .space 4