EE 314

advertisement
EE 314
Microprocessor Systems
Spring 2002
Laboratory Project #3
Arithmetic and Subroutines
Overview and Introduction
Review the information in your textbook (pp. 115 - 118) on ASCII and BCD arithmetic.
This lab has two parts. In the first you will work with ASCII and BCD arithmetic. The lab takes a step-bystep logical progression. You will start by modifying a small program that adds unpacked BCD to instead
add packed BCD in the pre-lab. In the lab session you will then write a program that converts ASCII
numbers to packed BCD. This will be followed by a program that adds two packed BCD number of
uniform length. The two programs you do in the lab session 1 will then be turned into sub-routines that are
used by another program.
In the second part, you will adapt the program you wrote to be called from another procedure using a stack
frame to pass parameters. The idea of using a stack frame is a fundamental and very important concept.
It is the mechanism that C and other languages use to pass parameters and provide space for local variables
inside function calls. It is powerful idea that realizes independent, relocatable, generically-usable
subroutines. An additional discussion of stack frames and parameter passing is included in Pre-lab
Part 2. Reading it is not necessary to do part 1.
Arithmetic calculations such as addition and subtraction are fundamental to computer software. When
calculations are performed, numeric data is often translated from ASCII into binary format because the
arithmetic computations are much faster in binary format than in ASCII or BCD. Unfortunately, the
conversions from ASCII to binary and vice versa are fairly complex and require more computation. So
whether you choose binary or ASCII representation depends a lot on the amount of arithmetic needed for
each IO operation. If there is a small amount of IO and a lot of arithmetic, then binary is better. If there is a
lot of IO and only a little arithmetic to do, then ASCII or BCD is better. Some applications, such as
business computations for example, tend to do a lot of reading and writing of numbers, but relatively little
computation. In these cases, it makes sense to do the arithmetic with decimal numbers in BCD or ASCII
format. This project deals with decimal arithmetic and provides more experience in writing programs.
An arithmetic calculation with two arrays containing multi-digit numbers can be written in a subroutine so
that it can be re-used wherever needed. To work with any size array however, the number of digits (or array
elements) must be indicated in some way. Two possible alternatives are: 1) use an end-marker appended
after the last element of the digit-array (as is often done with character arrays in C), and 2) pass the value to
the subroutine as a parameter. When using the first approach, the value represented by the end-marker must
be unique: in other words, it cannot represent any BCD or ASCII number. Alternative 2 removes this
restriction, but requires that an additional parameter be passed to the subroutine.
Objectives
1.
2.
To learn to use the stack for parameter passing.
To practice working with decimal arithmetic in an assembly language program
Note: This lab will take two laboratory sessions to complete.
Pre-Lab Part 1 Decimal arithmetic (due at the beginning of the first lab period)
This is a fairly in-depth and lengthy project, which means you will learn a lot from it. Therefore, it
is recommended that you do it well ahead of time. The best way to answer these questions is to
experiment with the steps using PWB and CodeView.
Part 1.
The 80x86 family instruction set provides several instructions to aid in performing decimal
arithmetic. Among these are AAA (ASCII Adjust AL after Addition) and DAA (Decimal Adjust AL
after Addition). AAA is used when adding ASCII digits or unpacked BCD digits, and DAA is used
for adding packed BCD digits. Both work only with the AL register, so we can add only one-byte
numbers in each step. In both cases, the adjust instruction is used after an ADD or ADC
instruction to convert a 4 or 8 bit hex number to a 4 or 8 bit BCD number (with a possible carry).
When adding unpacked BCD digits or ASCII digits and a number greater than 10 results, the AAA
instruction will add 1 to AH, set the C flag, and clear the upper 4 bits of AL. This allows the
programmer to convert the result back to ASCII by adding 3030H, or leave it in unpacked BCD
form in AX. For adding multi-byte packed BCD numbers, you must take into account the value of
the C flag when adding the digits to the left of the first 2.
Here is an example of a program to add two 3-digit unpacked BCD numbers:
U1
U2
DB
DB
0H, 5H, 2H, 1H
0H, 4H, 8H, 4H
MOV
MOV
AX,CS
DS,AX
MOV
ADD
AAA
MOV
MOV
ADC
AAA
MOV
MOV
ADC
MOV
AAA
MOV
MOV
AL,U1+3
AL,U2+3
;the first 0H is to store the carry
; add U2+3 to U1+3
; this makes ds equal to cs
U1+3,AL
AL,U1+2
AL,U2+2
;add U2+2 to U1+2
U1+2,AL
AL,U1+1
AL,U2+1
AH,0H
;add U2+1 to U1+1
U1+1,AL
U1,AH
;note: use add with carry
;clear AH before adjustment
;set the leftmost digit of U1
Similar techniques can be used for adding multi-byte packed BCD numbers, with a few minor
differences. First, you must use DAA instead of AAA. Second, you can process two digits at a
time. Third, unlike AAA, DAA does not add 1 to AH if there is a carry out of AL. Thus, you must
depend on the C flag to tell you if the last addition produced a carry that must be copied to the
leading digit of the result.
Modify the above program for adding two 3-digit packed BCD numbers such as the following:
P1
DB
00H, 56H, 43H, 21H
P2
DB
00H, 45H, 68H, 54H
Lab Procedure Part 1
In both parts (a) and (b) or Part 1 the results will be verified using CodeView. No output to screen is
necessary. You will demonstrate these programs the second week of lab (The week of Feb. 7 to Feb. 11).
a) Write a program that converts a string of ASCII numbers (no letters allowed) into a packed BCD
number. This program should be able to handle a number of any length. To achieve this use a separate
variable that tells you the length of the ASCII number. An example of how to structure this is given
below in Figure 1:
.286c
CODE
CODE
SEGMENT 'code'
ENDS
STACK SEGMENT STACK
DW
100
STACK
ENDS
DATA
DATA
CODE
DUP(0FFFFH)
SEGMENT 'data'
NUMBER
DB '99918764'
BUFFER
DB 4 dup (0)
LENGTH
DB 8
ENDS
SEGMENT 'code'
ASSUME CS:CODE,DS:DATA,SS:STACK
include macro.inc
A2PBCD PROC NEAR
;(code goes here to convert the ASCII NUMBER
; to packed BCD and store it into BUFFER)
A2BCD ENDP
START:
MOV
MOV
AX,DATA
DS,AX
;Initialize the DS register.
EXIT:
CALL
A2PBCD
MOV
AX,4C00H
;After the program runs,
INT
21H
;return
Figureto1.DOS.
CODE
ENDS
Be sure to test this program with variable length numbers. Using this successfully in part 2 of the lab
END upon
START
procedure relies
being able to use this program with arbitary number. This program should be able to
handle arbitrary length numbers by changing only the length of the NUBMER and BUFFER and the value
in LENGTH.
b) Write a program that takes 2 packed BCD numbers of arbitrary (but uniform) length, adds them, and
writes them back to a buffer. This program will be very much like the program you modified in the
pre-lab. However, like part (a) you need to use a separate variable to tell you the length of the
numbers. Again, this program should be able to handle arbitrary length numbers by only changing the
LENGTH, the size of BUFFER, and the numbers. For example (Figure 2):
.286c
CODE
CODE
SEGMENT 'code'
ENDS
STACK SEGMENT STACK
DW
100
STACK
ENDS
DATA
DATA
CODE
DUP(0FFFFH)
SEGMENT 'data'
PBCDNUM1
DB ,99h,99h,17h,33h
PBCDNUM2
DB 91h,45h,81h,00h
BUFFER
DB 5 dup (0)
LENGTH
DB 4
ENDS
SEGMENT 'code'
ASSUME CS:CODE,DS:DATA,SS:STACK
include macro.inc
ADDBCD PROC NEAR
;(code goes that adds PBCDNUM1 to PBCDNUM2 and writes
;the result back into BUFFER)
ADDBCD ENDP
START:
MOV
MOV
AX,DATA
DS,AX
;Initialize the DS register.
EXIT:
CALL
A2PBCD
MOV
AX,4C00H
;After
the2. program runs,
Figure
INT
21H
;return
to DOS.
A couple of warnings:
CODE
ENDS
 You will have to use conditional logic to determine how many digits to add. However, using CMP
ENDtheSTART
will alter
flags register and thus ADC may not work correctly. You'll have to think carefully
about this problem and come up with a solution (PUSHF may come in handy).
 Notice that the length of BUFFER is 1 greater than the length of either packed BCD number. Why?
Pre-Lab Part 2
In this part of the lab you will learn how to use a stack frame to pass parameters to a procedure call. You
will do this by adapting your programs from part one to be functions called by another program. More on
this in the Lab procedure.
Stack frames are important because they are a generate method for parameter passing. Registers are limited
in number, and simply pushing parameters onto the stack causes problems. This problem is demonstrated
in question 1. You will need to use CodeView to observe the instructions in operation; Plan on spending
some time in the Lab before your lab session.
1) Experiment with the stack and stack pointer with the following steps.
a) Create a program and load the following registers with the following values. AX=0AAAAH,
BX=5555H, CX = 00003h
b) What is the content of SP initially.
c) What is the content of SP and CX after executing each of the following statements?
PUSH AX
PUSH BX
POP CX
d) It may be useful to keep track of the data stored on the stack by using a diagram to represent
memory drawn with SS at the bottom, the initial SP at the top, and the data filled in at each
location as data is pushed and popped to/from the stack. Draw such a diagram for step c.
e) Repeat steps c) and d) for the following sequence of statements (reload the registers with the
values from step a) ):
PUSH CX
CALL proc1
POP CX
Proc1PROC near
POP CX
PUSH AX
RET
Proc1 endp
You will notice that the sequence of instruction probably doesn't behave the way you
think they will. Expect to the value of SP change after the CALL and RET instructions.
You should notice the value of CX is not restored by the POP CX within proc1. You will
also notice that the RET doesn’t go back to the right place. Why? (Recall what happens
during a CALL and RET instruction).
As you can see, the storage of the return address creates a problem when trying to use the stack.
Fortunately, there is a solution. You may recall from lecture that when you use the BP register to access
memory BP uses SS as its base register instead of the default DS register. This tool gives us a very general
procedure to pass parameters to and from PROC calls, while getting around the problem of the return
address being stored in the stack. This procedure is enumerated in Figure 3. See sfexampl.asm to see this
procedure in action.
Steps to using
To Enter a Stack Frame
1) Push args
2) Call proc
3) push bp
4) mov bp,sp
5) sub sp,n
(n an even number: the number of bytes required to hold local variables)
To Exit a Stack Frame
1) mov sp, bp
2) pop bp
3) ret
4) pop/clean-up args
… possibly use returned values (you won't do this in this lab)
All of these concepts are demonstrated in sfexampl.asm. If necessary, build this program and
observe its operation in CodeView.
Lab Procedure Part 2
Change your program from Lab Procedure Part 1 into two separate procedure. You must name these
procedures ASC2PBCD (ASCII to Packed BCD) and ADDPBCD (Add packed BCD). Your
demonstration will consist of supplying a file with the procedures only. This function will then be called
by a driver program by the TA. The driver program will use each of your procedure calls multiple times.
The TA's program will do the followin (several times with several sets of data):
1) Convert 2 equal but arbitrarily long string of ASCII decimal numbers to PBCD
2) Add these 2 packed BCD number (which are of arbitrary length)
The program driver.asm has been provided for you to test your procedures. This file demonstrates the
exact order procedures will be passed onto the stack. You must use the procedures passed on the stack, and
you may NOT use any memory outside the stack frame for your local variables. A demonstration of multifile projects will be given, and the program sfexampl.asm will also be posted to the web as a multifile
project.
Lab report
You will have to write a lab report for this lab summarizing the results of all parts of the lab.
Download