watashiSHUN
watashiSHUN

Reputation: 10484

How can an assembly instruction of 4 byte encode a 4 byte memory address?

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

Answers (2)

mcleod_ideafix
mcleod_ideafix

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

Jester
Jester

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

Related Questions