Relative versus absolute jmp in assembly

I was interested to know the following. When I wrote the assembler language, I noticed that IA32 is designed in such a way as to facilitate the use of relative jumps, i.e. Move the number of byte moves compared to using absolute transitions, i.e. change eip to a specific address in memory. What is the logic behind this?

+8
source share
2 answers

Most jumps are aimed at targets that are far from the jump instruction. Since jump instructions are provided that accept a signed 16-bit value, they may be fewer bytes than necessary for an absolute jump (usually 4 bytes plus the instruction itself).

One small additional advantage of relative branches is that they do not need to be fixed in the linker or, for that matter, go through the additional indirection necessary in the PIC (position-independent code).

+14
source

Relative leaps allow compilers to generate relocatable code, which means the code will work anywhere in memory; It is not tied to a fixed location. This is a critical concept of libraries: you can write the code once and compile it into a file of a movable object, which can be linked as is in any program. The compiler should assign absolute addresses only for functions that are externally accessible (so your own code can find them); all "internal" jumps are relative and should not change from one executable to the next.

It is worth your time to write code in a high-level language such as C, have a compiler generate the assembly code (check the -S option on gcc), and then read the assembly output. Pay particular attention to conditionals and loops such as if , for and while , and you will see that they all generate relative jumps.

Here's a far-fetched example using dummy build commands:

 // Sample C code Address Assembly Code Comments if (x < 10) { 0000 CMP x,#10 ; Compare x to 10 do_true_stuff(); 0003 JGE +7 ; Skip 7 bytes to 000A if x>=10 } else { 0005 SUB do_true_stuff ; x<10 do_false_stuff(); 0008 JMP +5 ; Skip 5 bytes to 000D } 000A SUB do_false_stuff ; else-branch (x>=10) do_more_stuff(); 000D SUB do_more_stuff ; Finished if/else 

Here, the compiler generates relative jumps ( JGE and JMP ) to skip the incomplete branch of the if-else block. These jumps will work regardless of where in the memory the linker places the code. If they were absolute leaps, the linker would have to recount the addresses each time it linked the code.

You will even find that many function calls will generate relative jumps, especially if functions are limited within a single file. This not only speeds up the binding process, but also makes working code smaller and more efficient. This is because relative addresses are usually limited to a much smaller range than absolute addresses, which means that they can be represented in fewer bytes.

Hope this helps!

+9
source

All Articles