| ECE291 | Computer Engineering II | Lockwood, Fall 1996 |
| Assigned | Tuesday 10/1/96 |
| Due Date | Friday 10/11/96 |
| 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 ModeDisp variable stores the current mode of the calculator. By default, the calculator should operate in decimal mode.
The value of the ModeDisp variable and the commands to switch modes are summarized below.
| ModeDisp | 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 reads the input from the keyboard. You may use the KBDINE routine from LIB291 to read in the ASCII characters. Input can be numbers, operation commands, or mode commands. Input may include a comments, which is indicated by a semicolon. Your program should ignore all spaces (' '), LineFeeds (LF), as well as ALL characters following the ';' (comments).
This routine is called to print the value at the top of the stack in the appropriate MODE (as selected by ModeByte). You may use the BINASC and DSPMSG routines from LIB291. You will need to write your own code to display binary or hex values.
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. You will need to manipulate the stack in order to retrive and push elements without affecting the IP that was pushed when the subroutine was called
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 |
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: Locical 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 DOSXIT: Exit to DOS |
PAGE 75, 132
TITLE MP2 your name current date
CR EQU 13
LF EQU 10
ESCKEY EQU 27
SPACE EQU 32
SEMI EQU 59
extrn dosxit:near, kbdine:near, dspmsg:near, binasc:near
extrn ReadInput:near ; Remove this line to add your own procedure
extrn Calculate:near ; Remove this line to add your own procedure
extrn DispOutput:near ; Remove this line to add your own procedure
;====== SECTION 3: Define stack segment ===================================
stkseg segment stack ; *** STACK SEGMENT ***
db 64 dup ('STACK ') ; 64*8 = 512 Bytes of Stack
stkseg ends
;====== SECTION 4: Define code segment ====================================
cseg segment public ; *** CODE SEGMENT ***
assume cs:cseg, ds:cseg, ss:stkseg, es:nothing
;====== SECTION 5: Declare variables ======================================
DispMode DW 10 ; Operate in decimal mode by default
crlf DB CR,LF,'$' ; New Line
;====== SECTION 6: Main procedure =========================================
main proc far
mov ax, cseg ; Initialize DS register
mov ds, ax
MOV DI, offset DispMode
Calc: Call ReadInput ; Read Input from Keyboard
MOV DX,offset crlf
call dspmsg ; New Line
CMP BH, ESCKEY ; Quit When ESC is entered
JE Done
CMP BH, 'Q' ; Also quit if Q is entered
JE Done
Call Calculate ; Perform Math/Logical Calculation
Call DispOutput ; Display number at top of stack
JMP Calc
Done: call dosxit ; Exit to DOS
main endp
cseg ends
end main