As a way to refresh my knowledge on assembly, I tried to compile the below C program to x86 assembly by hand.
#include <stdio.h>
long f(long a, long b, long c, long d, long e, long f, long g, long h) {
long xx = a * b * c * d * e * f * g * h;
long yy = xx + 1;
long zz = yy * 2;
return xx + yy + zz;
}
int main() {
printf("%d", f(3, 4, 5, 6, 7, 8, 9, 10));
return 0;
}
Here is the corresponding assembly program:
; nasm -f elf64 test.asm && gcc -no-pie -fno-pie -o test test.o && ./test
bits 64
global main
extern printf
extern exit
section .text
f:
push rbp
mov rbp, rsp
sub rsp, 24
push r12
push r13
mov r12, rdi
mov r13, rsi
imul r12, r13
mov rax, r12
imul rax, rdx
imul rax, rcx
imul rax, r8
imul rax, r9
imul rax, [rbp+24]
imul rax, [rbp+32]
mov [rbp-8], rax
add rax, 1
mov [rbp-16], rax
imul rax, 2
mov [rbp-24], rax
mov rax, [rbp-8]
add rax, [rbp-16]
add rax, [rbp-24]
pop r13
pop r12
add rsp, 24
pop rbp
ret
main:
mov rdi, 3 ; arg 1
mov rsi, 4 ; arg 2
mov rdx, 5 ; arg 3
mov rcx, 6 ; arg 4
mov r8, 7 ; arg 5
mov r9, 8 ; arg 6
mov rax, 9
push rax ; arg 7
mov rax, 10
push rax ; arg 8
sub rsp, 8 ; stack alignment procedure (call will add extra 8 bytes)
call f ; the return value will be in rax
add rsp, 24 ; remove arg 7 and arg 8 from the stack (and the extra space from stack aligment)
mov rdi, fmt ; arg 1
mov rsi, rax ; arg 2
xor rax, rax ; since printf is varargs, so we need to clear rax
call printf
mov rdi, 0 ; arg 1
call exit
section .data
fmt: db "%d", 10, 0 ; "%d\n\0"
(I am using Linux-based machine to run this program.)
There are no errors with this program (I hope!) and it produces the same output as the original C code.
I am wondering what are possible ways I can improve my assembly code (i.e. making it faster and safe). I believe I can write the function f in a better way: use less registers and mov instructions. There are some things I am uncertain:
I am not sure whether I aligned the stack pointer correctly before each
callinstruction. I believe I did so.I ended the program by making call to
exitfunction. I am not sure if it is the best way to do it.
Other suggestions are welcome!