Code:
db programsize
jmp codestart
//************** level 0 *******************//
level0: //ecx - start, edx - end
push ecx
push edx
push esi
push ebx
push ebp
push edi
mov edi,0
mov ebx,ecx
mov ebp,0
level0_loop2:
mov esi,expr
add esi,ebx
cmp #esi,43 //'+'
jne l0_l2_next1
push edx
mov edx,ebx
call level1
pop edx
call level0_perform
mov edi,0
inc ebx
mov ecx,ebx
jmp level0_loop2
l0_l2_next1:
cmp #esi,45 //'-'
jne l0_l2_next2
push edx
mov edx,ebx
call level1
pop edx
call level0_perform
mov edi,1
inc ebx
mov ecx,ebx
jmp level0_loop2
l0_l2_next2:
cmp #esi,40
jne l0_l2_next3
call skip_par
l0_l2_next3:
inc ebx
cmp ebx,edx
jge l0_l2_end
jmp level0_loop2
l0_l2_end:
call level1
call level0_perform
level0_end:
mov eax,ebp
pop edi
pop ebp
pop ebx
pop esi
pop edx
pop ecx
ret
level0_perform:
cmp edi,0
jg subtract
add ebp,eax
jmp l0_perform_end
subtract:
sub ebp,eax
l0_perform_end:
ret
//************** level 1 *******************//
level1: //ecx - start, edx - end
push ecx
push edx
push esi
push ebx
push ebp
push edi
mov edi,0
mov ebx,ecx
mov ebp,1
level1_loop2:
mov esi,expr
add esi,ebx
cmp #esi,42 //'*'
jne l1_l2_next1
push edx
mov edx,ebx
call level2
pop edx
call level1_perform
mov edi,0
inc ebx
mov ecx,ebx
jmp level1_loop2
l1_l2_next1:
cmp #esi,47 //'/'
jne l1_l2_next2
push edx
mov edx,ebx
call level2
pop edx
call level1_perform
mov edi,1
inc ebx
mov ecx,ebx
jmp level1_loop2
l1_l2_next2:
cmp #esi,40
jne l1_l2_next3
call skip_par
l1_l2_next3:
inc ebx
cmp ebx,edx
jge l1_l2_end
jmp level1_loop2
l1_l2_end:
call level2
call level1_perform
level1_end:
mov eax,ebp
pop edi
pop ebp
pop ebx
pop esi
pop edx
pop ecx
ret
level1_perform:
cmp edi,0
jg divide
mul ebp,eax
jmp l1_perform_end
divide:
div ebp,eax
l1_perform_end:
ret
//************** level 2 *******************//
level2: //ecx - start, edx - end
push ecx
push edx
push esi
push ebx
push ebp
push edi
mov edi,0
mov ebx,ecx
mov ebp,0
level2_loop2:
mov esi,expr
add esi,ebx
cmp #esi,94 //'^'
jne l2_l2_next1
push edx
mov edx,ebx
call level3
pop edx
call level2_perform
mov edi,1
inc ebx
mov ecx,ebx
jmp level2_loop2
l2_l2_next1:
cmp #esi,40
jne l2_l2_next2
call skip_par
l2_l2_next2:
inc ebx
cmp ebx,edx
jge l2_l2_end
jmp level2_loop2
l2_l2_end:
call level3
call level2_perform
level2_end:
mov eax,ebp
pop edi
pop ebp
pop ebx
pop esi
pop edx
pop ecx
ret
level2_perform:
cmp edi,0
jne l2_perf_next
mov ebp,eax
jmp l2_perf_end
l2_perf_next:
fpwr ebp,eax
l2_perf_end:
ret
//************** level 3 *******************//
level3: //ecx - start, edx - end
push ecx
push edx
push esi
mov eax,0
cmp ecx,edx
je level3_end
mov esi,expr
add esi,ecx
cmp #esi,40 //'('
jne not_parenthesis
push ebx
mov ebx,ecx
call skip_par
mov edx,ebx
pop ebx
inc ecx
call level0
jmp level3_end
not_parenthesis:
mov eax,0
mov #decimal,0
push ebx
mov ebx,ecx
eval_loop:
mov esi,expr
add esi,ebx
cmp #esi,46 //'.'
jne eval_next1
cmp #decimal,0
jg parse_error
inc ebx
mov #decimal,1
jmp eval_loop
eval_next1:
cmp #esi,48
jl parse_error
cmp #esi,57
jg parse_error
mul eax,10 //eax *= 10
add eax,#esi
sub eax,48 //eax += #esi-48
cmp #decimal,0
je eval_next2
inc #decimal
eval_next2:
inc ebx
cmp ebx,edx
jge level3_next2
jmp eval_loop
level3_next2:
pop ebx
cmp #decimal,0
je level3_end
dec #decimal
push ebx
mov ebx,10
fpwr ebx,#decimal
div eax,ebx
pop ebx
level3_end:
pop esi
pop edx
pop ecx
ret
alloc decimal
//******************************************//
alloc n_par
skip_par:
mov #n_par,1
par_loop:
inc ebx
mov esi,expr
add esi,ebx
cmp #esi,40
jne par_loop_next1
inc #n_par
par_loop_next1:
cmp #esi,41
jne par_loop_next2
dec #n_par
par_loop_next2:
cmp #n_par,0
je par_end
cmp ebx,edx
jge parse_error
jmp par_loop
par_end:
ret
//************** in case of error **********//
error_txt:
db 'Syntax error.',10,0
parse_error:
mov esp,#stack
mov eax,9
mov esi,error_txt
int 32
jmp main_loop
//************** variables *****************//
welcome:
db 'Alcyone Calculator v1.0',10,0
query:
db '> ',0
quit:
db 'quit',0
crlf:
db 10,0
expr:
alloc 256
buffer:
alloc 20
alloc stack
//************** code **********************//
codestart:
mov eax,9
mov esi,welcome
int 32
main_loop:
mov eax,9
mov esi,query
int 32
mov eax,8
mov esi,expr
mov ecx,256
int 32
mov eax,24
mov esi,expr
push es
mov es,ds
mov edi,quit
int 32 //strcmp(expr,'quit')
pop es
cmp eax,0
je program_end
mov #stack,esp
mov ecx,0
mov edx,expr
zero_search:
cmp #edx,0
je search_end
inc edx
jmp zero_search
search_end:
sub edx,expr
call level0
mov edx,eax
mov eax,10
mov esi,-3
int 32
mov eax,9
mov esi,crlf
int 32
jmp main_loop
program_end:
retf Note: This program needs latest version of the BIOS, uploaded to GWCD SVN today. Previous version had bugs in displaying real numbers, so for example 1/2 gave 500 instead of 0.500, or 2^0.5 would give 1414 instead of 1.414.
Bookmarks