The Emu86 Simulator

The simulator executes binary programs compiled for the 8086. You can start the simulator by typing "emu86" in a terminal window (after setting up your path). When emu86 starts, a second window should appear with the title "Program Output". This window is used to display all output from your program as it executes in the simulator. The original terminal window will contain the "Emu86>" prompt and is used to enter commands and program input as well as to receive information from the simulator. Important tip: Make sure you run Emu86 in a terminal with the scroll bar enabled.


Quick Command Lookup

  ?
a
addr
b
c
clear
Ctrl+b
d
ds
dump
dumpb
dumpw
dumpd
e
eto
f
fb
fm
g
h
hist
l
lexe
  help
assert
address lookup
breakpoint
clear breakpoint
clear breakpoints & monitors
program break
disassemble
dump stack
dump
dump byte
dump word
dump dword
execute
execute to
reg monitor info
reg minitor (become)
reg monitor (modify)
clear reg monitor
help
inst/int history
load
load exe
m
ma
mb
mm
mr
mw
n
o
pb
pd
pr
pw
q
r
rd
ru
regs
s
simptris
t
v
w
  mem monitor info
mem monitor (access)
mem monitor (become)
mem monitor (modify)
mem monitor (read)
mem monitor (write)
clear mem monitor
step over
poke byte
poke double
poke register
poke word
quit
print regs (hex)
print reg (signed dec)
print reg (unsigned dec)
register info
step
simptris mode
tick
verbose
wipe output window

 

Parameter Formats

Parameters (or arguments) entered with simulator commands can be numbers, addresses, labels, or register names. Only labels are case sensitive.

Numbers:

If a parameter is a number, it can be entered in decimal or hexadecimal. For example you can enter the number 171 in the following ways:

    171     (Decimal)
    ABh     (Hexadecimal)
    0xAB    (Hexadecimal)

Addresses:

If a command parameter is an address, it can be entered as a segment and offset (representing a logical address), as a single number (representing a physical address), or as the symbolic label for the address (see the section on Labels below). The 8086 uses logical addresses for all memory references but physical addresses can be useful since several logical addresses can represent the same physical address (Reminder: the physical address equals (segment << 4) + offset). For example, if you had a global variable, named MyGlobal, at address 12AB:34CD (physical address 89,981 or 15F7Dh), you could enter its address in the following ways:

    12AB:34CD    (Hexadecimal logical address)
    15F7Dh       (Hexadecimal physical address)
    0x15F7D      (Hexadecimal physical address)
    89981        (Decimal physical address)
    MyGlobal     (Symbolic label for the location)
    

Note: if you use the segment and offset notation, it must be entered in hexadecimal.

Labels:

Symbolic labels from the listing file output by NASM can be used in place of numeric address parameters. For example, if you had a global variable named MyGlobal in your C or assembly code, you could simply refer to it by that name rather than entering its address. This also works for function names as well as any other label that appears in the listing file.

In order to use this feature, the listing file must have the same name as the binary file except it must have the ".lst" extension. For example, if you loaded a file "my_program.bin" using the load command, the simulator will automatically attempt to load the symbols from a listing file named "my_program.lst".

Registers:

To identify a register, use the Intel register name (e.g., AX, BX, BP, etc.). Enter 'regs' at the emu86 prompt to see a list of register names and descriptions.

 

Command Descriptions

Below is a comprehensive description of simulator commands. A shorter description can be obtained by entering 'h' in the simulator window. After each command, the allowable parameters are shown. Optional parameters are enclosed in brackets ('[...]'), required parameters are not. To enter a command, simply type the command name at the "Emu86>" prompt followed by the desired parameters. If you do not enter an optional parameter then some default is value assumed.


Getting help:

h, ?   - help
Enter "h" or "?" to display a concise list of commands and descriptions.

regs   - register info
Enter this command to see an explanation of what the different 8086 registers are and what they are typically used for.


Using the simulator:

l [FILE] [ADDR] [ADDR]   - load file
Loads a binary file (like the DOS .COM format) specified by the FILE parameter into the simulator for execution. Normally no parameters are needed other than the filename. Use "l" by itself to reload the last file that was loaded and reset the processor for a second run. By default, files are loaded at address 0000:0000, all segment registers are set to 0, SP is set to FFFEh, and IP is set to 100h. If you do not enter a filename as the FILE parameter, the simulator will reload the last file that was loaded using the same parameters that were used previously. If an address is given as the first ADDR parameter, the file will be loaded at that address. If a second address is given, the segment of the address will be used to initialize the processor's segment registers and its offset will be used to initialize the IP register. For this command, ADDR must be a numeric address, not a label.

lexe FILE   - load exe file
Load a DOS .EXE format file.

q   - quit
Quits the simulator.

w   - wipe output window
Wipes (i.e., clears) the program output window.


Program execution:

Ctrl+B   - program break
This key combination (the 'Ctrl' and 'B' keys pressed simultaneously) can be pressed any time while a program is executing to stop execution of the program at its current location. This is very useful when your program appears to be frozen. You can stop the program and immediately see where it is executing.

e [NUM]   - execute
If no NUM parameter is given, this command executes the program from the current CS:IP to the end of the program. If given, NUM tells the simulator to execute NUM instructions.

eto ADDR   - execute to
This command causes the simulator to execute up the address ADDR, where ADDR is a numeric address or label.

s   - step into
Steps through the next instruction. Use this command to execute a program one instruction at a time.

o   - step over
Steps over the next instruction. This command is very similar to the 's' command. The difference is that it will step "over" call and int instructions. If you do not wish to step through the code of a procedure or software interrupt, use this command to run the entire function in a single step.

v   - verbose toggle
Enter this command to turn verbose mode on and off. When verbose mode is turned on, the instruction count, address, disassembly, and assembly instruction will be displayed. This greatly slows down the execution time but can be useful to see what is being executed.


Displaying simulator state:

r
rd
ru
   - display registers

Entering "r" will print in hexadecimal the CPU's current register values, the register contents of the PIC (programmable interrupt controller), the instruction count (in decimal), and the next instruction to be executed (address, disassembly, and assembly name). Use 'r' for hexadecimal output, 'rd' for signed decimal output and 'ru' for unsigned decimal output.

addr SYMBOL   - display address
Use this command to display the address for a symbolic label. For example, if you hade a global variable named "MyGlobal" (in your C or assembly code) and you wanted to know its address, you could enter the command "addr MyGlobal". The listing file must have been created and automatically loaded with the binary in order for this command to work.

d [ADDR] [NUM]   - disassemble
Use this command to disassemble instructions. With no parameters, this command will display the address, hexadecimal value, and assembly code for several instructions starting at the address CS:IP. If given, ADDR specifies the address or label at which to disassemble. The NUM parameter specifies the number of instructions to disassemble.

ds [NUM]   - dump stack
Use this command to display the values at the top of the stack. It also shows the various BP offsets, making it easy to look at local variables. If given, NUM specifies the number of words to dump from the top of the stack. Otherwise a default number is used.

dump ADDR [NUM]   - dump memory
This command dumps memory to the screen as hexadecimal numbers and as text characters 16 bytes per line. A starting address or label, specified by ADDR, must be given. By default, one row of 16 bytes will be displayed. To display more than 16 bytes, a minimum number of bytes can be specified by NUM. Be aware, however, that ADDR does not necessarily specify the address of the first byte that will be dumped. Instead, ADDR will be used to determine the 16 byte region in which to begin. For example, if you enter "dump 0000:1005", the command will dump from address 0000:1000 to 0000:100F (16 bytes). Use the index numbers displayed at the top of the dump to help you determine exact addresses.

dumpb ADDR [NUM]
dumpw ADDR [NUM]
dumpd ADDR [NUM]
   - dump memory values

These commands dump NUM bytes of memory starting at address or label ADDR. The three versions interpret the memory as bytes, words, and double words, respectively, and each displays the values as a hex, unsigned decimal and signed decimal (and ASCII for dumpb).


Modifying simulator state:

pr REG VAL   - poke register
This command pokes (i.e., places or puts) the value specified by VAL into the register specified by REG.

pb ADDR VAL
pw ADDR VAL
pd ADDR VAL
   - poke memory

These commands poke (i.e., place or put) the value specified by VAL into the memory location at ADDR. Use 'bp' to write a byte value (8 bits), 'pw' to write a word value (16 bits), or 'pdw' to write a doubleword value (32 bits). All values are poked as little endian format values (i.e., the least significant bytes are written at lower memory locations). Note: the size (byte, word, or dword) specifies the number of bytes that will be written at ADDR, not the number of bytes required to fit VAL.

clear   - clear all breakpoints, memory monitors, and register monitors
This command is clears all breakpoints, memory monitors, and register watches. It is equivalent to entering the three commands "c all", "n all", and "g all".


Breakpoint support:

Breakpoints allow you to specify points in the code at which execution of a program should stop. Once stopped, the simulator state can be viewed and execution can be continued or restarted as desired.

b   - view breakpoint info
Entering 'b' displays a list of the current breakpoints with each breakpoint's ID number and address.

b ADDR   - set breakpoint
Entering 'b' followed by an address or label will set a new breakpoint for the instruction located at ADDR. When a breakpoint is created, it is automatically given an ID number. Care must be taken when specifying ADDR since 8086 instructions can be from one to several bytes in length. ADDR must be the address of the first byte of the instruction. If ADDR is not the first byte then the simulator may not know when a breakpoint has been reached.

c ID   - clear breakpoint(s)
This command clears the breakpoint with the given ID number. Enter 'all' as the ID to clear all current breakpoints.


Memory monitors:

Memory monitors can be used like breakpoints to stop execution when regions of memory are accessed by the processor. There are several memory monitor modes that can be used to determine when execution should be stopped. They are:

   modify: Stop when a modification (change) occurs in the memory region.
   read:   Stop when a value is read from the memory region.
   write:  Stop when a value is written in the memory region.
   access: Stop when the region is accessed (i.e., read or written).
   become: Stop when the memory region becomes a certain value.

m   - view memory monitor info
Enter "m" to display a list of the current memory monitors with each monitor's ID number, address, size, and mode.

mX ADDR [SIZE]   - set memory monitor
This command sets a memory monitor for the location specified by ADDR. The X should be first letter of the mode you wish to use (i.e., enter 'mm', 'mr', 'mw', 'ma', or 'mb', for modify, read, write, access, and become). If given, SIZE specifies the size of the region to monitor in bytes. If SIZE is not given then a size of 2 is assumed. Note that if 'become' mode is used then a value must be given. When the monitored region becomes this value, the simulator will stop execution. The syntax for this mode is: mb ADDR VALUE [SIZE]. For this mode, the size must be from 1 to 4 bytes, 2 being the default. When a monitor is created, it is automatically assigned an ID number.

n ID   - clear memory monitor(s)
This command removes the memory monitor with the given ID number. Enter 'all' as the ID to clear all memory monitors.


Register monitors:

Register monitors are just like memory monitors except that registers are monitored. However, for register monitors, only two modes are allowed: modify and become.

f   - view register monitor info
Displays a list of the current register monitors with each monitor's ID number, register, and mode.

fm REG
fb REG VAL
   - set register monitor

These commands set a monitor for the register specified by REG. Use the 'fm' command for modify mode and 'fb' for become mode. When using become mode a value must be given. When the register becomes this value, the simulator will stop execution. When a monitor is created, it is automatically assigned an ID number.

g ID   - clear register monitor(s)
This command clears the register monitor with the given ID number. Enter 'all' as the ID to clear all register monitors.


Interrupt support:

a NUM   - assert
Asserts the interrupt with IRQ specified by NUM. Note: the IRQ is not the same as the interrupt vector number but refers to the pin number on the PIC.

t [NUM]   - tick
This command displays, sets, or disables the timer tick interval. Enter "t" to simply display the current timer tick interval. Add the NUM parameter to set the timer tick interval to NUM instructions. To disable timer ticks, enter "t 0".

hist [NUM]   - instruction/interrupt history
This command displays two lists. The list on the left shows the addresses and labels of the most recently executed instructions. The list on the right shows the addresses and labels of the most recently interrupted instructions (i.e., the value of CS:IP when the interrupt occurred, which corresponds to the next instruction that would have executed had the interrupt not occurred) as well as the IRQ number for the interrupt. The most recent occurrences are listed at the bottom. NUM, if present, specifies the number of entries to display.


Simptris support:

Simptris is a simplified version of Tetris that can be played via the 8086 interrupts. Simptris mode will be used in one of the labs.

simptris   - simptris mode
This command is used to turn Simptris mode on and off. When you type this command, simptris mode will be enabled and the Simptris window should appear. When you type it again the mode will be disabled and the Simptris window should disappear.