Hello World in x64 Assembler
I should really brush up on this stuff.. this is some old junk I found laying around. I wish I could write assembler as well as I could in 2016. Maybe a resolution for 2020?
Just seeing int 0x80
below, I’m not sure if this is x64 or x86/32-bit. (Shouldn’t that be syscall
?) It is what it is.
hello-world.asm
section .text
global mystart
mystart:
push dword mylen
push dword mymsg
push dword 1
mov eax, 0x4
sub esp, 4
int 0x80
add esp, 16
push dword 0
mov eax, 0x1
sub esp, 4
int 0x80
section .data
mymsg db "hello, world", 0xa
mylen equ $-mymsg
x64.asm
; /usr/local/bin/nasm -f macho64 64.asm
; && ld -macosx_version_min 10.7.0 -lSystem -o 64 64.o
; && ./64
%include "x64-lib.asm"
Sub start
extern _printf
String int_msg, "%52lu (%16lxh)", 0Ah, 00h
; __call _printf, int_msg, 01FFFFFFFFh, 01FFFFFFFFh
__call _printf, int_msg, 0ffffffffffffffffh, 0ffffffffffffffffh
__call square32, 0ffffffffh
__call _printf, int_msg, rax, rax
__call _printf, int_msg, 46341, 46341
__call square32, 46341
__call _printf, int_msg, rax, rax
__call _printf, int_msg, -1, -1
__call square32, -1
__call _printf, int_msg, rax, rax
__exit 0
EndSub
Sub square32 ;N
mov rax, rdi
mul rdi
EndSub
x64-lib.asm
section .data
STDOUT equ 1
; User-level applications use as integer registers for
; passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9.
; The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.
; A system-call is done via the syscall instruction. The kernel
; destroys registers %rcx and %r11.
; The number of the syscall has to be passed in register %rax.
; System-calls are limited to six arguments, no argument is passed
; directly on the stack.
; Returning from the syscall, register %rax contains the result of
; the system-call. A value in the range between -4095 and -1 indicates
; an error, it is -errno.
; Only values of class INTEGER or class MEMORY are passed to the kernel.
section .text
global start
%macro Sub 1
%1:
push rbp
mov rbp, rsp ;PROLOGUE
and rsp, 0xFFFFFFFFFFFFFFF0
%endmacro
%macro EndSub 0
.Return:
mov rsp, rbp ;EPILOGUE
pop rbp
ret
%endmacro
%macro String 2+
section .data
%1:
. db %2
.len equ $-.
section .text
%endmacro
; BSD systems (MacOS X included) use similar system calls,
; but convention to execute them is different. While on Linux
; you pass system call arguments in different registers, on BSD
; systems they are pushed onto stack (except the system call
; number, which is put into eax, the same way as in Linux).
;
; https://en.wikibooks.org/wiki/X86_Assembly/NASM_Syntax
%macro __syscall0 1
mov rax, %1
syscall
%endmacro
%macro __syscall1 2
mov rdi, %2
__syscall0 %1
%endmacro
%macro __syscall2 3
mov rsi, %3
__syscall1 %1, %2
%endmacro
%macro __syscall3 4
mov rdx, %4
__syscall2 %1, %2, %3
%endmacro
%macro __syscall4 5
mov r10, %3
__syscall3 %1, %2, %3, %4
%endmacro
%macro __syscall5 6
mov r8, %4
__syscall4 %1, %2, %3, %4, %5
%endmacro
%macro __syscall6 7
mov r9, %7
__syscall5 %1, %2, %3, %4, %5, %6
%endmacro
%macro __write 3
__syscall3 0x2000004, %1, %2, %3
%endmacro
%macro __exit 1
__syscall1 0x2000001, %1
%endmacro
%macro __call0 1
and rsp, 0xFFFFFFFFFFFFFFF0
call %1
%endmacro
%macro __call1 2
mov rdi, %2
__call0 %1
%endmacro
%macro __call2 3
mov rsi, %3
__call1 %1, %2
%endmacro
%macro __call3 4
mov rdx, %4
__call2 %1, %2, %3
%endmacro
%macro __call4 5
mov rcx, %5
__call3 %1, %2, %3, %4
%endmacro
%macro __call5 6
mov r8, %6
__call4 %1, %2, %3, %4, %5
%endmacro
%macro __call6 7
mov r9, %7
__call5 %1, %2, %3, %4, %5, %6
%endmacro
%macro __call 1-7
%if %0 == 1
__call0 %1
%elif %0 == 2
__call1 %1, %2
%elif %0 == 3
__call2 %1, %2, %3
%elif %0 == 4
__call3 %1, %2, %3, %4
%elif %0 == 5
__call4 %1, %2, %3, %4, %5
%elif %0 == 6
__call5 %1, %2, %3, %4, %5, %6
%elif %0 == 7
__call6 %1, %2, %3, %4, %5, %6, %7
%endif
%endmacro