Created
April 21, 2016 19:21
-
-
Save nlowe/867768a1e76d82937aa719f96bc89a05 to your computer and use it in GitHub Desktop.
Composite file for the radix project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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