4字节的汇编指令如何编码4字节的存储器地址?

时间:2015-10-04 22:00:12

标签: assembly linker makefile

我没有特定的机器设置,但总的来说我在C ++中编写了以下内容:

int* x;
x = 0xFFFFFFFF;
int* y; 
y = 0x00000000;

*y = *x

我可以想到在汇编中这样做的方法:

// find &x (on the stack frame) using the frame register + an offset
// load value of x into register 0
load *(register 0) -> register 1   // load value of *x
load y -> register 2
store register 1 register 2

但是,上述指令都没有编码存储器地址(4GB存储器为32位),只编码寄存器地址(如果我们有32个寄存器,则指令需要5位)

TL; DR 我的问题是像“分支”(函数调用)这样的指令,它需要一个函数地址(或链接器给出的符号),它实际上是一个32位的内存地址......它怎么可能(假设每个汇编指令也是4字节大)?如果“branch”也使用临时寄存器来存储地址(就像我给出的例子那样),这是否意味着“branch”不是原子操作?

2 个答案:

答案 0 :(得分:1)

  

我的问题是关于" branch" (函数调用),它   获取一个函数地址(或链接器给出的符号)   事实上一个32位的内存地址......它怎么可能(假设每个组件   指令也是4个字节大)?如果"分支"也用临时的   注册以存储地址(就像我给出的例子),这样做   意思是"分支"不是原子操作吗?

可以通过以下几种方式完成:

  • 通过使用PC相对寻址:目标地址不是编码为绝对地址,而是编码为相对于PC当前值的有符号偏移量。这利用了相互关联的相关函数,因此它们之间的距离可以用16位有符号整数进行编码。

  • 使用32位寄存器作为操作数,而不是使用中间操作数。因此,32位寄存器先前加载了CALL或JUMP指令的目标地址,然后,CALL / JUMP进入该寄存器指向的地址。这将32位指令中的32位值转换为LOAD / STORE指令的问题,LOAD / STORE指令通常在两个阶段执行此操作,具有LOADHI和LOADLOW指令以加载32位寄存器的一半,或者只有一个LOADLOW指令并使用SHIFTLEFT指令。

答案 1 :(得分:0)

在许多体系结构中,控制传输使用范围小于32位的相对编码。在其他体系结构上,指令不是固定为32位。您还可以通过寄存器或内存进行间接跳转。加载寄存器和跳转可能不是原子的,但通常不关心,特别是如果你编写C代码。