Im very new to assembly but know a bit of c. Im playing around with extern function calls like
extern _printf
str db \"Hello\", 0
push str
call _printf
Here is my answer. It is specific to x86-64 though. Please know that when pushing arguments to a function, you usually place the first 6 in registers rdi
, rsi
, rdx
, rcx
, r8
, and r9
. The rest get pushed to the stack. The specification for this is called the System V ABI (Note that Windows uses a different convention called the "Microsoft x64 Calling Convention").
segment .data ; or use .rodata for read-only data.
str1 db "Hello", 0x0
str2 db "Hellx", 0x0
fmt db "Comparison = %d", 0xa, 0x0
segment .text
global main
extern strcmp, printf
default rel ; RIP-relative addressing for [name] is what you want.
main:
; Create a stack-frame, re-aligning the stack to 16-byte alignment before calls
push rbp
mov rbp, rsp
; Prepare the arguments for strcmp.
lea rdi, [str1]
lea rsi, [str2]
; Call strcmp, return value is in rax.
call strcmp
; Prepare arguments for printf.
lea rdi, [fmt]
mov esi, eax ; int return value from strcmp -> 2nd arg for printf
xor eax, eax ; Indicate no floating point args to printf.
; Call printf
call printf
; Return 0 (EXIT_SUCCESS), and destroy the stack frame.
xor eax, eax
leave ; or just pop rbp because RSP is still pointing at the saved RBP
ret
Edit: I made a few mistakes here, see comments for details!
Here is a 32bit version (64bit below):
SECTION .data
; global functions in this file
global main
; extern functions
extern strcmp
hworld: ; our first string
db "hello world", 0
hworld2: ; our second string
db "hello world2", 0
SECTION .text
;=============================================================================
; The program entrypoint
;
main:
; int rv = strcmp("hello world", "hello world2");
push hworld2
push hworld
call strcmp
; _exit(rv);
mov ebx, eax
mov eax, 1
int 0x80
Then you can compile it with:
nasm -f elf main.s -o main.o
cc -m32 main.o -o hello_world
And here is the 64bit version:
SECTION .data
; global functions in this file
global main
; extern functions
extern strcmp
hworld: ; our first string
db "hello world", 0
hworld2: ; our second string
db "hello world2", 0
SECTION .text
;=============================================================================
; The program entrypoint
;
main:
; int rv = strcmp("hello world", "hello world2");
mov rsi, hworld2
mov rdi, hworld
call strcmp
; _exit(rv);
mov rdi, rax
mov rax, 60
syscall
Then you can compile the x64 version with:
nasm -f elf64 main.s -o main.o
cc main.o -o hello_world
And run it:
$ ./hello_world
$ echo $?
206