Converting User Chosen Base to Base 10 - MASM

579 views Asked by At

The point of the program is to let the user choose a base (2-16) and then enter in a number or numbers for that base and then display them in bases 2,8,10 and 16. One of the requirements is that when we are getting the number choices under the user chosen base, we are to keep a running total and come up with the decimal value. I think my problem with this program is at that part. In my program it would be "Number" and "Calculating" under the function "ReadInteger". I'm sure I have other issues, but I need to fix this first to continue debugging my program. I've been working at this for a long time and am not sure what I'm doing wrong. It seems like the EAX register isn't clearing properly, but I thought I had that under control? Would appreciate some pointers or even tips on how to debug easier in Visual Studios for MASM when there's user input.

Here is my code so far:

INCLUDE Irvine32.inc


.data
prompt BYTE 'Enter base value (2 thru 16 or 0 to exit):', 0     
prompt1 BYTE 'Enter a number in your chosen base:', 0
error BYTE 'That is not within the accepted range, please try again.', 0
report1 BYTE 'Base 2: ', 0          
report2 BYTE 'Base 8: ', 0
report3 BYTE 'Base 10: ', 0
report4 BYTE 'Base 16: ', 0
Temp DWORD ?
Temp1 DWORD ?
BaseNumber BYTE ?
.code

main PROC
; Main program control procedure.
; Calls: WriteString, ReadInteger, AsciiToDigit,
;        Crlf, DisplayIntegers

Start:
    xor eax,eax                 ;Clear EAX register
    xor ebx,ebx                 ;Clear EBX register
    mov edx,OFFSET prompt       ;Prompt user for base choice
    call WriteString
    mov al,1                    ;Set AL to 1 for ReadInteger Function
    call ReadInteger            ;Get Base choice
    cmp al,'0'                  ;If al is 0 then exit program
    je Finish
    call AsciiToDigit           ;Change character to digit
    mov BaseNumber,al           ;Save the base choice
    call Crlf                   ;New line
    mov edx,OFFSET prompt1      ;Prompt user for number in chosen base
    call WriteString
    mov al,2                    ;Set AL to 2 for ReadInteger Function
    call ReadInteger            ;Get number in chosen base
    cmp al,'0'                  ;If al is 0 then exit program
    je Finish
    call Crlf                   ;New line
    call DisplayIntegers        ;Display results in base 2,8,10 and 16
    call Crlf                   ;New line
    jmp Start                   ;Restart Program

Finish:
    exit                        ;exit to operating system
main ENDP

;-------------------------------------------------------------
ReadInteger PROC
;
; Takes in user's Base choice and Numbers. Validates both and
; calculates decimal value
; Receives: AL value of 1 or 2 
; Returns: Base value in BL and decimal value in Temp1
; Calls: ReadChar,WriteChar,AsciiToDigit,IsLegal,WriteString
;----------------------------------------------------------------
    mov esi,0
    cmp al, 1                   ;If AL is 1 then jump to Base section
    je Base
    cmp al, 2                   ;If AL is 2 then jump to Number section
    je Number
Base:   
    call ReadChar               ;Read input
    cmp al,'0'                  ;Jump to invalid if less than 0
    jl Invalid
    cmp al,'0'                  ;End program if 0 is entered
    je EndFunction
    cmp al,'9'                  ;Jump to invalid if more than 9
    jg Invalid
    cmp al,'1'                  ;Jump to One if 1 is entered
    je One
    call WriteChar              ;Display character entered
    mov bl,al                   ;Save base number in BL register
    jmp EndFunction             ;End the function

One:
    call WriteChar              ;Display the 1
    mov bl,10h                  ;place it in the 10s column
    jmp NextChar

NextChar:
    xor eax,eax                 ;clear eax register
    call ReadChar               ;Read user character entry
    cmp al,'6'                  ;Jump to invalid if entry is bigger than 6
    jg Invalid
    call WriteChar              ;Display entry
    call AsciiToDigit           ;Change from Ascii to digit
    add bl,al                   ;Add to the previous 10h in BL register
    jmp EndFunction             ;End the function

Invalid:
    mov edx,OFFSET error        ;Display Error message
    call WriteString
    mov edx,OFFSET prompt       ;Display prompt to re-enter
    call WriteString
    jmp Base

Number:
    xor eax,eax                 ;Clear eax register
    call ReadChar               ;Read user entry
    cmp al,0Dh                  ;With Enter jump to noneEntered
    je NoneEntered
    mov bl,BaseNumber           ;Get the base number into the bl register
    call IsLegal                ;Check to see if entry is legal with base choice
    cmp al,0                    ;if AL is 0 jump back to number
    je Number
    mov eax, Temp               ;Put the number from Temp into EAX register
    mov Temp1,eax               ;Put the value of EAX into Temp1
Calculating:
    call ReadChar               ;Read user entry
    cmp al,0Dh                  ;With Enter jump to EndFunction
    je EndFunction
    call IsLegal                ;Check to see if entry is legal with base choice
    xor eax,eax                 ;clear eax register
    mov eax, Temp1              ;Put Temp1 value in EAX register
    mul ebx                     ;multiply EAX by EBX register
    add eax, Temp               ;Add temp value to EAX
    mov Temp1, eax              ;Place the new EAX value into Temp1
    jmp Calculating             ;Repeat as long as there is no Enter press


EndFunction:
    ret
NoneEntered:
    mov al,0                    ;AL is 0 if no legal characters are entered
    ret


ReadInteger ENDP

;----------------------------------------------------------------
DisplayIntegers PROC
; Displays Number in base 2,8,10,16 using WriteInteger
; Receives: Nothing
; Returns: Value in BL
; Calls: WriteString,WriteInteger,Crlf
;----------------------------------------------------------------
call Crlf                       ;New line
mov edx,OFFSET report1          ;Display Base 2 value
call WriteString
mov bl,2                        ;Set BL to 2 for WriteInteger Function
call WriteInteger

call Crlf                       ;New line
mov edx,OFFSET report2          ;Display Base 8 value
call WriteString        
mov bl,8                        ;Set BL to 8 for WriteInteger Function
call WriteInteger

call Crlf                       ;New line
mov edx,OFFSET report3          ;Display Base 10 value
call WriteString
mov bl,10                       ;Set BL to 10 for WriteInteger Function
call WriteInteger

call Crlf                       ;New line
mov edx,OFFSET report4          ;Display Base 16 value
call WriteString
mov bl,16                       ;Set BL to 16 for WriteInteger Function
call WriteInteger
call Crlf                       ;New line
ret
DisplayIntegers ENDP

;------------------------------------------------------------------
WriteInteger PROC
; Calculates the value in base 2,8,10,16 and displays
; Receives: BL value of 2,8,10 or 16
; Returns: Nothing 
; Calls: WriteChar
;---------------------------------------------------------------------
mov eax,Temp1                   ;Set EAX register equal to Temp1
mov Temp,eax                    ;Set Temp equal to EAX value
cmp bl,2                        ;If Bl is 2 jump to Convert2
je Convert2
cmp bl,8                        ;If Bl is 8 jump to Convert8
je Convert8 
cmp bl,10                       ;If Bl is 10 jump to Convert10
je Convert10
cmp bl, 16                      ;If Bl is 16 jump to Convert16
je Convert16

Convert2: 
    xor edx,edx                 ;clear out edx register
    xor eax,eax                 ;clear eax register
    mov eax,Temp                ;Set eax register equal to Temp
    mov ecx,2                   ;Divide by ecx - 2
    div ecx
    mov Temp,eax                ;Move new eax value to Temp
    mov eax, edx                ;move edx (remainder) to eax
    add eax,30h                 ;change to Ascii
    call WriteChar              ;Display character
    mov eax,Temp                ;Place Temp value in EAX
    cmp eax,2                   ;If EAX is less than 2 go to next
    jl NextConversion
    jmp Convert2                ;Repeat

Convert8:
    xor edx,edx                 ;Clear edx register
    xor eax,eax                 ;Clear eax register                 
    mov eax,Temp                ;Divide Temp by 8
    mov ecx,8
    div ecx
    mov Temp,eax                ;Store new eax value in Temp
    mov eax, edx                ;Store edx (remainder in eax)
    add eax,30h                 ;Change to Ascii and display
    call WriteChar
    mov eax,Temp                ;If temp is less than 8 jump to next
    cmp eax,8
    jl NextConversion
    jmp Convert8
Convert10:
    mov ecx,SIZEOF Temp         ;Get bit size of temp
    mov esi,0                   ;Set place in string
WriteOut:
    xor eax,eax                 ;Clear eax register
    mov eax,Temp[esi]           ;set eax to first value in string Temp
    add eax,30h                 ;Display character
    call WriteChar
    inc esi                     ;Go to next place in string
    Loop WriteOut
    jmp NextConversion
Convert16:
    xor edx,edx                 ;clear edx register
    xor eax,eax                 ;clear eax register
    mov eax,Temp                ;Divide Temp by 16
    mov ecx,16
    div ecx
    mov Temp,eax                ;Put new eax value in Temp
    mov eax, edx                ;set edx (remainder) to eax
    cmp eax,9                   ;If larger than 9 jump to HexTable
    jg HexTable
    add eax,30h                 ;Otherwise display character
    call WriteChar
    mov eax,Temp                ;If Temp is less than 16 go to Next
    cmp eax,16
    jl NextConversion
    jmp Convert16
HexTable:
    add eax,37h                 ;Find correct character for above 9 values
    call WriteChar
    mov eax,Temp
    cmp eax,16
    jl NextConversion
    jmp Convert16
NextConversion:
ret
WriteInteger ENDP

;-----------------------------------------------------------------
AsciiToDigit PROC
;
; Changes Ascii Character to Digit
; Receives: Ascii Character in the AL register
; Returns: Decimal Value in the AL register
; Calls: None
;------------------------------------------------------------------
cmp al, 60h                 ;if hexidecimal value is greater than 60h jump to lowercase
jg LowerCase
cmp al, 40h                 ;if greater than 40h jump to Upper
jg UpperCase
sub al, 30h                 ;Get digit value
ret

LowerCase:                  ;get lower case value
    sub al,57h
    ret
UpperCase:                  ;get upper case value
    sub al,37h
    ret

AsciiToDigit ENDP

;-------------------------------------------------------------------
DigitToAscii PROC
; Converts Decimal value to Ascii character
; Receives: Decimal AL register value
; Returns: Ascii character value in AL register
; Calls: None
;-------------------------------------------------------------------
cmp al, 9h                  ;if larger than 9h is letter
jg Letter
add al, 30h                 ;change to ascii
ret
Letter:                     ;change to ascii
    add al, 37h
    ret
DigitToAscii ENDP

;------------------------------------------------------------------------------
IsLegal PROC
; Validates for legal values under the specific base
; Receives: Base value in BL register and number in AL register to validate
; Returns: AL register value of 0 for not legal and 1 for legal
; Calls: AsciiToDigit,WriteChar,DigitToAscii
;------------------------------------------------------------------------------
call AsciiToDigit               ;Change to digit
cmp al,bl                       ;Compare digit to base value
je NotLegal                     ;if equal or greater it is not legal
cmp al,bl
jg NotLegal
jmp Legal
NotLegal:                       ;return 0 in AL to symbolize not legal
    mov al,0
    ret
Legal:                          ;Display character and return 1 for legal
    mov Temp,eax                ;save digit in temp
    call DigitToAscii
    call WriteChar
    mov al,1
    ret
IsLegal ENDP

END main
0

There are 0 answers