ECEn 425
Lab #2: Debugging with the 8086 Tools
Overview
Complete this lab by yourself. This lab will teach you how to use the tools to debug your programs. You are given a simple program and asked to find out specific information about it.
Instructions
- Download the file lab2.c. This is the program you
will run and use to answer the questions below. You may look at the code, but do NOT modify it.
- Build the executable for lab2.c as explained in the documentation and as demonstrated in the previous lab. Once again you will need clib.s and clib.h to build your program. Use the following file names for the files you generate:
lab2.i - preprocessed C file
lab2.s - compiled file
lab2final.s - concatenation of clib.s and lab2.s
lab2.bin - binary executable
lab2.lst - listing file
Your final assembly file should be composed only of clib.s and lab2.s. Make sure that you use the "-g" flag with C86 when compiling the program and make sure to generate the listing file during assembly by using the "-l" option with NASM.
WARNING: You should use the current version of c86
and NASM (in /ee2/ece425/bin) on the spice machine, or your answers
to the questions below might differ slightly.
- Take a look at lab2.c to get an idea of what it does. Then take a moment to look through the
assembly file (lab2.s) that you generated from lab2.c to get an idea of what the compiler output looks
like. Notice how the "-g" option caused the compiler to
insert the actual C code into the assembly file as comments.
- Now take a moment to look at the listing file for the executable. Notice the
columns and what they are used for. The line number column on
the left refers to the line number of the listing file only, not the line number
of the assembly file. Most of the listing file was generated from clib.s. The portion generated from lab2.s is at the end of the file.
- Load the executable (lab2.bin) into Emu86 using the 'l' command. Once loaded, you can enter 'l' by itself to reload the executable for a second run.
Briefly read through the Emu86 Manual to get an idea of what commands are available.
At a minimum, experiment with the following commands:
- Execute ('e', 'eto')
- Single stepping execution ('o', 's')
- Register commands ('r', 'rd', 'ru')
- Breakpoints ('b', 'c')
- Verbose output mode ('v')
- Disassemble ('d')
- Dump ('dump', 'dumpb', 'dumpw', 'dumpd')
- Register monitors ('f', 'fX', 'g')
- Memory monitors ('n', 'm', 'mX')
- Wipe ('w')
- Help ('h')
- Register info ('regs')
Careful and judicious use of these commands will save you hours of debugging.
You must also be aware of the other commands available to you. Commands such as
manual interrupt assertion ('a'), address lookup ('addr'), manual break (Ctrl+b),
clear ('clear'), history ('hist'), poke ('pb', 'pw', 'pr'), and tick ('t')
can be invaluable in later labs.
Make sure you are aware of the functionality these commands provide.
Use the 'h' command to remind yourself the syntax of the various commands or
refer to the Emu86 Manual for more information.
Helpful Hints and Advice
- Make sure you use a terminal that supports scrolling, since many Emu86 commands can output large amounts of
information. Also, keep in mind that the Emu86 output window can also be scrolled.
- Save yourself time by not quitting and restarting the simulator each time you want to recompile your code.
You can do your compiling and assembling in one terminal window and leave the simulator running in another terminal window.
Simply type 'l' to reload the last file loaded and
reinitialize the simulator.
- Start learning to use the simulator now! The better you are at using Emu86 the more time you will save on
your labs. Don't be one of those students who end up saying,
"If I had only known about that command before I started these labs..."
Questions
Using Emu86, the listing file, and some ingenuity, you should be able
to find the information required to answer all of the following
questions.
When asked for an address, just give the physical address in
hexadecimal (instead of the full logical address with segment and
offset), keeping in mind that the program is loaded at address 0. Use
proper notation('0x---' or '---h') when writing hexadecimal numbers.
- At what address does the function a() begin?
- If you wanted to set a breakpoint for the start of the "return fibonacci(n-1) + fibonacci(n-2);"
line in the fibonacci() function of lab2.c, what address would you use?
- What would you type in Emu86 to create the breakpoint just mentioned?
- What command is used to display the current breakpoints? If a breakpoint had ID number 0, what command
would you enter to delete the breakpoint?
- What is the address of the memory location assigned to global variable k?
- What could you type in Emu86 to view the contents of
k as an integer?
- What command would you type to put a memory watch (a.k.a. monitor) on global variable k that would cause
the simulator to stop executing when k is modified? What command would you type if k were of type char (instead of int)?
- What command is used to list the current memory monitors?
If a memory monitor had ID number 3, what command would you enter to delete the monitor?
- What would you type in Emu86 to store the value 0x113 into global variable k?
- What is the address of the memory location
assigned to local variable i when function a() runs the first
time?
- What is the address of the memory location
assigned to local variable i when function a() runs the second
time?
- What is the address of the memory location
assigned to local variable j when function a() runs the first
time?
- What is the address of the memory location assigned to local variable j when function
a() runs the second
time?
- What command would you type in Emu86 to create a register watch on AX that causes the simulator to
stop when AX becomes the value 0x333?
- What command is used to display the most recently executed and interrupted instructions?
- What value is the stack pointer initialized to?
- Does the stack grow up (increasing memory addresses) or down
(decreasing memory addresses)?
- The stack grows as the depth of recursive calls to the fibonacci()
function increases. Of all memory accesses to stack locations, what
address is accessed that is farthest away from the initial value of
the stack pointer?
- How is the parameter n passed to the fibonacci()
function?
- How are values returned from the fibonacci() function?
- What is the purpose of the "add sp, 2" instruction
that is repeated so often in the assembly code for lab2.c?
- How is the "add sp, 2" instruction encoded in
hexadecimal? How large is this instruction in bytes? Which byte(s)
represent the numerical value 2 that is added?
- What does the "TIMES 2 db 0" statement at the very end of
the assembly file do and what is its purpose?
Pass-off
On or before the due date for this lab, you must submit via Learning Suite
your answers to each of the above questions. Make sure
your response is well organized with each response clearly numbered.
Last updated 26 August 2019
James Archibald jka@ee.byu.edu