title: GCC/X86, Problems with relative jumps
body: <p>I'm trying to do a relative jump in x86 assembly, however I can not get it to work. It seems that for some reason my jump keeps getting rewritten as an absolute jump or something.</p>
  
  <p>A simple example program for what I'm trying to do is this:</p>
  
  <pre><code>.global main
  
  main:
      jmp 0x4
      ret
  </code></pre>
  
  <p>Since the jmp instruction is 4 bytes long and a relative jump is offset from the address of the jump + 1, this should be a fancy no-op. However, compiling and running this code will cause a segmentation fault.</p>
  
  <p>The real puzzler for me is that compiling it to the object level and then disassembling the object file shows that it looks like the assembler is correctly doing a relative jump, but after the file gets compiled the linker is changing it into another type of jump. </p>
  
  <p>For example if the above code was in a file called asmtest.s:</p>
  
  <pre><code>$gcc -c asmtest.s
  $objdump -D asmtest.o
  
  ... Some info from objdump
  00000000 &lt;main&gt;:
     0:    e9 00 00 00 00           jmp    5 &lt;main+0x5&gt;
     5:    c3                       ret   
  </code></pre>
  
  <p>This looks like the assembler correctly made a relative jump, although it's suspicious that the jmp instruction is filled with 0s. </p>
  
  <p>I then used gcc to link it then disassembled it and got this:</p>
  
  <pre><code>$gcc -o asmtest asmtest.o
  $objdump -d asmtest
  
  ...Extra info and other disassembled functions
  08048394 &lt;main&gt;:
   8048394:        e9 6b 7c fb f7      jmp   4 &lt;_init-0x8048274&gt;
   8048399:        c3                  ret
  </code></pre>
  
  <p>This to me looks like the linker rewrote the jmp statement, or substituted the 5 in for another address.</p>
  
  <p>So my question comes down to, what am I doing wrong?</p>
  
  <p>Am I specifying the offset incorrectly? Am I misunderstanding how relative jumps work? Is gcc trying to make sure I don't do dangerous things in my code?</p>