; nasm -f elf64 -o wsort.o wsort.S ; gcc -o wsort wsort.o BITS 64 DEFAULT REL SECTION .text EXTERN strlen, strtok, strcmp EXTERN stdin, getline, ferror, perror EXTERN puts, fflush, stdout, fputs EXTERN stderr EXTERN realloc, free, qsort, exit GLOBAL main main: ; callee-saved register: push rbp ; used as word array pointer xor rbp, rbp push rbx ; used as word array length xor rbx, rbx push r12; pointer to input/ouput line push r13; unused, but stack must be 16 byte aligned anyway .inputloop: ; call getline xor rax,rax push rax mov rdi, rsp push rax mov rsi, rsp mov rdx, [rel stdin] call getline wrt ..plt pop rdx ; ignore buffer length pop r12 ; pointer to line not rax test rax,rax jz .inputend mov rdi, r12 mov rsi, newline call strtok wrt ..plt; remove newline, returns NULL if line is empty test rax,rax jz .ignore mov rdi, r12 call strlen wrt ..plt cmp rax, 100 ja .ignore_verbose ; collect line and continue mov rdi, rbp lea rsi, [8*rbx + 8] call realloc wrt ..plt mov rbp, rax mov rdi, mem_err call diez mov [rbp+8*rbx], r12 inc rbx jmp .inputloop .ignore_verbose: mov rdi, msg_ignore mov rsi, [rel stderr] call fputs wrt ..plt .ignore: mov rdi, r12 call free wrt ..plt jmp .inputloop .inputend: ; error checking for getline, free the last (unused) line buffer mov rdi, [rel stdin] call ferror wrt ..plt mov rdi, input_err test rax,rax jnz die mov rdi, r12 call free wrt ..plt ; sort mov rdi, rbp mov rsi, rbx mov rdx, 8 mov rcx, compare call qsort wrt ..plt ; output & free mov r12, rbp .printloop: ; rbx counts down (remaining lines to print) cmp rbx, 0 jz .printend mov rdi, [r12] call puts wrt ..plt not eax call diez mov rdi, [r12] call free wrt ..plt dec rbx add r12, 8 jmp .printloop .printend: mov rdi, rbp call free wrt ..plt mov rdi, [rel stdout] call fflush wrt ..plt mov rdi, output_err not eax call diez ; load callee saved registers and return 0 pop r13 pop r12 pop rbx pop rbp xor rax,rax ret ; die if rax is zero (for malloc, or inverted EOF=-1) ; takes perror argument in rdi diez: test rax,rax jnz .ok jmp die .ok: ret ; perror(rdi), exit(1) die: call perror wrt ..plt ; argument already in rdi mov rax, 1 jmp exit wrt ..plt compare: ; dereferencing strcmp for qsort mov rdi, [rdi] mov rsi, [rsi] jmp strcmp wrt ..plt output_err: db "Error while writing output", 0 mem_err: db "Error while allocating memory", 0 input_err: db "Error while reading input", 0 msg_ignore: db "Line too long, ignoring", 10,0 newline: db 10,0 ; strtok argument