Reputation: 10484
I don't have a specific machine setup, but let's say in general I wrote the following in C++:
int* x;
x = 0xFFFFFFFF;
int* y;
y = 0x00000000;
*y = *x
I can think of a way of doing this in assembly:
// 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
however, none of the above instructions have a memory address encoded (which is 32 bits for 4GB memory), only the address of a register is encoded (if we have 32 registers, it takes 5 bits in the instruction)
TL;DR My question is for instructions like "branch" (function call), it takes a function address (or a symbol given by linker) which is in fact a 32 bits memory address...how can it be(assuming each assembly instruction is also 4 bytes big)? if "branch" also use temporary registers to store the address(like the example I gave), does that mean "branch" is not an atomic operation?
Upvotes: 2
Views: 1821
Reputation: 11428
My question is for instructions like "branch" (function call), it takes a function address (or a symbol given by linker) which is in fact a 32 bits memory address...how can it be(assuming each assembly instruction is also 4 bytes big)? if "branch" also use temporary registers to store the address(like the example I gave), does that mean "branch" is not an atomic operation?
It can be done in several ways:
By using PC relative addressing: the destination address is not encoded as an absolute address, but as a signed offset relative to the current value of the PC. This takes advantage of related functions being close one to another, so distance between them can be encoded in a 16-bit signed integer.
By using a 32 bit register as operand, instead of having an inmediate operand. Thus, a 32 bit register is previously loaded with the destination address of a CALL or JUMP instruction, and then, the CALL/JUMP is made to the address pointed by that register. This shifts the problem of having a 32 bit value in a 32 bit instruction to the LOAD/STORE instructions, which normally do this operation in two stages, having LOADHI and LOADLOW instructions to load either half of a 32 bit register, or having only a LOADLOW instruction and using SHIFTLEFT instruction.
Upvotes: 2
Reputation: 58762
On many architectures, control transfers use relative encoding with a range less than 32 bits. On other architectures, instructions are not fixed at 32 bits. You also get indirect jumps via register or memory. Loading a register and jumping is probably not atomic, but you don't normally care, especially if you write C code.
Upvotes: 0