4

The first form of JMP in x86-64 is:

Opcode    Instruction  Description
EB cb     JMP rel8     Jump short, RIP = RIP + 8-bit displacement sign

So for example JMP rel8=-2 is eb fe. fe is a one byte signed 2s-compliment -2.

How do I express this rel8 immediate in Intel syntax?

I tried the following:

test.s:

.intel_syntax noprefix
.global _start
_start:
    jmp -2

Compile with:

$ gcc -nostdlib test.s
$ objdump -d -M intel

But I get:

   e9 00 00 00 00           jmp    5 <_start+0x5>

Not eb fe as desired.

(More generally, where is Intel syntax documented? I couldn't find anything in the Intel manual about it. The Intel manual explains how to encode operands, but it doesn't give the syntax of the assembly language.)

Update:

Solution is:

.intel_syntax noprefix
.global _start
_start:
    jmp .

. must represent address of current instruction. Assembling it and disassembling gives:

4000d4: eb fe      jmp    4000d4 <_start>

eb fe as desired. RIP-relative addressing is in terms of the next instruction, so the assembler must adjust for the size of the current instruction for you.

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • Have you tried `jmp $+offset`? Or `jmp $` in this case – harold Nov 03 '13 at 10:01
  • @harold: `Error: junk '$-2' after expression` and `Error: junk '$' after expression` respectively. – Andrew Tomazos Nov 03 '13 at 10:05
  • Ok, how about `jmp . + offset`? Apparently GAS breaks with tradition again.. – harold Nov 03 '13 at 10:14
  • Good question about Intel syntax not being documented. The problem is that it *isn't* even standardized, so different assemblers have to document their own syntax (even though they're usually highly similar). NASM and YASM docs for example seem to assume you already know MASM syntax, and just point out the differences from it (like `mov reg, sym` is mov `reg, imm32`, not `mov reg, [mem]`). IIRC, GNU docs for AT&T syntax is not bad, since gas is the only major assembler that uses it. I've had to go looking to check the NASM syntax for register-indirect `jmp rax`, and it's hard to find. – Peter Cordes Dec 28 '15 at 08:22
  • Anyway, the docs for `$` being the current address in NASM is in the NASM docs. Another way to do it would just be to put a local label at the branch target: `.tmp_label: jmp tmp_label`. The symbol won't appear in the object file's symbol, because local labels are forgotten after assemble time. Or maybe GNU as needs `.Ltmp_label`. I forget if label names starting with just `.` are considered local in GNU as like they are in NASM/YASM, or if you need to start them with `.L`. – Peter Cordes Dec 28 '15 at 08:26
  • LLVM's version of as (Apple clang version 11.0.3 (clang-1103.0.32.29)) fails for "jmp ." with xx.s:4:9: error: unknown token in expression" Using ".tmp_label: jmp tmp_label" assembles but unfortunately generates a 32b offset " 0: e9 00 00 00 00 jmp 0 <_start+0x5>" rather than a rel8. This appears to be a bug in LLVM. – Olsonist Sep 19 '20 at 14:06
  • However, "1: jle 1b" generates "0: 7e fe" – Olsonist Sep 19 '20 at 14:17

1 Answers1

4

(G)AS apparently uses . to denote the current address (the address of the current instruction), unlike most other assemblers.

There is a tiny page documenting it here in the documentation.

harold
  • 61,398
  • 6
  • 86
  • 164