| ECE291 | Computer Engineering II | Lockwood, Spring 1999 |
| Assigned | Thursday 2/11/99 |
| Due Date | Thursday 2/25/99 |
| Purpose | Math, Stack, Subroutines. |
| Points | 50 |
RPN employs a stack to hold numbers and intermediate results. When a number is entered, it is PUSHed to the stack. When an operation is entered, it POPs element(s) from the stack, performs the calculation, and PUSHes the result back to the stack. With RPN, there is no need for parenthese or equal buttons.
Using RPN, 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 LIB291 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. Your routine should ignore all spaces (' '), LineFeeds (LF), as well as ALL characters following the ';' (comments). The length of InputString is given by BufLength.
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).
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.
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 |
============ ECE291 RPN Calculator ============
Enter Number -or-
Operation (+,-,*,/,%,!,N,&,|,^,~) -or-
Mode (MD=Decimal, MH=Hex, MB=Binary) -or-
Quit (ESC, Q, or q)
============ Lockwood: Spring 1999 ============
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 2.1 Calls:
-FormatOutput
-ProcessInput
-Calculate
|
PAGE 75, 132
TITLE MP2 your name current date
COMMENT % RPN Calculator
ECE291: Machine Problem 2
Prof. John W. Lockwood
University of Illinois
Dept. of Electrical & Computer Engineering
Spring 1999
Ver. 2.1
%
;====== Constants ========================================================
CR EQU 13
LF EQU 10
BSKEY EQU 8
ESCKEY EQU 27
SPACE EQU 32
SEMI EQU 59
;====== External Functions ===============================================
;-- Lib291 Calls --
extrn kbdine:near, dspmsg:near, binasc:near, dspout:near
;-- LibMP2 Calls --
extrn LibProcessInput:near ; Your code will replace the call to this function
extrn LibCalculate:near ; Your code will replace the call to this function
extrn LibFormatOutput:near ; Your code will replace the call to this function
extrn mp2xit:near
;====== Stack ============================================================
stkseg segment stack ; *** STACK SEGMENT ***
db 64 dup ('STACK ') ; 64*8 = 512 Bytes of Stack
stkseg ends
;====== Begin Code/Data ===================================================
cseg segment public 'CODE' ; *** CODE SEGMENT ***
assume cs:cseg, ds:cseg, ss:stkseg, es:nothing
;====== Variables =============
DispMode DW 10 ; Operate in decimal mode by default
crlf DB CR,LF,'$' ; New Line
HelpMsg db '============ ECE291 RPN 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 1999 ============',CR,LF,CR,LF,'$'
ResultMsg db 'Result: ','$' ; Message displayed on screen before output
OutputBuffer db 16 dup(?),'$' ; Contains formatted output
; (Should be terminated with '$')
MAXBUFLENGTH EQU 80 ; Maximum length of an input line
InputBuffer db MAXBUFLENGTH dup(?),'$' ; Contains one line of user input
BufLength dw ? ; Actual Length of InputBuffer
PUBLIC DispMode, InputBuffer, BufLength, OutputBuffer ; Needed by LIBMP2
;====== Your procedures =======
ProcessKey PROC NEAR
; 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 BufLength ; Proceed to next byte.
ProcessKeyFinished:
RET
ProcessBackSpaceKey:
CMP DI,0 ; If string is not already empty ..
JE ProcessKeyFinished
DEC BufLength
RET ; .. make it 1 byte shorter
ProcessKey ENDP
; ------------------
ProcessInput PROC Near
; Write Your code here !
RET
ProcessInput ENDP
; ------------------
FormatOutput PROC Near
; Write Your code here !
RET
FormatOutput ENDP
; ------------------
Calculate PROC Near
; Write Your code here !
RET
Calculate ENDP
;====== Main procedure =========
main proc far
mov ax, cseg ; Initialize DS register
mov ds, ax
MOV DX, offset HelpMsg ; Print on-line help
CALL DSPMSG
MainLoop: ; --- Main body of program ---
MOV 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,13
JNE KeyLoop ; Continue reading until end-of-line
MOV DX, offset crlf ; Skip a line
CALL DSPMSG
Call LibProcessInput ; -- Process InputBuffer --
; (Replace with your 'Call ProcessInput')
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, Offset ResultMsg
Call DSPMSG ; Print 'Result: '
MOV DX, Offset OutputBuffer
Call DSPMSG ; Print formatted output
MOV dx,offset crlf
call DSPMSG ; Print New line
JMP MainLoop
Done: call mp2xit ; Exit program
main endp
cseg ends
end main