global _start section .data STR: db 'this string will be reversed',0xA STRSIZE: equ $ - STR section .text _start: ; Function calls follow the Unix System V ABI on Linux. ; This spec defines the INTEGER class "functions" (not sure what they mean) ; that use the registers: ; %rdi, %rsi, %rdx, %rcx, %r8 %r9 ; Most data types fit the INTEGER class; pointers and integers all fit within ; a single register. So nearly all functions are of this class.. mov rdi, STR ; first arg lea rsi, [STRSIZE - 1] ; second arg (exclude \n) ; Call jumps to the label supplied, but first sets the return point ; in the stack (hence recursion can cause stack overflows) call revstr mov rax, 1 ; write mov rdi, 1 ; stdout mov rsi, STR mov rdx, STRSIZE syscall mov rax, 60 ; see ya later xor rdi, rdi ; ret 0 syscall ; Functions MUST NOT modify the registers: ; rbx and r12 to r15 ; Function arguments go into: ; %rdi, %rsi, %rdx, %rcx, %r8 %r9 ; Function return value(s) end up in: ; %rax, %rdx ; void revstr(char * s, size_t length) ; Reverses the bytes given, e.g. s[length] = s[0], s[length-1] = s[1], etc. revstr: xor r8, r8 ; loop counter lea r9, [rsi - 1] ; loop limit .loop: ; labels prefixed with a dot (.) are LOCAL labels cmp r8, r9 jge .done ; The actual swapping mov cl, byte [rdi + r8] ; one value needs to be a in a register xchg cl, byte[rdi + r9] ; swap s[loop counter] with s[loop limit] mov byte [rdi, r8], cl ; store s[loop counter] manually inc r8 ; ++loop counter dec r9 ; --loop limit jmp .loop .done: ret