|
CS456 - Systems Programming
| Displaying exercises/e4/files/lib.s
; To compile to .o:
; nasm -felf64 lib.s
%include "lib.h"
GLOBAL getrandom, strlen, puts, putc, getc, exit
GLOBAL isspace, isdigit, printnum, printnumnl, atoi
SECTION .bss
_ch: resb 1
_randbuf: resq 1
numbuf: resb 32
SECTION .text
; Converts the string pointed by rsi to a number in rax:
; registers used: rax, rsi, r8, r11, rdx
atoi:
mov r8, 0 ; int64_t r8 = 0;
mov r11, 0 ; int r11 = 0;
cmp BYTE [rsi], '-' ; if (*rsi == '-') {
jne .loop
mov r11, 1 ; r11 = 1;
inc rsi ; rsi++;
; }
.loop:
mov al, BYTE [rsi] ; while (isdigit(*rsi)) {
call isdigit
cmp rdx, 0
je .done
imul r8, r8, 10 ; r8 = r8 * 10;
movzx rdx, BYTE [rsi] ; rdx = *rsi; // r8 = r8 + (*rsi - '0');
sub rdx, '0' ; rdx -= '0';
add r8, rdx ; r8 += rdx;
inc rsi ; rsi++;
jmp .loop ; }
.done:
cmp r11, 1 ; if (r11)
jne .return
neg r8 ; r8 = -r8;
.return:
mov rax, r8 ; rax = r8;
ret ; return
; rax holds the number to be printed:
printnum:
mov rdi, 31
mov rsi, 3
mov BYTE [numbuf + rdi], 0
mov rbx, 10
.loop:
dec rsi
cmp rax, 0
jne .else
cmp rdi, 31
je .else
dec rdi
mov BYTE [numbuf+rdi], ' '
cqo
div rbx
jmp .endif
.else:
dec rdi
cqo
div rbx
add rdx, '0'
mov BYTE [numbuf + rdi], dl
.endif:
cmp rax, 0
jg .loop
cmp rsi, 0
jg .loop
lea rsi, [numbuf + rdi]
call puts
ret
printnumnl:
call printnum
mov al, `\n`
call putc
ret
; places 64 bits of randomness into rax:
getrandom:
mov rax, SYS_getrandom
mov rdi, _randbuf
mov rsi, 8
mov rdx, GRND_NONBLOCK
syscall
mov rax, [_randbuf]
ret
; string in rsi, compute the length in rdx
strlen:
mov rdx, 0 ; rdx = 0
.loop:
cmp BYTE [rsi+rdx], 0 ; while (rsi[rdx] != '\0')
je .done
inc rdx ; rdx++;
jmp .loop
.done:
ret
; Expects the address of string to be printed in rsi
puts:
call strlen
mov rax, SYS_write
mov rdi, STDOUT_FILENO
syscall
ret
; character to be printed in al
; write(STDOUT_FILENO, &_ch, 1);
putc:
mov [_ch], al
mov rax, SYS_write
mov rdi, STDOUT_FILENO
mov rsi, _ch
mov rdx, 1
syscall
ret
; return character read in rax, or -1 on EOF:
getc:
mov rax, SYS_read
mov rdi, STDIN_FILENO
mov rsi, _ch
mov rdx, 1
syscall
cmp rax, 0
jle .eof
mov al, BYTE [_ch]
ret
.eof:
mov rax, -1
ret
; rdx = isspace(al)
isspace:
cmp al, ' '
je .true
cmp al, `\t`
je .true
cmp al, `\n`
je .true
cmp al, `\v`
je .true
cmp al, `\f`
je .true
mov rdx, 0
ret
.true:
mov rdx, 1
ret
; rdx = isdigit(al);
isdigit:
cmp al, '0'
jl .false
cmp al, `9`
jg .false
mov rdx, 1
ret
.false:
mov rdx, 0
ret
; expects the exit status in rdi
exit:
mov rax, SYS_exit
syscall
ret
|