Initial commit
This commit is contained in:
2
bmi-calc/.gitignore
vendored
Normal file
2
bmi-calc/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
main.o
|
||||
bmi-calc
|
9
bmi-calc/Makefile
Normal file
9
bmi-calc/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
bmi-calc: main.o
|
||||
ld -o bmi-calc main.o
|
||||
|
||||
main.o: main.nasm
|
||||
nasm -g -f elf64 -o main.o main.nasm
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f bmi-calc main.o
|
385
bmi-calc/main.nasm
Normal file
385
bmi-calc/main.nasm
Normal file
@ -0,0 +1,385 @@
|
||||
%define SYS_read 0
|
||||
%define SYS_write 1
|
||||
%define SYS_poll 7
|
||||
%define SYS_exit 60
|
||||
|
||||
%define FD_stdin 0
|
||||
%define FD_stdout 1
|
||||
%define FD_stderr 2
|
||||
|
||||
%define POLLIN 1
|
||||
|
||||
section .text
|
||||
global _start
|
||||
_start:
|
||||
prompt_weight:
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,weight_prompt_text
|
||||
mov rdx,weight_prompt_length
|
||||
syscall
|
||||
|
||||
call read_float
|
||||
cmp rax,0
|
||||
jne good_weight
|
||||
|
||||
call clear_stdin
|
||||
jmp prompt_weight
|
||||
|
||||
good_weight:
|
||||
; convert weight to kg
|
||||
divss xmm0,[lb_kg_scale]
|
||||
movq r15,xmm0 ; weight
|
||||
|
||||
prompt_height:
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,height_prompt_text
|
||||
mov rdx,height_prompt_length
|
||||
syscall
|
||||
|
||||
call read_float
|
||||
cmp rax,0
|
||||
jne good_height
|
||||
|
||||
call clear_stdin
|
||||
jmp prompt_height
|
||||
|
||||
good_height:
|
||||
; convert height to cm
|
||||
mulss xmm0,[inch_cm_scale]
|
||||
movq r14,xmm0 ; height
|
||||
|
||||
; print metric weight
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,weight_notice_pre_text
|
||||
mov rdx,weight_notice_pre_length
|
||||
syscall
|
||||
|
||||
movq xmm0,r15
|
||||
mov rdi,3
|
||||
call print_float
|
||||
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,weight_notice_post_text
|
||||
mov rdx,weight_notice_post_length
|
||||
syscall
|
||||
|
||||
; print metric height
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,height_notice_pre_text
|
||||
mov rdx,height_notice_pre_length
|
||||
syscall
|
||||
|
||||
movq xmm0,r14
|
||||
mov rdi,3
|
||||
call print_float
|
||||
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,height_notice_post_text
|
||||
mov rdx,height_notice_post_length
|
||||
syscall
|
||||
|
||||
; calculate bmi (kg/(m^2))
|
||||
movq xmm1,r14 ; height
|
||||
divss xmm1,[_100f] ; cm to m
|
||||
mulss xmm1,xmm1
|
||||
movq xmm0,r15 ; weight
|
||||
divss xmm0,xmm1
|
||||
movq r15,xmm0 ; bmi
|
||||
|
||||
; write bmi
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,bmi_notice_text
|
||||
mov rdx,bmi_notice_length
|
||||
syscall
|
||||
|
||||
movq xmm0,r15
|
||||
mov rdi,3
|
||||
call print_float
|
||||
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,newline_char
|
||||
mov rdx,1
|
||||
syscall
|
||||
|
||||
call clear_stdin
|
||||
|
||||
; exit
|
||||
xor rdi,rdi
|
||||
mov rax,SYS_exit
|
||||
syscall
|
||||
|
||||
clear_stdin:
|
||||
; 16 - read buff
|
||||
; 4 - pollfd.fd
|
||||
; 2 - pollfd.events
|
||||
; 2 - pollfd.revents
|
||||
sub rsp,24
|
||||
mov DWORD [rsp+16],FD_stdin
|
||||
mov WORD [rsp+20],POLLIN
|
||||
clear_stdin_loop:
|
||||
mov rax,SYS_poll
|
||||
lea rdi,[rsp+16]
|
||||
mov rsi,1
|
||||
xor rdx,rdx
|
||||
syscall
|
||||
|
||||
cmp rax,0
|
||||
jle clear_stdin_end
|
||||
|
||||
mov rax,SYS_read
|
||||
mov rdi,FD_stdin
|
||||
mov rsi,rsp
|
||||
mov rdx,16
|
||||
syscall
|
||||
|
||||
jmp clear_stdin_loop
|
||||
|
||||
clear_stdin_end:
|
||||
add rsp,24
|
||||
ret
|
||||
|
||||
print_float: ; void print_float(float f, int percission)
|
||||
sub rsp,24
|
||||
movss xmm1,[_10f]
|
||||
mov rcx,rdi
|
||||
print_float_scale_loop:
|
||||
mulss xmm0,xmm1
|
||||
loop print_float_scale_loop
|
||||
|
||||
; put digits in memory
|
||||
cvtss2si rax,xmm0
|
||||
mov rcx,23
|
||||
mov rbx,10
|
||||
print_float_reverse_loop:
|
||||
xor rdx,rdx
|
||||
div rbx
|
||||
add rdx,'0'
|
||||
mov [rsp+rcx],dl
|
||||
dec rcx
|
||||
|
||||
cmp rax,0
|
||||
jne print_float_reverse_loop
|
||||
|
||||
push rcx
|
||||
push rdi
|
||||
|
||||
add rcx,17
|
||||
|
||||
; number to write
|
||||
mov rdx,rcx
|
||||
sub rdx,40
|
||||
imul rdx,-1
|
||||
sub rdx,rdi
|
||||
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
lea rsi,[rsp+rcx]
|
||||
syscall
|
||||
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
mov rsi,period_char
|
||||
mov rdx,1
|
||||
syscall
|
||||
|
||||
pop rdi
|
||||
pop rcx
|
||||
|
||||
lea rsi,[rsp+24]
|
||||
sub rsi,rdi
|
||||
mov rdx,rdi
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stdout
|
||||
syscall
|
||||
|
||||
add rsp,24
|
||||
ret
|
||||
|
||||
|
||||
; on error, return 0 in rax. otherwise, return 1 in rax
|
||||
; and the result in xmm0
|
||||
read_float: ; float read_float()
|
||||
push r15 ; read count
|
||||
push r14 ; whole part
|
||||
|
||||
sub rsp,21 ; read buffer
|
||||
xor r15,r15
|
||||
mov r14,-1
|
||||
read_float_loop:
|
||||
cmp r15,20
|
||||
je read_float_size_error
|
||||
|
||||
mov rax,SYS_read
|
||||
mov rdi,FD_stdin
|
||||
lea rsi,[rsp+20]
|
||||
mov rdx,1
|
||||
syscall
|
||||
|
||||
mov dil,[rsp+20]
|
||||
|
||||
cmp r15,0
|
||||
sete ah
|
||||
|
||||
cmp dil,'0'
|
||||
sete al
|
||||
and al,ah
|
||||
jnz read_float_loop
|
||||
|
||||
cmp dil,' '
|
||||
sete al
|
||||
and al,ah
|
||||
jnz read_float_loop
|
||||
|
||||
cmp dil,0xA ; \n
|
||||
je read_float_convert
|
||||
|
||||
cmp dil,'.'
|
||||
je read_float_start_decimal
|
||||
|
||||
call is_number ; dil is preserved
|
||||
cmp rax,0
|
||||
je read_float_num_error
|
||||
|
||||
sub dil,'0'
|
||||
mov [rsp+r15],dil
|
||||
inc r15
|
||||
|
||||
xor rax,rax
|
||||
cmp r14,-1
|
||||
setne al
|
||||
add r14,rax
|
||||
|
||||
jmp read_float_loop
|
||||
|
||||
read_float_start_decimal:
|
||||
cmp r14,-1
|
||||
jne read_float_num_error
|
||||
|
||||
xor r14,r14
|
||||
jmp read_float_loop
|
||||
|
||||
read_float_convert:
|
||||
; zero r14 if it is -1
|
||||
xor rax,rax
|
||||
cmp r14,-1
|
||||
cmove r14,rax
|
||||
|
||||
; invert scale
|
||||
sub r14,r15
|
||||
imul r14,-1
|
||||
|
||||
mov rax,0
|
||||
movq xmm0,rax
|
||||
|
||||
xor rcx,rcx
|
||||
read_float_convert_whole_loop:
|
||||
cmp rcx,r14
|
||||
je read_float_convert_dec_prepare
|
||||
|
||||
mulss xmm0,[_10f]
|
||||
|
||||
xor eax,eax
|
||||
mov al,[rsp+rcx]
|
||||
cvtsi2ss xmm1,eax
|
||||
|
||||
addss xmm0,xmm1
|
||||
|
||||
inc rcx
|
||||
jmp read_float_convert_whole_loop
|
||||
|
||||
read_float_convert_dec_prepare:
|
||||
mov rax,1 ; return value
|
||||
movss xmm7,[_0.1f]
|
||||
movss xmm6,[_10f]
|
||||
read_float_convert_dec_loop:
|
||||
cmp rcx,r15
|
||||
je read_float_end
|
||||
|
||||
xor ebx,ebx
|
||||
mov bl,[rsp+rcx]
|
||||
cvtsi2ss xmm1,ebx
|
||||
|
||||
mulss xmm1,xmm7
|
||||
addss xmm0,xmm1
|
||||
divss xmm7,xmm6
|
||||
|
||||
inc rcx
|
||||
jmp read_float_convert_dec_loop
|
||||
|
||||
read_float_end:
|
||||
add rsp,21
|
||||
pop r14
|
||||
pop r15
|
||||
ret
|
||||
|
||||
read_float_num_error:
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stderr
|
||||
mov rsi,num_error_text
|
||||
mov rdx,num_error_length
|
||||
syscall
|
||||
|
||||
mov rax,0
|
||||
jmp read_float_end
|
||||
|
||||
read_float_size_error:
|
||||
mov rax,SYS_write
|
||||
mov rdi,FD_stderr
|
||||
mov rsi,size_error_text
|
||||
mov rdx,size_error_length
|
||||
syscall
|
||||
|
||||
mov rax,0
|
||||
jmp read_float_end
|
||||
|
||||
; dil is preserved across calls
|
||||
is_number: ; bool is_number(char n)
|
||||
cmp dil,'0'
|
||||
jl is_number_fail
|
||||
|
||||
cmp dil,'9'
|
||||
jg is_number_fail
|
||||
|
||||
mov rax,1
|
||||
ret
|
||||
|
||||
is_number_fail:
|
||||
xor rax,rax
|
||||
ret
|
||||
|
||||
section .data
|
||||
num_error_text: db "Invalid number!",0xA
|
||||
num_error_length: equ $ - num_error_text
|
||||
size_error_text: db "Number too long!",0xA
|
||||
size_error_length: equ $ - size_error_text
|
||||
period_char: db "."
|
||||
newline_char: db 0xA
|
||||
_10f: dd 10.0
|
||||
_0.1f: dd 0.1
|
||||
_100f: dd 100.0
|
||||
|
||||
inch_cm_scale: dd 2.54
|
||||
lb_kg_scale: dd 2.20462
|
||||
|
||||
weight_prompt_text: db "Enter weight (pounds): "
|
||||
weight_prompt_length: equ $ - weight_prompt_text
|
||||
height_prompt_text: db "Enter height (inches): "
|
||||
height_prompt_length: equ $ - height_prompt_text
|
||||
height_notice_pre_text: db "Your metric height: "
|
||||
height_notice_pre_length: equ $ - height_notice_pre_text
|
||||
height_notice_post_text: db "cm",0xA
|
||||
height_notice_post_length: equ $ - height_notice_post_text
|
||||
weight_notice_pre_text: db "Your metric weight: "
|
||||
weight_notice_pre_length: equ $ - weight_notice_pre_text
|
||||
weight_notice_post_text: db "kg",0xA
|
||||
weight_notice_post_length: equ $ - weight_notice_post_text
|
||||
bmi_notice_text: db "Your BMI: "
|
||||
bmi_notice_length: equ $ - bmi_notice_text
|
Reference in New Issue
Block a user