EMU8086 Solutions
EMU8086 Solutions
To make sure you are using the latest version, choose check for an update from the
help menu.
Windows Vista and Windows 7 users should enable Windows XP compatibly mode.
Windows XP compatibly mode should also be applied to all virtual hardware devices. To
further minimize incompatibly problems, it's recommended to run both the emulator and
any virtual devices as system administrator.
(these files are used to communicate with virtual devices and for emulating hardware
interrupts)
To step forward press F8 key, to run forward press F9 or press and hold F8. To step
backward press F6 key, to run backward press and hold F6. The maximum number of
steps-back can be set in emu8086.ini. For example:
or
Question:
org 100h
mov si, 0
mov ax, myArray[si]
ret
Solution:
org 100h
jmp code
ret
For the computer all bytes look the same, it cannot determine if it's an instruction or a
variable. Here is an example of MOV AL, 5 instruction that can be coded with simple
variable declarations:
org 100h
byte1 db 176
byte2 db 5
ret
When you run this program in emulator you can see that bytes 176 and 5 are actually
assembled into:
MOV AL, 5
This is very typical for Von Neumann Architecture to keep data and instructions in the
same memory, It's even possible to write complete program by using only DB (define
byte) directive.
org 100h
db 235 ; jump...
db 6 ; 6 - six bytes forward (need to skip characters)
db 72 ; ascii code of 'H'
db 101 ; ascii code of 'e'
db 108 ; ascii code of 'l'
db 108 ; ascii code of 'l'
db 111 ; ascii code of 'o'
db 36 ; ascii code of '$' - DOS function prints untill dollar.
db 186 ; mov DX, .... - DX is word = two bytes
db 2 ; 02 - little end
db 1 ; 01 - big end
db 180 ; mov AH, ....
db 9 ; 09
db 205 ; int ...
db 33 ; 21h - 33 is 21h (hexadecimal)
db 195 ; ret - stop the program.
8086 and all other Intel's microprocessors store the least significant byte at a lower
address. 102h is the address of 'H' character = org 100h + 2 bytes (jmp instruction).
The above assembly code produces identical machine code to this little program:
org 100h
jmp code
msg db 'Hello$'
ret
If you open the produced ".com" file in any hex editor you can see hexadecimal values,
every byte takes two hexadecimal digits, for example 235 = EB, etc... memory window
of the emulator shows both hexadecimal and decimal values.
Problem:
Solution:
The latest version of the emulator uses Terminal font by default and it is MSDOS/ASCII
compatible.It is also possible to set the screen font to Fixedsys from the options. For
other controls the font can be changed from c:\emu8086\emu8086.ini configuration file.
It is well known that on some localized versions of Windows XP the Terminal font may be
shown significantly smaller than in original English version. The latest version
automatically changes default font to 12 unless it is set in emu8086.ini:
FIX_SMALL_FONTS=false. The Fixedsys font is reported to be shown equally on all
systems. It is reported that for small Terminal font D and 0 (zero) look very alike.
Starting from version 4.00-Beta-8 the integrated assembler of emu8086 can be used
from command line. The switch is /a followed by a full path to assembly source code
files. The assembler will assemble all files that are in source folder into MyBuild
directory.
For example:
emu8086 /a c:\emu8086\examples
Do not run several instances of the assembler under the same path until <END> appears
in the file. You may see if emu8086 is running by pressing the Ctrl+Alt+Del combination,
or by just opening and reopening _emu8086_log.txt file in Notepad to see if the file is
written completely. This can be checked automatically by another program (the file must
be opened in shared mode).
The assembler does not save files with extensions .com, .exe, or .bin, instead it uses
these extensions: .com_, .exe_, or .bin_ (there is underline in the end). If you'd like to
run the file for real just rename .com_ to .com etc.
Theoretically it's possible to make a high level compiler that will use emu8086 as an
assembler to generate the byte code. Maybe even C or C++ compiler. The example of a
basic compiler program written in pure 8086 code may be available in the future.
To disable little status window in the lower right corner, set SILENT_ASSEMBLER=true
in emu8086.ini
For the emulator physical drive A: is this file c:\emu8086\FLOPPY_0 (for BIOS
interrupts: INT 13h and boot).
Question:
Solution:
There are two general solutions to this task, small and big.
; it is a much shorter solution, because procedures are hidden inside the include file.
include "emu8086.inc"
ORG 100h
MOV AX, 27
MOV BX, 77
ADD AX, BX
CALL PRINT_NUM
ret
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS
end
For more information about macro definitions check out tutorial 5.
Question:
How to calculate the number of elements in array?
jmp start:
array db 17,15,31,16,1,123, 71
start:
MOV AX, array_byte_size
$ is the location counter, it is used by the assembler to calculate locations of labels and
variables.
note: this solution may not work in older versions of emu8086 integrated assembler, you
can download an update here. the result is always in bytes. If you declare an array of
words you need to divide the result by two, for example:
jmp start:
array dw 12,23,31,15,19,431,17
start:
MOV AX, array_byte_size / 2
Question:
Solution:
Question:
Is there another way to achieve the same result without using DD variables?
Solution:
DD definitions and far jumps are supported in the latest version, for example:
addr dd 1235:5124h
If you are using earlier version of emu8086 you can use a workaround, because double
words are really two 16 bit words, and words are really two bytes or 8 bits, it's possible
to code without using any other variables but bytes. In other words, you can define two
DW values to make a DD.
For example:
ddvar dw 0
dw 0
Long jumps are supported in the latest version (call far). For previous versions of
emu8086 there is another workaround:
jmp 1234h:4567h
and it is assembled into byte sequence:
EA 67 45 34 12
It can be seen in memory window and in emulator -> debug.
Therefore, you can define in your code something similar to this code:
The above code is assembled into the same machine code, but allows you to modify the
jump values easily and even replace them if required, for exampe:
this is just a tiny example of self-modifying code, it's possible to do anything even
without using DD (define double word) and segment overrides, in fact it is possible to
use DB (define byte) only, because DW (define word) is just two DBs. it is important to
remember that Intel architecture requires the little end of the number to be stored at the
lower address, for example the value 1234h is combined of two bytes and it is stored in
the memory as 3412.
org 100h
mov ax, 0
mov es, ax
rr:
mov ax, 1 ; return here
ret
end
Question:
It would be very useful to have the option of invoking a DOS shell at the build directory
from the compile finished dialogue.
Solution:
The latest version of emu8086 has external button that allows to launch command
prompt or debug.exe with preloaded executable and it also allows to run executables in
real environment.
for previous versions of emu8086 you can download Microsoft utility called command
prompt here, after the compilation click browse..., to open C:\emu8086\MyBuild
folder in file manager, then right-click this folder and select "open command prompt
here" from the pop-up menu.
Question:
Is it possible to set a break point?
Answer:
Yes, it's possible to click the instruction line and click Set break point from Debug
menu of the emulator.
It is also possible to keep a log similar to debug program, if you click View -> Keep
Debug Log.
The break point is set to currently selected address (segment:offset).
The emulator will stop running when the physical address of CS:IP registers is equivalent
to break point address (note: several effective address may represent the same physical
address, for example 0700:114A = 0714:000A)
Another way to set a break point is to click debug -> stop on condition and set value
of IP register. The easiest way to get IP values is from the listing under LOC column. To
get listing click debug -> listing
In addition it's possible to the emulator to stop on codition AX = 1234h and to put the
follwoing lines in several places of your code:
MOV AX, 1234h
MOV AX, 0
Question:
I am aware that 8086 is limited to 32,767 for positive and to -32,768 for negative. I am
aware that this is the 16-bit processor, that was used in earlier computer systems, but
even in 8-bit Atari 2600 score counts in many games went into the 100,000s, way
beyond 32,000.
Solution:
Here is the example that calculates and displays the sum of two 100-bit values (30
digits).
32 bits can store values up to: 4,294,967,296 because 2^32 = 4294967296 (this is
only 10 decimal digits).
100 bits can hold up to 31 decimal digits because 2^100 =
1267650600228229401496703205376
(31 decimal digits = 100 binary digits = 100 bits)
; this example shows how to add huge unpacked BCD numbers (BCD is binary coded decimal).
; this allows to over come the 16 bit and even 32 bit limitation.
; because 32 digit decimal value holds over 100 bits!
; the number of digits in num1 and num2 can be easily increased.
ORG 100h
; skip data:
JMP code
; 423454612361234512344535179521 + 712378847771981123513137882498 =
; = 1135833460133215635857673062019
; you may check the result on paper, or click Start , then Run, then type "calc".
; digit pointer:
XOR BX, BX
next_digit:
; add digits:
MOV AL, num1[BX]
ADC AL, num2[BX]
; store result:
MOV sum[BX], AL
LOOP next_digit
print_d:
MOV AL, sum[BX]
; convert to ASCII char:
OR AL, 30h
INC BX
LOOP print_d
RET
END
With some more diligence it's possible to make a program that inputs 200 digit values
and prints out their sum.
Question:
I'm making an interrupt counter; for that I am using 1 phototransister and sdk-86 board
at college. I am not having this kit at home so I have a problem to see the output.
here is issue.: when light on phototransister is on and off pulse is generated, this pulse
comes just like the harwared iterrupt. my program must to count these pulses
continuously; for that I am using 8255kit and SDK-86kit at college, but at home I don't
have this equempent at home. Am I able to emulate the output of real system?
Perchanps, I have to develope 8255 device as an externel device in emu8086; but how
can I prog this device in vb? I am using ports: 30h, 31h, 32h, and 33h. I dont know vb...
Answer:
You don't have to know vb, but you have to know any real programming language apart
from html/javascript. the programming language must allow the programmer to have
complete control over the file input/output operations, then you can just open the file
c:\emu8086.io in shared mode and read values from it like from a real i/o port. byte at
offset 30h corresponds to port 30h, word at offset 33h corresponds to port 33h. the
operating system automatically caches files that are accessed frequently, this makes the
interaction between the emulator and a virtual device just a little bit slower than direct
memory-to-memory to communication. in fact, you can create 8255 device in 16 bit or
even in 32 bit assembly language.
idle:
nop
jmp idle
Question:
Answer:
it's possible to use emu8086 integrated calculator to make these calculations (set show
result to hex).
note: 10h = 16
Question:
I would like to print out the assembly language program as well as the corresponding
machine language code. How can I do so ?
Solution:
It is not possible to print out the source code directly from emu8086, but you may click
file -> export to HTML... and print it from the browser or even upload it to the server
preserving true code colors and allowing others just to copy & paste it.
The corresponding machine code can be opened and then printed out by clicking view -
> listing right after the successful assembling/compilation or from the emulator's menu.
Question:
Answer:
It is possible to overwrite the default stub address for int 03h in interrupt vector table
with a custom function. And it is possible to insert CC byte to substitute the first byte of
any instruction, however the easiest way to set a break point is to click an instruction
and then click debug -> set break point from the menu.
Editor hints:
Question:
It is good that emu8086 supports virtual devices for emulating the io commands. But
how does the IO work for real? (Or: How do I get the Address of a device e.g. the serial
port)
Answer:
It is practically the same. The device conrolling is very simple. You may try searching for
"PC PhD: Inside PC Interfacing". The only problem is the price. It's good if you can
afford to buy real devices or a CPU workbench and experiment with the real things.
However, for academic and educational purpoces, the emulator is much cheaper and
easier to use, plus you cannot nor burn nor shortcut it. Using emu8086 technology
anyone can make free additional hardware devices. Free hardware easy - in any
programming language.
Question:
How do I set the output screen to 40*25, so I dont have to resize it everytime it runs.
Answer:
mov ax, 0
int 10h
It's possible to change the colours by clicking the "options" button. The latest version
uses yellow color to select lines of bytes when the instruction in disassembled list is
clicked, it shows exactly how many bytes the instruction takes. The yellow background is
no longer recommended to avoid the confusion.
Instead of showing the offset the emulator shows the physical address now. You can
easily calculate the offset even without the calculator, because the loading segment is
always 0700 (unless it's a custom .bin file), so if physical address is 07100 then the
offset is 100 and the segment is 700.
The file system emulation is still undergoing heavy checks, there are a few new but
undocumented interrupts. INT 21h/4Eh and INT 21h/4Fh. These should allow to get the
directory file list.
Question:
What is org 100h ?
Answer:
First of all, it's a directive which instructs the assembler to build a simple .com file.
unlike instructions, this directive is not converted into any machine code. com files are
compatible with DOS and they can run in Windows command prompt, and it's the most
tiny executable format that is available.
Literally this directive sets the location counter to 256 (100h). Location counter is
represented in source code as dollar. This is an example of how location counter value
can be accessed: MOV AX, $ the execution of this instruction will make AX contain the
address of instruction that put this address in it.... but usually, it's not something to
worry about, just remember that org 100h must be the first line if you want to make a
tiny single segment executable file. note: dollar inside "$" or '$' is not a location counter,
but an ASCII character. Location counter has nothing to do with string terminating "$"
that is historically used by MS-DOS print functions.
Question:
Answer:
It is very similar to org 100h. This directive instructs the assembler to add 7C00h to all
addresses of all variables that are declared in your program. It operates exactly the
same way as ORG 100h directive, but instead of adding 100h (or 256 bytes) it adds
7C00h.
without ORG 100h directive assembler produces the following machine code:
If program is not using variable names and only operates directly with numeric address
values (such as [2001h] or [0000:1232h]... etc, and not var1, var2...) and it does
not use any labels then there is no practical use for ORG directive. generally it's much
more convenient to use names for specific memory locations (variables), for these cases
ORG directive can save a lot of time for the programmer, by calculating the correct
offset automatically.
Notes:
ORG directive does not load the program into specific memory area.
Misuse of ORG directive can cause your program not to operate correctly.
The area where the boot module of the operating system is loaded is defined on
hardware level by the computer system/BIOS manufacture.
When .com files are loaded by DOS/prompt, they are loaded at any available
segment, but offset is always 100h (for example 12C9:0100).
It is not recommended to use two neighbouring 16 bit ports, for example port 0 and port
1.
Every port has a byte length (8 bit), two byte port (16 bit word) is emulated using 2
bytes or 2 byte ports.
When the emulator outputs the second word it overwrites the high byte of the first word.
; For example:
MOV AL, 34h
OUT 25, AL
MOV AL, 12h
OUT 26, AL
; is equvalent to:
MOV AX, 1234h
OUT 25, AX
Question:
org 256
ret
bugi db 55
Answer:
To make the integrated assembler to generate more errors you may set:
STRICT_SYNTAX=true
in this file:
C:\emu8086\emu8086.ini
By default it is set to false to enable coding a little bit faster without the necessity to use
"byte ptr" and "word ptr" in places where it is clear without these long constructions
(i.e. when one of the operands is a register).
Note: the settings in emu8086.ini do not apply to fasm (flat assembler). To use fasm
add #fasm# or any valid format directive (valid for emu8086 version 4.00-Beta-15 and
above)
For differences between the integrated assembler (MASM/TASM compatible) and FASM
see fasm_compatibility.asm
FASM does not require the offset directive. By default all textual labels are offsets (even
if defined with DB/DW)
To specify a variable [ ] must be put around it.
Question:
The lab is set up with Windows XP machines on a domain. I have admin privileges but
the students do not. I tried setting the security setting of C:\emu8086 so all users have
full privileges but it did not help. Are there other folders that are in play when the
program is running?
Solution:
In order for virtual devices to work correctly, it is required to set READ/WRITE privileges
for these files that are created by the emulator in the root folder of the drive C:
C:\emu8086.io
c:\emu8086.hw
These files are are used to communicate between the virtual devices and the emulator,
and it should be allowed for programs that run under students' login to create, read and
write to and from these files freely.
To see simulated memory - click emulator's "aux" button and then select "memory" from
the popup menu.
EMU8086 Home