Skip to content

Instantly share code, notes, and snippets.

@FROGGS
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FROGGS/00cc9c2b4c1443f4f613 to your computer and use it in GitHub Desktop.
Save FROGGS/00cc9c2b4c1443f4f613 to your computer and use it in GitHub Desktop.
objdump -D -b binary -m i386:x86-64 -M intel jit-code.bin
jit-code.bin: Dateiformat binary
Disassembly of section .data:
0000000000000000 <.data>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 57 push rdi
5: 56 push rsi
6: 49 89 f6 mov r14,rsi
9: 4d 8b 7e 10 mov r15,QWORD PTR [r14+0x10]
d: 49 c7 07 02 00 00 00 mov QWORD PTR [r15],0x2
14: 49 c7 47 08 02 00 00 mov QWORD PTR [r15+0x8],0x2
1b: 00
1c: 49 8b 07 mov rax,QWORD PTR [r15]
1f: 49 03 47 08 add rax,QWORD PTR [r15+0x8]
23: 49 89 47 18 mov QWORD PTR [r15+0x18],rax
27: 48 8b 7d f8 mov rdi,QWORD PTR [rbp-0x8]
2b: 49 8b 77 18 mov rsi,QWORD PTR [r15+0x18]
2f: 48 c7 c2 00 00 00 00 mov rdx,0x0
36: 49 ba 11 16 f4 04 00 movabs r10,0x4f41611
3d: 00 00 00
40: 41 ff d2 call r10
43: 4c 8b 75 f0 mov r14,QWORD PTR [rbp-0x10]
47: 4d 8b 7e 10 mov r15,QWORD PTR [r14+0x10]
4b: eb 00 jmp 0x4d
4d: 48 89 ec mov rsp,rbp
50: 5d pop rbp
51: c3 ret
@bdw
Copy link

bdw commented Jun 12, 2014

0: pushes the stack base pointer on the stack.
1: move the base pointer to the stack top
4,5: push rdi, rsi (argument registers) on the stack.

When a function is called, a callee is responsible for managing stack space. The registers rbp and rsp keep the stack base and stack top, respectively. The old stack base must be saved, and the stack top becomes the new stack base. (Linte 1). Note that in intel syntax, the destination operand is always the first operands, and source operands are second. The 'push' instruction moves it argument to the top of the stack and increases (actually, decreases) the stack pointer. So line 4,5 end up saving the function arguments on the stack, and at the same time decrease the stack top by 16 bytes (a register is 8 bytes wide).

6,9: These set up the 'special environment' for MoarVM. The rsi register holds the MVMFrame* argument that was passed to the code. The 'work space' registers created by MoarVM are kept in register r15, and are frequently refered to.

d,14: Store the literal value 0x2 in the MoarVM 'registers' 0 and 1, respectively.

The [register+number] syntax is used to refer to a memory location relative to the value of the register. Thus, if register r10 contains the value 0x40, [r10 + 0x8] refers to the memory location 0x48. These can be used as lvalues and as rvalues, depending on operand.

1c-23: add values of MoarVM registers 0 and 1 into MoarVM register 3.
This is somewhat obscure code because I use indirection in the add instruction to directly add moar-register 1 to the value of moar-register 0 which I stored in the rax register. There is no special reason to use rax here, it's just a register that can be overwritten freely.

27-2f: Set up arguments for a function call.
In x86-64, function arguments are passed via registers.If you ask me - you shouldn't - then for most modern software this is wrong, as the next thing that happens (as it did here) is that these arguments are then stored on stack space. Why not pass 'm on stack space and save yourself the trouble, I say. Anyway, the order of register in which arguments are passed are rdi, rsi, rdx, rcx, r8, r9, and remaining arguments are then passed on the stack(!). The number of variable arguments - if applicable - are passed in the rax register.

36-40: Load the function pointer (as a literal) and call it.

For what it is worth, this is a call to MVM_args_set_result_int, and the first argument is the threadcontext (8 bytes from our stack base), the second argument is the value of moarvm register 3, and the third argument is a constant zero.
I'm not sure if the operand of call actually has to be a register or can also be a literal, however because of dasm limitations, inserting a literal pointer might mean that the top half of the value is forgotten.

43-47: restore the moarvm-specific registers. This is not needed here, as we'll return shortly after, and I hope to eliminate them in due course. However they don't matter that much, either.

4b: jump to the exit of the function. Also not necessary, but I do it for completeness - it's possible we'd compile another block after this.

4d-51: function epilogue. Restore the stack top to the stack base (thus 'clearing' the space 'allocated' in 4,5), and pop the old stack base off the stack (so that the caller will see the right frame). ret returns to the caller. (It is shorthand for pop instruction pointer and jump there, much as call is shorthand for push instruction pointer and jump).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment