Top-Down Design Using Subroutines

advertisement
3D1-Microprocessor Systems 1
Lecture 17: Top-Down Design Using Subroutines
A common mechanism for the re-use of a block of instructions is to incorporate it into a
subroutine. The subroutine is given a name and is supplied with the input parameters of
the problem and returns the results as output parameters. Thus if the solution of a problem
has been neatly encapsulated into a subroutine which has been comprehensively tested and
debugged then it can be incorporated into subsequent programs. This obviously saves much
work and removes some sources of error.
In this lecture, we will apply a top-down approach to develop a program that reads and
evaluates simple expressions involving unsigned word integers and the usual arithmetic
operators (+, -, * and /).
Learning Outcomes:
On completion of this lecture, you will be able to:
 Discuss the advantages of the top-down approach;
 Decompose complex problems into small modular subroutines.
17.1 The top-down approach
When solving large problems it is usually necessary to split the problem down into a series
of sub-problems, which in turn may be split into further sub-problems etc. This is usually
called a top-down approach. This process continues until problems become of such a size
that they can be solved by a single programmer. This top-down approach is essential if the
work has to be shared out between a team of programmers, each programmer ending up
with a specification for a part of the system which is to be written as a subroutine (or
subroutines). While writing a single subroutine the programmer is able to concentrate on
the solution of this one problem only and is thus more likely to be able to solve the problem
and make fewer errors. This subroutine can then be tested on its own for correctness.
17.2
Example
Write a subroutine to read and evaluate simple expressions involving unsigned word
integers and the usual arithmetic operators (+, -, * and /). The expressions are stored as
NUL-terminated ASCII character sequences of the form:
[integer][space] [operator][space] [integer] [end]
Where [space] is a single ASCII space character (ASCII code: 0100000).
For example:
651 * 70
A solution could be presented as follows:
Get first number
Skip space character
Get operator
Skip space character
Get second number
Compute operation
Save result
Then each task can be broken down into smaller tasks:
17-1
3D1-Microprocessor Systems 1
Get Number:
Push the address of the ASCII code string of digits into the stack
Push the address where to save the binary number on stack
Repeat
Test if character is a digit
If Yes then do convertion
Else goto exit
Exit save binary number in the address loaded on the stack
Save address of character pointer on the stack
Skip space:
increment the character pointer
Get Operator:
Save the contents of memory pointed at by the character pointer in a Dn
Increment the character pointer
Compute operation:
If operator = ‘+’ Then add
Else if operator = ‘-’ Then subtract
Else if operator = ‘*’ Then multiply
Else if operator = ‘/’ then divide
End if
End if
End if
End if
17.3
Program implementation in 68000 Assembly Language:
op1
op2
RSLT
ORG
DS.W
DS.W
DS.L
$2000
1
1
1
origin of
reserve 1
reserve 1
reserve 1
num
ORG
DC.B
$2100
'671 * 70',$0
origin of input data
define the expression to evaluate
ORG
PEA
PEA
BSR
LEA
MOVE.L
MOVE.B
ADDA.L
MOVE.L
PEA
BSR
MOVE.W
MOVE.W
BSR
$4000
num
op1
origin of main program
push the reference to num into the stack
push the reference to op1 into the stack
GetNum
get the 1st number
4(A7),A7
(A7),A0
(A0),D5
#2,A0
A0,(A7)
op2
clean up the stack by removing op1
load top of stack into A0
save operator in D5
skip space character
load character pointer to the stack
push the reference to op1 into the stack
GetNum
get the 2nd number
op1,D2
op2,D3
action
copy 1st operand in D2
copy 2nd operand in D3
compute operation and save result in RSLT
TRAP
#0
return control of the CPU to Monitor
main
return data
word for 1st operand
word for 2nd operand
longword for operation result
17-2
3D1-Microprocessor Systems 1
ORG
GetNum MOVEM.L
MOVEQ
LEA
MOVE.L
MOVEQ
CMP.B
BNE
MOVEQ
ADDA.L
loop
exit
$3000
D0-D2/A0-A2,-(A7)
#0,D0
(A7),A1
32(A1),A0
#1,D2
#'-',(A0)
loop
#-1,D2
#1,A0
(A0)+,D1
#$30,D1
exit
#$3A,D1
exit
#$30,D1
#10,D0
D1,D0
loop
D2,D0
28(A1),A2
(A2),A2
D0,(A2)
A0,32(A1)
(A7)+,D0-D2/A0-A2
copy ascii char in D1
*
*
*if char not a digit then exit
*
else subtract $30 from ascii code
[D0] -> [D0]*10
add [D1] and [D0]
goto loop
[D0] -> [D0]*[±1]
Get pointer to address of operand
Get actual address of operand
save operand in memory
save pointer in stack
Restore working registers
return to caller
ORG
$3200
D2/D3/D5,-(A7)
#'+',D5
compute the operation
CMP.B
BEQ
CMP.B
BEQ
CMP.B
BEQ
CMP.B
BEQ
BRA
Plus
#'-',D5
Minus
#'*',D5
Mult
#'/',D5
Div
return
ADD.L
BRA
D2,D3
Minus SUB.L
D2,D3
Mult
Div
copy addr top of stack in A1 (local stack pointer)
*
*
*check for minus sign before number
*
*
*
MOVE.B
CMP.B
BMI
CMP.B
BPL
SUB.B
MULU
ADD.L
BRA
MULS
LEA
MOVEA.L
MOVE.W
MOVE.L
MOVEM.L
RTS
action MOVEM.L
Plus
convert sting of ascii digits into binary
save working registers on the stack
clear D0
return
BRA
return
MULU
BRA
D2,D3
DIVU
AND.L
D2,D3
#$0000FFFF,D3
return MOVE.L
MOVEM.L
RTS
return
mask remainder
D3,RSLT
(A7)+,D2/D3/D5
END
17-3
3D1-Microprocessor Systems 1
17.4
Conclusion
The top-down approach to program design splits the initial problem into several subproblems which in turn can be further sub-divided. Once a sub-problem is simple enough to
be solved then it can be implemented as a subroutine.
A subroutine should be completely self-contained. That is it should communicate with the
calling program only via supplied input parameters and output parameters.
REFERENCES

Clements; A Four-function Calculator, In: 68000 Family Assembly Language; pp.255264; PWS Publishing Company; 1994.

Dr. Mike Brady, Microprocessor Systems 1, dept of Computer Science, Trinity College
Dublin: http://www.tcd.ie/Engineering/Courses/BAI/JS_Subjects/3D1/.

Look on the Web at http://www.mee.tcd.ie/~assambc/3D1.
17-4
Download