Skip to content

Instantly share code, notes, and snippets.

@nlowe
Created April 21, 2016 19:21
Show Gist options
  • Save nlowe/867768a1e76d82937aa719f96bc89a05 to your computer and use it in GitHub Desktop.
Save nlowe/867768a1e76d82937aa719f96bc89a05 to your computer and use it in GitHub Desktop.
Composite file for the radix project
; Nathan Lowe
; EECS 2110 - Computer Architecture and Organization
; Spring 2016 at the University of Toledo
;
; Description: Given an input radix, output radix, and two numbers in the
; specified input radix, perform the following operations:
; A+B
; A-B
; A*B
; A/B if b != 0, otherwise display an error
; A^abs(b)
; ==============================================================================
; | Include libraries and macros |
; ==============================================================================
include pcmac.inc
LOWERCASE_START EQU 'a'
LOWERCASE_END EQU 'z'
ASCII_TO_UPPER_MASK EQU 11011111b ; The bitmask to convert a character to upper
_PickRadix MACRO mem, exit_jmp_loc, err_jmp_loc
LOCAL _PICK_RADIX_NOT_HEX, _PICK_RADIX_DONE
_GetCh
_CharToUpper al
cmp al, 'X'
je exit_jmp_loc
cmp al, 'H'
jne _PICK_RADIX_NOT_HEX
mov mem, 16
jmp _PICK_RADIX_DONE
_PICK_RADIX_NOT_HEX:
cmp al, '1'
jnge err_jmp_loc
cmp al, '9'
jnle err_jmp_loc
sub al, '0'
mov mem, al
_GetCh
cmp al, CR
je _PICK_RADIX_DONE
cmp al, '0'
jnge err_jmp_loc
cmp al, '9'
jnle err_jmp_loc
sub al, '0'
mov bl, al
mov al, mem
mov cl, 10
mul cl
add al, bl
mov mem, al
_PICK_RADIX_DONE:
cmp mem, MAX_RADIX
jg err_jmp_loc
cmp mem, MIN_RADIX
jl err_jmp_loc
nop
ENDM
; Find the index of the first occurrence of c in the string s of length len
; result in dx, -1 if not found
_IndexOf MACRO s, c, len
LOCAL _INDEX_OF_LOOP0, _INDEX_OF_LOOP0_DONE, _INDEX_OF_LOOP0_DONE_NOT_FOUND
cmp len, 0 ; Check to see if we were passed a 0 length string
je _INDEX_OF_LOOP0_DONE_NOT_FOUND
mov bx, -1
_INDEX_OF_LOOP0:
inc bx
cmp bl, len
je _INDEX_OF_LOOP0_DONE_NOT_FOUND
cmp s[bx], c
jne _INDEX_OF_LOOP0
mov dx, bx
jmp _INDEX_OF_LOOP0_DONE
_INDEX_OF_LOOP0_DONE_NOT_FOUND:
mov dx, -1
_INDEX_OF_LOOP0_DONE:
nop
ENDM
_GetRadix MACRO outnum, radix, symbols, symbolLen, err_jmp_loc
LOCAL _GET_RADIX_LOOP0, _GET_RADIX_LOOP0_DONE
LOCAL _GET_RADIX_END, _GET_RADIX_HANDLE_NEG, _GET_RADIX_DONE
xor cx, cx ; The running total is kept in cx
push cx
_GET_RADIX_LOOP0:
_GetCh
cmp al, CR
je _GET_RADIX_LOOP0_DONE
cmp al, '-'
je _GET_RADIX_HANDLE_NEG
_CharToUpper al
_IndexOf symbols, al, symbolLen ; Index in dx
cmp dx, -1
je err_jmp_loc
cmp dl, radix
jge err_jmp_loc
pop bx
or bx, 2
push bx
push dx
mov al, radix
cbw
xchg ax, cx
xor dx, dx
imul cx
pop dx
add ax, dx
mov cx, ax
jmp _GET_RADIX_LOOP0
_GET_RADIX_LOOP0_DONE:
xor dx, dx
pop ax ; Pop the status flags into ax
cmp ax, 2 ; Ensure we got at least one valid character
jnge err_jmp_loc
je _GET_RADIX_DONE
mov ax, -1
imul cx
mov cx, ax
_GET_RADIX_DONE:
mov outnum, cx
jmp _GET_RADIX_END
_GET_RADIX_HANDLE_NEG:
cmp cx, 0 ; The negative symbol must be the first
jne err_jmp_loc ; symbol to appear. If cx isn't zero, treat
pop cx ; it as a bad symbol. Read the flags from
or cx, 1 ; the stack and set the sign flag
push cx
xor cx, cx
jmp _GET_RADIX_LOOP0
_GET_RADIX_END:
nop
ENDM
; We're lazy. Print num in the specified radix using the symbol table
_PutRadix MACRO num, radix, symbols
LOCAL _PUT_RADIX_LOOP0, _PUT_RADIX_LOOP1, _PUT_RADIX_LOOP1_DONE
mov al, radix
cbw
mov cx, num
xchg ax, cx
push '$'
cmp ax, 0
jge _PUT_RADIX_LOOP0
sPutCh '-'
cwd
xor ax, dx
sub ax, dx
_PUT_RADIX_LOOP0:
; radix is in bx
; leftover is in ax
; divide ax by dx. Leftover in ax, remainder (symbol offset) in dx
xor dx, dx
idiv cx
mov bx, dx
mov dl, symbols[bx]
push dx
cmp ax, 0
jne _PUT_RADIX_LOOP0
_PUT_RADIX_LOOP1:
pop ax
cmp al, '$'
je _PUT_RADIX_LOOP1_DONE
_PutCh al
jmp _PUT_RADIX_LOOP1
_PUT_RADIX_LOOP1_DONE:
nop
ENDM
; Compute a to the power x and store the result in res. X must be positive
_Pow MACRO a, x, res
LOCAL _POW_LOOP0, _POW_LOOP0_DONE, _POW_X_0
mov cx, x
jcxz _POW_X_0
mov bx, a
mov res, bx
_POW_LOOP0:
dec cx
jcxz _POW_LOOP0_DONE
xor dx, dx
mov ax, res
imul bx
mov res, ax
jmp _POW_LOOP0
_POW_X_0:
mov res, 1
_POW_LOOP0_DONE:
nop
ENDM
; convert the character in the specified register to uppercase if it is a letter
_CharToUpper MACRO reg
LOCAL _CHAR_TO_UPPER_DONE
cmp reg, LOWERCASE_START
jnge _CHAR_TO_UPPER_DONE
cmp reg, LOWERCASE_END
jnle _CHAR_TO_UPPER_DONE
and reg, ASCII_TO_UPPER_MASK
_CHAR_TO_UPPER_DONE:
nop
ENDM
; ==============================================================================
; | Constants used in this file |
; ==============================================================================
TAB EQU 09 ; Horizontal Tab
CR EQU 13 ; Carriage Return
LF EQU 10 ; Line Feed
EOS EQU '$' ; DOS End of string terminator
MIN_RADIX EQU 2
MAX_RADIX EQU 36
RET_OK EQU 00h ; Return code for OK
; =========================== Start of Setup ============================
.model small ; Small Memory MODEL
.586 ; Pentium Instruction Set
.stack 100h ; Stack area - 256 bytes
; =========================== End of Setup ===========================
; =========================== Start of Data Segment ===========================
.data
radixTable DB '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', EOS
radixTableLength DB 36
; --------------------------- Input Prompt Strings ---------------------------
inputRadixPrompt DB 'Enter input radix (8=Octal, 16,h,H=hex, x to exit)> ', EOS
outputRadixPrompt DB 'Enter output radix (8=Octal, 16,h,H=hex, x to exit)> ', EOS
numberPrompt_A DB 'Enter number A (in radix ', EOS
numberPrompt_B DB 'Enter number B (in radix ', EOS
numberPrompt_Radix DB ')> ', EOS
; ----------------------------------------------------------------------------------
; --------------------------- Output Message ---------------------------
outAdd DB 'A+B=', EOS
outSub DB 'A-B=', EOS
outMul DB 'A*B=', EOS
outDiv DB 'A/B=', EOS
outRemainder DB ' remainder ', EOS
outPow DB 'A^B=', EOS
errBadRadix DB 'Invalid Radix', CR, LF, EOS
errBadSymbol DB 'Invalid Symbol for input radix', CR, LF, EOS
errDivByZero DB 'The second number is 0, cannot divide', CR, LF, EOS
notImplemented DB 'Not Implemented Yet', CR, LF, EOS
blank DB CR, LF, EOS
; ----------------------------------------------------------------------------------
; --------------------------- Variables ---------------------------
inputRadix DB ?
outputRadix DB ?
inputA DW ?
inputB DW ?
mathscratch DW ?
; ------------------------------------------------------------------------------
; =========================== End of Data Segment ===========================
.code
start:
main PROC
_LdSeg ds, @data ; Load the data segment
PROMPT:
_PutStr inputRadixPrompt
_PickRadix inputRadix, EXIT, INVALID_RADIX
_PutStr blank
_PutStr outputRadixPrompt
_PickRadix outputRadix, EXIT, INVALID_RADIX
_PutStr blank
_PutStr numberPrompt_A
mov al, inputRadix
cbw
mov dx, ax
_PutRadix dx, 10, radixTable
_PutStr numberPrompt_Radix
_GetRadix inputA, inputRadix, radixTable, radixTableLength, INVALID_RADIX_SYMBOL
_PutStr numberPrompt_B
mov al, inputRadix
cbw
mov dx, ax
_PutRadix dx, 10, radixTable
_PutStr numberPrompt_Radix
_GetRadix inputB, inputRadix, radixTable, radixTableLength, INVALID_RADIX_SYMBOL
_PutStr outAdd
mov ax, inputA
mov mathscratch, ax
mov bx, inputB
add mathscratch, bx
_PutRadix mathscratch, outputRadix, radixTable
_PutStr blank
_PutStr outSub
mov ax, inputA
mov mathscratch, ax
mov bx, inputB
sub mathscratch, bx
_PutRadix mathscratch, outputRadix, radixTable
_PutStr blank
_PutStr outMul
xor dx, dx
mov ax, inputA
imul inputB
mov mathscratch, ax
_PutRadix mathscratch, outputRadix, radixTable
_PutStr blank
_PutStr outDiv
cmp inputB, 0
jne OUT_DIV
_PutStr errDivByZero
jmp OUT_DIV_DONE
OUT_DIV:
mov ax, inputA
cwd
idiv inputB
push dx
mov mathscratch, ax
_PutRadix mathscratch, outputRadix, radixTable
_PutStr outRemainder
pop dx
mov mathscratch, dx
_PutRadix mathscratch, outputRadix, radixTable
_PutStr blank
OUT_DIV_DONE:
_PutStr outPow
mov ax, inputB
cwd ; Fill dx with the sign bit of ax
xor ax, dx ; And compute the absolute value
sub ax, dx ; of inputB first
_Pow inputA, ax, mathscratch
_PutRadix mathscratch, outputRadix, radixTable
_PutStr blank
jmp PROMPT
INVALID_RADIX:
_PutStr blank
_PutStr errBadRadix
jmp PROMPT
INVALID_RADIX_SYMBOL:
_PutStr blank
_PutStr errBadSymbol
jmp PROMPT
EXIT:
_Exit RET_OK
main ENDP
END main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment