222 lines
7.5 KiB
NASM
222 lines
7.5 KiB
NASM
;----------------------------------------------------------------------------
|
|
; Author: SL
|
|
;----------------------------------------------------------------------------
|
|
|
|
[GLOBAL mystart] ; export the start address
|
|
|
|
;----------------------------------------------------------------------------
|
|
[SECTION .text]
|
|
;----------------------------------------------------------------------------
|
|
|
|
; code belongs in this section starting here
|
|
|
|
;----------------------------------------------------------------------------
|
|
; MESSAGE is a macro displays a message for prompts.
|
|
; The address of the $ terminated string is passed as the only parameter.
|
|
|
|
%macro MESSAGE 1
|
|
push eax ; macro transparency
|
|
push edx
|
|
|
|
mov ah, 09h ; select write string function
|
|
mov edx, %1 ; load EDX with address of string
|
|
int 0f1h ; call OS interrupt 0F1H
|
|
|
|
pop edx ; restore registers
|
|
pop eax
|
|
%endmacro
|
|
mystart:
|
|
;----------------------------------------------------------------------------
|
|
; MAIN starts here
|
|
|
|
INF:
|
|
MESSAGE msg1 ;callGETBASE for inital base
|
|
call GETBASE
|
|
cmp edi,0 ;check to see if it should quit
|
|
je END
|
|
|
|
MESSAGE msg2 ;enter the number
|
|
call ASCIIBIN
|
|
cmp edi, 0
|
|
je END
|
|
push edi
|
|
|
|
MESSAGE msg3 ;second base
|
|
call GETBASE
|
|
cmp edi, 0
|
|
je END
|
|
|
|
pop edi
|
|
MESSAGE msg5 ;print answer
|
|
mov ebx, OBU ;location of string in outbuffer
|
|
mov eax, edi ;accum in edi mov to eax
|
|
call BINASCII
|
|
call CONOUT
|
|
jmp INF
|
|
END:
|
|
ret
|
|
|
|
|
|
GETBASE: mov ecx, 10 ; BASE 10
|
|
mov edi, 0 ; set accum to 0
|
|
call ASCIIBIN
|
|
cmp edi, 2 ;cmp the upper and lower base limit
|
|
jb END1
|
|
cmp edi, 36
|
|
ja END1
|
|
mov ecx, edi ; move current base into accum
|
|
ret
|
|
|
|
END1: mov ecx, 0
|
|
ret
|
|
|
|
ASCIIBIN:
|
|
mov edi, 0
|
|
mov byte [buffer], 32 ; buffer can hold 32 characters
|
|
mov byte [buffer+1], 0 ; reuse 0 characters from last input
|
|
mov ah, 0ah ; select buffered input function
|
|
mov edx, buffer ; put buffer address in EDX
|
|
int 0f1h ; call OS interrupt 0F1H
|
|
|
|
movzx esi, byte [buffer+1] ;load ECX with number of characters read
|
|
mov ebx, buffer+2 ;load address of input text into EBX
|
|
|
|
looop1: mov al, [ebx] ; load 1 byte from ebx address
|
|
|
|
inner: cmp al, '0'
|
|
jb error2
|
|
cmp al, '9'
|
|
ja error1
|
|
sub al, '0' ; subtract '0'
|
|
jmp OK
|
|
|
|
error1: and al, 0DFh ; else and with DF
|
|
cmp al, 'A'
|
|
jb error2
|
|
cmp al, 'Z'
|
|
ja error2
|
|
sub al,'A'-10 ; sub al"A"-10
|
|
jmp OK
|
|
|
|
error2: MESSAGE msg4
|
|
mov edi, 0 ;zeros out the accumulator
|
|
ret
|
|
|
|
|
|
OK: ;compare digit to base. If >, ERROR.
|
|
movzx eax, al ; zero extend digit
|
|
cmp eax, ecx ; cmp digit to base
|
|
ja error2
|
|
imul edi, ecx ; accum * base
|
|
add edi, eax ; accum + digit
|
|
|
|
next: add ebx, 1 ; increment ebx
|
|
sub esi, 1 ; decraments esi
|
|
cmp esi, 0
|
|
ja looop1 ; loop if it is above 0
|
|
cmp edi, 2147483647 ;checks the upperbound
|
|
ja error2
|
|
cmp edi, 1 ;check lowerbound
|
|
je error2
|
|
cmp edi, -2147483647 ; check lower bound
|
|
je error2
|
|
cmp edi, -1 ;check upperbound
|
|
je error2
|
|
ret
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
; CONOUT transfers byte characters from [EBX] to screen (console).
|
|
; String at [EBX] must be null terminated.
|
|
|
|
CONOUT:
|
|
push eax ; save regs for subroutine transparency
|
|
push edx
|
|
push esi
|
|
|
|
mov esi, ebx ; load ESI with address of buffer
|
|
cld ; clear direction flage for forward scan
|
|
mov ah, 02h ; select write character function
|
|
loop1: lodsb ; get next byte (NB this loop could be
|
|
test al, 0ffh ; test for null more efficiently coded!)
|
|
jz done
|
|
mov dl, al ; copy character into DL for function
|
|
int 0f1h ; call OS interrupt 0F1H
|
|
jmp loop1 ; ending in JMP is inefficient
|
|
done:
|
|
pop esi ; restore registers - transparency
|
|
pop edx
|
|
pop eax
|
|
ret
|
|
|
|
|
|
; BINASCII routine to convert a 2's complement number passed in EAX, base in
|
|
; ECX, into a null-terminated string of ASCII characters stored at [EBX].
|
|
|
|
BINASCII:
|
|
push edx ; transparency
|
|
push edi
|
|
|
|
mov edi, ebx ; put pointer to output string in EDI
|
|
test eax, 0ffffffffh
|
|
jns positive
|
|
mov byte [edi], '-' ; store minus sign in output string
|
|
inc edi
|
|
|
|
neg eax ; will this work OK with 8000000H?
|
|
positive:
|
|
push dword 0 ; push marker, keeping stack dword aligned
|
|
looop:
|
|
mov edx, 0 ; NOTE: HAD TO FIX THIS ONE, CUZ THE STUPID
|
|
; INTEL CHIP INSISTS ON GENERATING A DIVIDE
|
|
; ERROR EXCEPTION IF QUOTIENT TOO BIG!!!
|
|
|
|
div ecx ; divide base into R:Q where EDX will
|
|
; contain the remainder and EAX the
|
|
; dividend then quotient
|
|
cmp edx, 9
|
|
ja letter
|
|
add edx, '0' ; most convenient to do ASCII conversion here
|
|
; add ASCII '0'
|
|
jmp puush ; so we can terminate our popping off stack
|
|
letter:
|
|
add edx, 'A'-10 ; easily: we can have digits of zero which
|
|
; couldn't be distinguished from the marker
|
|
puush:
|
|
push edx ; push the character
|
|
test eax, 0ffffffffh ; if quotient is zero we are done
|
|
jnz looop
|
|
|
|
outloop:
|
|
pop eax ; pop digits
|
|
mov [edi], al ; and store
|
|
inc edi ; the null is also popped and stored
|
|
test al, 0ffh ; test for null
|
|
jnz outloop
|
|
|
|
pop edi ; transparency
|
|
pop edx
|
|
ret
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
[SECTION .data]
|
|
;----------------------------------------------------------------------------
|
|
|
|
; all initialized data variables and constant definitions go here
|
|
|
|
msg1 db 13,10,"Enter a base number or Q to quit: ", 13, 10, "$"
|
|
msg2 db 13,10,"Enter a Number: ", 13, 10, "$"
|
|
msg3 db 13,10,"Enter the desired base: ", 13, 10, "$"
|
|
msg4 db 13,10,"INVALID INPUT", 13, 10, "$"
|
|
msg5 db 13,10,"Your Result is: ", 13, 10, "$"
|
|
|
|
;----------------------------------------------------------------------------
|
|
[SECTION .bss]
|
|
;----------------------------------------------------------------------------
|
|
|
|
; all uninitialized data elements go here
|
|
|
|
buffer resb 34 ; buffer to store input characters
|
|
OBU resb 80 ; buffer to store output char
|