开发者

Relative vs Absolute jmp in Assembly

开发者 https://www.devze.com 2023-02-04 16:10 出处:网络
I was wondering about the following. I\'ve noticed when writing assembly language that IA32 is designed in such a way as to promote the use of relative jumps i.e. jump a displacement amount of bytes v

I was wondering about the following. I've noticed when writing assembly language that IA32 is designed in such a way as to promote the use of relative jumps i.e. jump a displacement amount of bytes vs the use of absolute jumps i.e. chang开发者_C百科e eip to a specific address in memory. What is the logic behind this?


Most jumps are to targets not far away from the jump instruction. Since jump instructions are provided that take a signed 16-bit value, they can be fewer bytes than needed for an absolute jump (usually 4 bytes plus the instruction itself).

One small additional advantage of relative branches is that they don't need to be fixed up in the linker, or, for that matter, go through the extra indirection needed in PIC (position independent code).


Relative jumps make it possible for compilers to generate relocatable code, which means the code will run anywhere in memory; it's not tied to a fixed location. This is the critical concept behind libraries: you can write the code once and compile it into a relocatable object file that can be linked as-is into any program. The linker needs to assign absolute addresses only for the functions that are externally accessible (so your own code can find them); all of the "internal" jumps are relative and needn't change from one executable to the next.

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

Here's a contrived example using fictitious assembly instructions:

// 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 over the un-executed branch of the if-else block. These jumps will work no matter where in memory the linker puts the code. If they were absolute jumps the linker would need to recalculate the addresses each time it linked the code.

You'll even find that many function calls will generate relative jumps, particularly if the functions are scoped within a single file. Not only does this speed up the linking process, but it makes the running code smaller and more efficient, too. That's because relative addresses are typically limited to a much smaller range than absolute addresses, which means they can be represented in fewer bytes.

Hope that helps!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号