| CS306 | Processing Systems and Structures | Lockwood, Spring 2002 |
| Assigned | Thursday 2/06/2002 |
| Due Date | Thursday 2/14/2002 |
| Purpose | Math, Stack, Subroutines. |
| Points | 50 |
On a stack-based calculator, the equation X+(Y*Z) can be computed by entering the following keystrokes:
| X [enter] Y [enter] Z [enter] * [enter] + [enter] |
For this example, X, Y, and Z were pushed to the stack. When the multiplication command was entered (*); the values Y and Z were POPed from the stack, Y*Z was computed, and this product (YZ) was PUSHed back to the stack. When the addition command was entered (+), X and YZ were POPed from the stack, X+YZ was computed, and this sum was pushed back to the stack. The final result is stored at the top of the stack.
Note that we are also using the stack when we call procedures. A 16-bit Instruction Pointer (IP) is pushed to the stack whenever a NEAR procedure is called.
In decimal mode, negative numbers are displayed in the more traditional format. Negative numbers are preceded by the '-' sign. You may find the BINASC routine in LIB306 useful for displaying numbers in the decimal mode.
Negative numbers will not entered directly. Instead, you may assume that the user will enter a positive number then use the negation command.
Modes can be changed while the calculator is running by entering the commands MB, MD, MH (ModeBin, ModeDecimal, ModeHex). The DispMode variable stores the current mode of the calculator. By default, the calculator should operate in decimal mode.
The value of the DispMode variable and the commands to switch modes are summarized below.
| DispMode | CMD | Description |
|---|---|---|
| 2 | MB | Binary Mode: (0,1): 2's complement |
| 10 | MD | Decimal Mode: (0..9): Negative numbers indicated with '-' |
| 16 | MH | Hex Mode: (0..9..A..F): 2's complement |
Single-operand instruction (such as negation) POPs the first element from the stack (S0), performs the operation, then PUSHes the result back to the stack as S0. Two-operand instructions (such as addition) POPs the first two elements from the stack (S1 and S0), performs the operation, then PUSHes the result back to the stack as S0.
| Cmd | Description |
|---|---|
| + | Addition: S0=S1+S0 |
| - | Subtraction: S0=S1-S0 |
| * | Multiplication: S0=S1*S0 |
| / | Division: S0=S1/S0 |
| % | Modulus (remainder): S0=S1%S0 |
| ! | Factorial: S0=(S0)*(S0-1)*(S0-2) .. (2)(1) |
| N | Negation: S0=-S0 |
| Cmd | Description |
|---|---|
| & | Logical AND: S0=S1&S0 |
| | | Logical OR: S0=S1|S0 |
| ^ | Exclusive OR (XOR): S0=S1^S0 |
| ~ | Logical NOT (Invert bits): S0=~S0 |
This subroutine processes the input in InputBuffer. Input can be numbers, operation commands, or mode commands. Input may include a comments, which is indicated by a semicolon. The routine ignores all spaces (' '), LineFeeds (LF), as well as ALL characters following the ';' (comments). The length of InputString is given by BufLength.
This routine POPs one or two elements from the stack, performs the operation given by the ASCII command in BH and PUSHes the result back to the stack.
This routine is called to format the output of the number at the top of the stack into the 'OutputMessage' string. This string should have the number formatted in the appropriate MODE (as selected by ModeByte).
150 ; First Number [base 10 by default] pushed to stack 50 ; Second Number pushed to stack - ; Calculate: 150-50=100 , Leave Result on stack 8 2 5 * + ; Calculate: (2*5)+8=18 , Leave Result on stack / ; Calculate: 100/18=5 (Integer Arithmetic) N ; Calculate: Negate(5)=-5 12 ; Enter 12 + ; Calculate: -5+12=7 ! ; Calculate: Factorial(7)=7*6*5*4*3*2*1=5040 MH ; Switch to Hex Mode (Enter/Display format): 5040d = 13B0h FFF ; Enter FFF (hex) + ; Calculate: 13B0h+0FFFh=23AFh 2300 ; Enter 2300 (hex) - ; Calculate: 23AFh-2300h=00AFh (hex) MB ; Switch to Binary Mode: 00AFh=0000000010101111b 111111 ; Enter 111111 (binary) & ; Calculate: Logical AND = 0000000000101111 000111 ; Enter 000111 (binary) (note that preceding zeros ignored) ^ ; Calculate: Logical XOR = 0000000000101000 11 ; Enter 11 (binary) | : Calculate: Logical OR = 0000000000101011 ~ ; Calculate: Logical NOT = 1111111111010100 MH ; Switch to Hex Mode: Final Result == FFD4h Q ; Escape to exit |
.___________ CS306 Stack Calculator ____________. | Enter Number -or-| | Operation (+,-,*,/,%,!,N,&,|,^,~) -or-| | Mode (MD=Decimal, MH=Hex, MB=Binary) -or-| | Quit (ESC, Q, or q) | |____________ Lockwood: Spring 2002 ____________| 150 ; First Number [base 10 by default] pushed to stack Result: 150 50 ; Second Number pushed to stack Result: 50 - ; Calculate: 150-50=100 , Leave Result on stack Result: 100 8 Result: 8 2 Result: 2 5 Result: 5 * Result: 10 + ; Calculate: (2*5)+8=18 , Leave Result on stack Result: 18 / ; Calculate: 100/18=5 (Integer Arithmetic) Result: 5 N ; Calculate: Negate(5)=-5 Result: -5 12 ; Enter 12 Result: 12 + ; Calculate: -5+12=7 Result: 7 ! ; Calculate: Factorial(7)=7*6*5*4*3*2*1=5040 Result: 5040 MH ; Switch to Hex Mode (Enter/Display format): 5040d = 13B0h Result: 13B0 FFF ; Enter FFF (hex) Result: 0FFF + ; Calculate: 13B0h+0FFFh=23AFh Result: 23AF 2300 ; Enter 2300 (hex) Result: 2300 - ; Calculate: 23AFh-2300h=00AFh (hex) Result: 00AF MB ; Switch to Binary Mode: 00AFh=0000000010101111b Result: 0000000010101111 111111 ; Enter 111111 (binary) Result: 0000000000111111 & ; Calculate: Logical AND = 0000000000101111 Result: 0000000000101111 000111 ; Enter 000111 (binary) (note that preceding zeros ignored) Result: 0000000000000111 ^ ; Calculate: Logical XOR = 0000000000101000 Result: 0000000000101000 11 ; Enter 11 (binary) Result: 0000000000000011 | ; Calculate: Logical OR = 0000000000101011 Result: 0000000000101011 ~ ; Calculate: Logical NOT = 1111111111010100 Result: 1111111111010100 MH ; Switch to Hex Mode: Final Result == FFD4h Result: FFD4 Q ; Escape to exit LIBMP2 Ver 3.1 Calls: -FormatOutput -ProcessInput -Calculate |
; Stack-based Calculator
; You Name Here : ____________________________________
; CS306: Machine Problem 2
; Spring 2002
; Prof. John W. Lockwood
; Washington University, Department of Computer Science
; Ver. 3.1
;====== Constants ========================================================
CR EQU 13
LF EQU 10
BSKEY EQU 8
ESCKEY EQU 27
SPACE EQU 32
SEMI EQU 59
MAXBUFLENGTH EQU 80 ; Maximum length of an input line
;====== External Functions ===============================================
;-- lib306 Calls --
extern kbdine, dspmsg, binasc, dspout
;-- LibMP2 Calls --
extern LibProcessInput ; This routine is given to you for free!
extern LibCalculate ; Your code will replace the call to this function
extern LibFormatOutput ; Your code will replace the call to this function
extern mp2xit ; Call this to exit the program
;-- Variables used by LibMP2 --
GLOBAL DispMode
GLOBAL InputBuffer
GLOBAL BufLength
GLOBAL OutputBuffer
;====== Stack ============================================================
SEGMENT stkseg STACK ; *** STACK SEGMENT ***
resb 64*8
stacktop:
;====== Begin Code/Data ===================================================
SEGMENT code ; *** CODE SEGMENT ***
;====== Variables =============
DispMode DW 10 ; Operate in decimal mode by default
crlf DB CR,LF,'$' ; New Line
HelpMsg db '.___________ CS306 Stack Calculator ____________.',CR,LF
db '| Enter Number -or-|',CR,LF
db '| Operation (+,-,*,/,%,!,N,&,|,^,~) -or-|',CR,LF
db '| Mode (MD=Decimal, MH=Hex, MB=Binary) -or-|',CR,LF
db '| Quit (ESC, Q, or q) |',CR,LF
db '|____________ Lockwood: Spring 2002 ____________|',CR,LF,CR,LF,'$'
ResultMsg db 'Result: ','$' ; Message displayed on screen before output
OutputBuffer db '................$' ; Contains formatted output
; terminated with '$'
InputBuffer db '........................................'
db '........................................$'
; Contains one line of user input
BufLength dw 0 ; Actual Length of InputBuffer
;====== Your procedures =======
ProcessKey:
; Input:
; Register AL == ASCII code for key that was entered
; (value of register AL must be preserved)
; Output:
; Variable InputBuffer == String containing one line of input
; Input/Output:
; BufLength == Length of InputBuffer
; Purpose:
; Enqueue each character entered from the keyboard
; into a string called 'InputBuffer'.
;
; Note:
; This code is given to you for free as an example
; of how to write function headers, label jumps, and comment your code.
;
MOV DI, [BufLength] ; Load existing string length
CMP AL,BSKEY ; Check if user hit 'Back space' key
JE ProcessBackSpaceKey
CMP DI, MAXBUFLENGTH ; Avoid Buffer Overflow!
JAE ProcessKeyFinished
MOV [InputBuffer+DI],AL ; Append input letter to buffer
INC word [BufLength] ; Proceed to next byte.
ProcessKeyFinished:
RET
ProcessBackSpaceKey:
CMP DI,0 ; If string is not already empty ..
JE ProcessKeyFinished
DEC word [BufLength]
RET ; .. make it 1 byte shorter
; ------------------
Calculate:
; Write Your code here !
RET
; ------------------
FormatOutput:
; Write Your code here !
RET
;====== Main procedure =========
..start:
MOV ax, cs ; Initialize Default Segment register
MOV ds, ax
MOV ax, stkseg ; Initialize Stack Segment register
MOV ss, ax
MOV sp, stacktop ; Initialize Stack Pointer register
MAIN:
MOV DX, HelpMsg ; Print on-line help
CALL dspmsg
MainLoop: ; --- Main body of program ---
MOV word [BufLength], 0
KeyLoop: Call kbdine ; Read keyboard input
Call ProcessKey ; -- Process Keyboard Input ---
CMP AL,ESCKEY
JE Done ; Quit instantly for ESCAPE key
CMP AL,LF
JE KeyDone ; Continue reading until end-of-line
CMP AL,CR
JE KeyDone ; Continue reading until end-of-line
JMP KeyLoop
KeyDone:
MOV DX, crlf ; Skip a line
CALL dspmsg
Call LibProcessInput ; -- Process InputBuffer --
; (This routine is given to you for free)
CMP BH,'Q'
JE Done ; Quit for 'Q' or 'q' command
CMP BH,'q'
JE Done
Call LibCalculate ; -- Perform Math/Logical Calculation --
; (Replace with your 'Call Calculate')
Call LibFormatOutput ; -- Format number at top of stack --
; (Replace with your 'Call FormatOutput')
MOV DX, ResultMsg
Call dspmsg ; Print 'Result: '
MOV DX, OutputBuffer
Call dspmsg ; Print formatted output
MOV dx,crlf
call dspmsg ; Print New line
JMP MainLoop
Done: call mp2xit ; Exit program