2

I'm on the OSX platform working with x86_64. I've worked out how to do near jumps with the E9 byte code directive where my relative addresses have 4 bytes (teamed up with RIP)
Now I have an instance where I've allocated something at a very high address and where I'm going to be referencing it is very far away in the same process. the end result is that the difference between the RIP and the starting address results in 5 bytes. (if I use relative addressing). I was attempting to use FF 25 + 4 bytes + 1 byte and the fifth wasn't being interpreted as part of the command.
Indeed when I looked up the data in the table x86 architecture mod R/M byte it noted FF 25 (apparently does a RIP+signed dword). This would explain why 1 byte was being dropped. I tried examining the table and do not really understand it.

So the questions I have are

  1. How do I read the table so as to understand how to get the byte code to set up so I can do question #3 correctly?
  2. Does JMP /5 use a direct address or indirect addressing (do I have to involve the RIP as a part of the calculation)?
  3. What set of byte codes do I need to assemble to get a JMP /5 to take effect (eg: FF ... )

typical 4 byte jump (e9) code might look like this: (lldb session)

-> 0x100000ebb:  81 7d fc 03 00 00 00  cmpl   $0x3, -0x4(%rbp)
   0x100000ec2:  0f 85 05 00 00 00     jne    0x100000ecd           
   0x100000ec8:  e9 3b 57 34 12        jmp    0x112346608
   0x100000ecd:  48 8d 3d bc 00 00 00  leaq   0xbc(%rip), %rdi  
1
  • I figured out my main problem is I need to use jmpq (FF 25) + 4 bytes and I need to designate the sign bit somehow. At the moment I do not know how to designate the sign bit. and I still don't know how to read the table (question #1).
    – Div
    Jan 19, 2017 at 2:41

2 Answers 2

3

There is no JMP-64bit-OFFSET instruction in AMD64 (don't ask me, normaly they are not stingy with new opcodes).

Quote from x86asm.net about JMPF:

AMD64 Architecture Programmer's Manual Volume 3: If the operand-size is 32 or 64 bits, the operand is a 16-bit selector followed by a 32-bit offset. (On AMD64 architecture, 64-bit offset is not supported)

What one would do instead, is to use an indirect jump like this:

mov rax, 0x100000ebb
jmp rax

This also works for 32 bit applications and directly jumps to the address contained in the register (no offset).

For further information, have a look at the related questions at StackOverflow: here and here

edit:

about assembler and signs: The highest-value bit in a byte sequence is usually considered to be the sign bit. For example, when using relative jumps, it will treat the offset as a two-complement number. If the result is negative, it subtracts the number from the instruction pointer.

0

This might have nothing to do with your scenario and if so I apologize. :) I came across your post while trying to figure out why a relative jump seemed off by 5 bytes. So I wanted to leave this answer here in case anyone else stumbles along the same path.

TL;DR: a x86 relative jump uses an offset whose displacement is relative to the next instruction.

I was looking at some assembly and trying to figure out where the +5 bytes was coming from...

0x7FFE9BAD116D : E9 74690000 ; jmp to 0x7FFE9BAD7AE6

I was calculating 0x7FFE9BAD116D + 6974 (remember we're on little endian) = 7FFE9BAD7AE1 , so I was confused about the 5 bytes difference.

I looked up the E9 opcode and saw the answer:

Jump near, relative, displacement relative to next instruction.

So in my example above, the current instruction is 5 bytes (1 byte opcode plus 4 byte address offset).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.