
Lab 3
The
WOOKIE Simulator
Introduction
The Axiom boards have several useful built-in debugging tools that should be
familiar to you by now. You may have noticed, though, that there are some
limitations with these tools. For example, what if your program is complex
enough and you need to set more than 4 (BUFFALO) breakpoints to debug it. Or
what if you need to set a breakpoint within a subroutine, this also is not
allowed by the debug monitors. How then, can you see what is going on in the
machine? In addition to these problems, it can be inconvenient (or impossible)
to look at several different areas of memory during execution to track down an
error in a program. What should you do? Write programs with no subroutines?
Always write perfect code? Not likely! Instead, you can use some new external
tools. Logic analyzers and in-line emulators can be invaluable for these types
of problems, but first there is a simpler way that we will explore during this
lab, the software simulator.
A software simulator is simply a program that runs on a PC. Its task is to act
just like a MC68HC11 micro-controller. The
simulator has the same registers, and memory as the real
MC68HC11, but instead of the debug monitor
(BUFFALO) you get something much better. The simulator allows you to view
simultaneously different areas of memory and all of the registers, all while you
step through program execution. You can see the entire picture. What's more,
there are no limitations concerning the number of breakpoints.
The simulator you will use in the lab is called WOOKIE.
On the lab PCs it can be found in the EE218\WOOKIE
directory. A complete manual is available in the lab for your reference, and a
short manual is included at the end of this lab. The short manual covers
everything you will need for the laboratory exercises, but you are encouraged to
study further. This simulator could be very useful to you from this point
forward in the class. You can debug your programs before the lab, which saves
you time and effort.
While you are getting accustomed to the simulator, you need some programs to
work with. Since you may have been frustrated in the past with BUFFALO's
problems related to the subroutines, let's take this opportunity to watch how
the simulator deals with them.
Each program in
this lab will use subroutines. A subroutine typically needs some input
information to process and return some output information. We refer to this
information as arguments or parameters. Inputs are passed in as parameters and
results are passed back out as parameters. There are several ways to accomplish
this, including:
-
Registers
- simply put the values to pass in the registers .
-
Memory
1ocations - store parameters in certain absolute memory locations.
-
Stack - push the data onto the stack for retrieval on the other end.
You have used the first two methods already in previous labs, so this time you
will use the stack to pass parameters. This is a more general method that does
not have the limitations of the first two. It works as follows: before the
subroutine call, push all the data the subroutine will need onto the stack. If
you want to pass pointers to data, remember that the stack can hold addresses as
well as data. Inside the subroutine, pull the data off of the stack and process
it. When finished, push the ‘answers’ onto the stack and return. The calling
program should retrieve the ‘answers’ from the stack and continue. The challenge
is keeping up with the state of the stack and the order of the
pushes and pulls.
Don't forget that
JSR
and RTS
have their own effect on the stack.
Before the Lab
Read the manual on
the Wookie
simulator. Next, read it again. Take notes. Make SURE you are familiar with and
are prepared to use the following facilities:
-
Loading your code into the
simulator.
-
Displaying/Modifying memory contents.
-
Displaying/Modifying registers contents.
-
Running your program and stepping through it.
-
Skipping and stepping through subroutines.
-
Setting, clearing, and displaying breakpoints.
Write programs to do the
following:
-
A list of
eight numbers (unsigned, 8 bit) is in memory. The ninth number in the list
represents a power of two by which all the rest of the numbers in the list
should be raised. Write a program to multiply each number in the list by two to the
specified power, leaving the results where the inputs were. Keep in mind
that to multiply a binary number by two, you just shift it once to the left.
Use a subroutine to perform the multiplication. Pass parameters in the A
and X registers (A holds power of two and X points to
the number to multiply). Since the results are in the same position as the
inputs, they must be 8 bit. This means we cannot work with very large
numbers, can we? Construct your data set so that overflow is not a problem.
Your subroutine does not have to check for it.
-
Given the same
list of numbers, treat the power of two as a signed number (2's comp.). If
the power is negative, divide by the absolute value of the power of two. In
other words, if the ninth number was $FC, then divide by two to the third
power ($FC=-4, so divide by two, four times). If the power is positive, the
program should behave exactly as the first program.
-
Write a program to calculate the mean of the
numbers generated by the second program.
-
Write a subroutine that will multiply two 8 bit binary numbers.
You CANNOT use the
MUL
assembly instruction.
An algorithm
for this multiply has been thoroughly discussed in class and is covered in
your text. Be sure you understand this algorithm before you use it. Be
prepared to explain your code to the TA. Use the stack to pass parameters to
and from the subroutine. Two single bytes are the input and two bytes (one
16 bit number) are the output. Your main program should push the data, call
the subroutine, and then retrieve the answer from the stack. Meanwhile, the
subroutine should retrieve the input numbers from the stack and push the
answer back before it returns. Note carefully the description of the
JSR
and RTS
instructions and their effect on the stack before you use the stack in a
subroutine. There are some adjustments you must make. To make testing
easier, have your main program read the input numbers from memory and store
the results back in memory after the multiply.
Programming
note: On
the HC11-VDK Axiom board you terminate a program with SWI.
This causes the monitor to jump up and take control. The
BUFFALO
monitor is not in the simulator (unless you load it, remember it's a program
too) so you cannot get to it with an SWI. To
terminate a program without the debug monitor, you should put an endless loop
like the following:
|
... |
... |
(program) |
|
... |
... |
(last line of program |
| SELF |
BRA |
SELF |
* INFINITE LOOP |
If you let the simulator run to completion, it will just 'hang' at this instruction. You should, when using the simulator, put a breakpoint on
SELF to get the same effect as SWI.
A word on testing
- You, the
engineer, are responsible for testing your own program to ensure that it meets
all of the specifications. A single, casual test is usually not sufficient.
Create data sets for testing that will exercise the full range of the program’s
capabilities. If a specification has upper and lower limits, test your program
at those limits. For example, will your ‘find the length of the list’ program
from lab 2 work if the list length is zero? What if it is one? What if it is
256? You must test all cases. For this lab, determine what the limits are for
each program. Create a data set to test the programs to these limits. Predict
the results. Have the data with answers ready before the lab so you can be
productive when you are ready to test.
Materials for lab - Bring the following items with you to lab:
-
A diskette with the above programs typed and ready for assembly.
-
Written program limitations and test data sets with answers.
-
The program from lab one that fills an area of memory (on
disk).
-
A blank diskette to get
your copy of the
AS11 assembler (if needed).
In the Lab
Assemble your programs on the PCs in the lab using the AS11.EXE
(Motorola's freeware assembler). This produces the data needed by the
Wookie simulator. Be sure that you have selected the listing option for the assembler. An example for doing that is
(DOS):
C:\> as11 -lo filename.asm
After assembly, verify that the .s19 and .lst files are
present on disk.
Keep in mind that the simulator only sees these files, not the source code.
Wookie provides the facility of watching target
source code being executed. Wookie displays
source code or disassembled object code. This feature is based on the presence,
or absence respectively, of an AS11 formatted
list file ending with the “lst” extension. If
the “lst” file is present then
Wookie will display source code extracted from
that file, if there is no “lst” file in the
current directory Wookie will display
disassembled code from the “s19” file.
Start the simulator with the program from Lab 1:
C:\>
Wookie
Load the program file, prg1.s19 using the
Wookie GUI. Follow the steps given in the
Wookie manual to execute/simulate the program.
Open the windows for displaying ports, memory, CPU registers and observe the
changes as you trace/step through the program (pressing the walking-man button).
Continue exploring until you understand how to use the simulator.
Load and run your
first program for this lab. Display the memory that holds your list of numbers.
Also display the local storage areas in your subroutine, and the content of the
stack. By the way, where is the stack? Who put it there? Is this where it is on
the Axiom board? Can we move it? How? Single step your program through the first
number raised to a power. What happens to the stack when the
JSR
instruction is executed? What happens on
RTS?
Debug your program (if necessary) and run your test cases. Verify the results.
Load and run the
second program. Set a breakpoint inside the subroutine at the point you decide
between multiplying and dividing. Is everything working right? Run your test
cases and verify the results.
Load and run the third program.
Load and run the fourth program. Record (draw a diagram) of the stack at the following points for one subroutine call:
-
before the parameter push
-
before the subroutine call
-
after the subroutine call
-
after the subroutine pulls the parameters
-
after the subroutine pushes the result
-
before the RTS
-
after the RTS
-
after the main retrieves the result
Record the memory contents and addresses, and the value of the stack pointer at each point.
Run your test data and verify the results.
After the Lab
Produce clean and
well commented listing of the code you used in the lab. Provide a table of the
test data sets and results and describe the rationale behind the testing (i.e.
why did you choose these numbers?). Answer briefly the following questions:
-
What are the benefits of a simulation vs. a
'real' MC68HC11? What are the
disadvantages?
-
Can you compare
BUFFALO and Wookie? Are they
different?
-
Can you use the
PDATA routine from Lab 1 on the simulator? Why or why not?
-
In your C
programming class you learned about pass-by-value vs. pass-by-reference for
subroutine arguments. Which method did you use for program four? What about
program two? Can you use the stack for both methods?
-
How could you
modify programs one and two to deal with the overflow problem? Assume the
word size must remain 8 bits.
-
What are the limitations of the three
different methods of parameter passing? Why would you want to use one over
the other?
-
How is the stack initialized on the Axiom
board? How is it initialized in the simulator? Where is the 'system,' stack
on the simulator?
| EE-218 Homepage |
Syllabus
| Schedule | Lab News | Faculty |
Contact
Information | Lab Info | Project
|
Department of Electrical Engineering and Computer Science
Box 1824 Station B
Nashville, TN 37235
Phone: 322-2771
Fax: 343-6702
|
Search |
Site Index
| People Finder
| Phone
Directory | VUnet |
VUmail | VU
Library | Help
|
Last Updated:
Thursday, February 02, 2006
Turker Keskinpala Copyright © 2003
Vanderbilt University
|