ABI on x86 and arm for Linux
It’s very important to know the ABI or it may be very hard to do reversing engineering. This article will give you a glimpse about the x86’s and arm’s ABI for Linux.
To investigate the ABI, we need some sample code. Here we use below C source code.
|
|
Just save it as abi.c.
1. x86
Use below command to build it.
|
|
Then remove unnecessary asm code, we get below part.
|
|
Here we can see that in main, the L3 and L2’s first two line is the for loop, and args starts from -68(%ebp), before call sum, it do 10 times push operation to put all the args to the stack, the order is from int j to int a, aka. from the tail to head. Then the sum is called, this will cause a ret address also be push to the stack, so the stack grows about 10 * 4 + 4 = 44 Bytes, here don’t care about why it sub 48 bytes after call sum, since before ret, it just use ebp to restore the stack, which will ensure the balance.
1.1 Conclusion
Here we know that in x86, all args will be put on stack.
2. x86_64
|
|
Then we get below asm code.
|
|
Here we can see that the order also is from int j to int a. But the first four args(from right to left) will use register edi/rdi, esi/rsi, edx/rdx, ecx/rcx, r8d/r8, r9d/r9. The reminds will be put on stack in order.
The ret value also put on eax/rax.
And the return still in the stack, same as x86.
arm
|
|
Strip unnecessary part, we will get below asm code.
|
|
So we can see that for arm, from the left to right, the first four args will be put in register r0, r1, r2, r3, then the remains will be put on stack in order. Here cause sum is called via instruction bl sum, so in sum it will use bx lr to return to main.
In arm, below registers have special usage:
- r15: pc
- r14: lr
- r13: sp
- r12: ip(intra procedure call)
- r11: fp
- r10: sl(stack limit)
- r9: sb(stack base)
aarch64
|
|
Use above command to get assembly for aarch64, then remove the unnecessary part, we get below code:
|
|
As we can see, for aarch64, more registers can be used to store args than arm, for args from left to right, first eight args will be stored in register w0, w1, w2, w3, w4, w5, w6, w7, the remains will be put on stack in order.
And the return is different that arm casue here it use ret, which in format ret {xm}, when xm is omitted, it will use x30(aka. lr)
In aarch64, below registers have special usage:
- x30: lr
The 31th register will have different usage:
- sp/wsp: stack pointer/32-bit stack pointer
- xzr/wzr: zero register
Also, In AArch64 state, the PC is not a general purpose register and you cannot access it by name.
Related Reading
- https://developer.arm.com/docs/den0024/latest/an-introduction-to-the-armv8-instruction-sets/the-armv8-instruction-sets/registers
- http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0801a/BABBGCAC.html
- http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0801a/BABBDBAD.html
- http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0068b/ch03s03s01.html
- http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.kui0060a/is51_ret.htm