0% found this document useful (0 votes)
21 views14 pages

Chapter 2

The document discusses the initial steps for programming an ISA bus embedded PC, emphasizing the importance of low-level knowledge for effective firmware development. It suggests starting with a debugger and a simple C program, utilizing tools like Dunfield's Micro-C Developer's Kit for embedded x86 programming. The chapter also covers hardware communication through serial ports and the basics of BIOS and startup code necessary for running embedded applications.

Uploaded by

foof faaf
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views14 pages

Chapter 2

The document discusses the initial steps for programming an ISA bus embedded PC, emphasizing the importance of low-level knowledge for effective firmware development. It suggests starting with a debugger and a simple C program, utilizing tools like Dunfield's Micro-C Developer's Kit for embedded x86 programming. The chapter also covers hardware communication through serial ports and the basics of BIOS and startup code necessary for running embedded applications.

Uploaded by

foof faaf
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Embedded PCs ISA Bus.book : Chapter 2.

fm Page 21 Tuesday, July 1, 1997 7:32 AM

2 Chickens and Eggs


Now that we have a way to boot programs into our ISA bus target system, what
should the First Program be? A multitasking, multiuser, multimedia, protected
mode operating system featuring 32-bit flat memory model programming with no
artificial segment limits?

Hardly!

The whole point of this book is providing the detailed knowledge you need in order
to write good firmware and build custom hardware for an ISA bus embedded PC.
While I suppose you can simply ignore all of the low-level details, I’ve found that
this kind of knowledge is indispensable in ferreting out bugs, taking maximum
advantage of the machinery, and generally doing a good job.

The First Program should be a debugger. The Second Program should be a simple
C program. Next, we will look at the hardware used in typical ISA bus interfaces.
After that… well, all things in due time.

Despite the killer GUI debuggers now in vogue for PC program development, a
traditional command line debugger has a lot going for it, at least for simple projects.
Those “primitive” debuggers are relatively small, you can drive them from a serial
port, and they do what you need to get things started from scratch. If you have ever
used the DOS Debug program (and who hasn’t?) you know what I mean.

But, because our target system doesn’t have DOS, we can’t use good old Debug.
Rather than write my own debugger, I’ll take advantage of the Dunfield
Development Systems 8086 Micro-C Developer’s Kit. It includes the Micro-C
compiler, an assembler, a pair of debuggers, and a host of other utilities useful for
embedded x86 program development.

There are, of course, higher-powered ANSI standard C/C++ compilers that can
generate code for embedded PCs and, as we’ll see, ways to run GUI debuggers
through serial ports and network links. Dunfield’s programs are straightforward
enough that we can see the fundamentals quite clearly. We’ll get more complex in
successive chapters, but, for now, let’s get the basics up and running.

The Bare Essentials


The diskette boot loader I described last in Chapter 1 provides a simple and
inexpensive way to load a program into the target system. In the next chapter, we
will begin building a Firmware Development Board that will eventually hold some

21
Embedded PCs ISA Bus.book : Chapter 2.fm Page 22 Tuesday, July 1, 1997 7:32 AM

The Embedded PC’s ISA Bus

nonvolatile memory that can make the diskette optional, but the code from this
chapter will help us check out that board and the code that runs on it.

Recall that our target system includes an integrated I/O board with a pair of serial
ports or a system board with all that built in. Because we are not using the keyboard
or display, those two ports provide an ideal way to communicate with the firmware.
It seems a shame to let a resource like that go to waste, so I’ll use COM1 for the
firmware and COM2 for the debugger that helps get the code running.

Dunfield’s HDM86 (which stands for Hardware Debug Monitor) is one of the
slickest chunks of code I’ve seen in a while. It will run on any 80x86 CPU and uses
no external RAM: all of its data stays in the CPU’s registers, including the return
address for one level of subroutine call. Talk about tight coding!

Although I won’t require HDM86 for our projects, it comes in handy to verify
hardware startup functions such as DRAM refresh and memory mapping. Of
course, HDM86 must be in EPROM (or loaded from diskette, as we will do) and
you can’t download any code (where would it go?), but performing the actual I/O
operations “by hand” can often reveal circuit problems.

HDM86 includes commands to run tight read/write loops that hammer on a specific
I/O or memory address. This makes it easy for you to scope out problems, because
the hardware strobes provide convenient sync points. Of course, you must reset the
system to regain control, but that’s why HDM86 can live in EPROM.

Incidentally, CPU and system board hardware setup is one of the (many) problems
we’ve sidestepped entirely by using a standard ISA bus PC system board as our
target system. As far as we are concerned, the BIOS initializes everything and
passes control to us through the diskette boot loader. While we can change
anything necessary (and we certainly will, as you’ll see later on), the essential
startup details are a done deal.

Remember, the rules are changing. You give up detailed hardware diagrams to gain
PC compatibility and a rock bottom per-unit price. All things in PC-dom are
negotiable, so you can get schematics if you’re using system boards in production
quantities and you can write your own BIOS if you must have absolute control.
However, the relentless pace of PC progress means any system you use today will be
obsolete in six months, so don’t plan on using any tricks that work on just one
system. Stay generic and stay alive…

MON86, the larger of Dunfield’s two 8086 debuggers, occupies a little over 5 KB
(gasp!) and includes a disassembler, HEX file loader, up to eight code breakpoints,
and the usual Debug style commands. It arrives set up for the PC’s keyboard and

22
Embedded PCs ISA Bus.book : Chapter 2.fm Page 23 Tuesday, July 1, 1997 7:32 AM

Chapter 2: Chickens and Eggs

video display, but is easy enough to adapt to any standard PC serial port. Dunfield
includes a detailed set of comments to help you through the process, which involves
changing a few constants and reassembling the code.

The diskette boot loader handles standard COM programs starting at offset 0100,
but MON86 assumes its programs begin at 0000. The only change required is to set
MON86’s initial  (Program Counter, which Intel fans know as the
Instruction Pointer: ) to 0100 instead of 0000.

MON86 disassembles code into 8086-level instructions, but this is not a serious
impediment during the first few projects because plain old 8086 instructions
provide all the functions we need. When instructions found on ’386 and higher
CPUs will benefit our code, we’ll use an appropriate assembler and debugger.

Load and Go
You could burn the modified MON86 into an EPROM, but I put it on a diskette
and boot it into the target system’s RAM using the loader from Chapter 1.
Remember that the whole point of this exercise is building the tools to build the
board to hold that EPROM.

Your host system must have a serial port and communications program to talk with
MON86 on the target PC. Schematic 1 shows the three possibilities for the null
modem adapter between the host and target system serial ports. With standards
like this, it’s a wonder we get anything working at all. Be careful of commercial null
modems, because I’ve seen some that cross-wire all of the CTS/RTS and
DTR/DSR pins together. Hard to believe, but true.

When MON86 starts up on the target system, you should see a display similar to
Listing 1 on your host system’s comm program. If not, recheck the source in
MON86.MAC to verify that you have all the options set correctly.

Listing 1
This is what MON86 sends from the target system to the comm program running on your
host system. If you get something else (or nothing at all), make sure that both MON86
and your host system comm program are set up correctly... and doublecheck the serial
cable! MON86 uses a * prompt rather than the more familiar - or > characters.


 !"
#!!"
$

23
Embedded PCs ISA Bus.book : Chapter 2.fm Page 24 Tuesday, July 1, 1997 7:32 AM

The Embedded PC’s ISA Bus

Schematic 1
Connecting two PC serial ports together requires a null modem adapter to swap the input
and output pins. Use a breakout box or continuity checker to verify the connections inside
commercial null-modem adapters, as I’ve found some that were wired incorrectly. You
need not connect the other pins. For example, because the communication program on
the host PC will not be dialing or answering a modem, the RI and CD pins are unused.

Although I should not need to mention this, make sure you plug the serial cable
into the right ports on both PCs. I speak as an expert, having gotten both ends
wrong on the first crawl under the desk.

Once MON86 boots up, use its Output command to write a few values to the parallel
printer port at address 0378. The LED and switch circuit shown in Chapter 1 will
come in handy to watch the bits toggle. This simple step verifies that MON86 is
loaded, the serial ports and your comm program work, and the parallel port is at the
address you expect.

The next step involves loading a HEX program with, naturally enough, the Load
command. Rotate.ASM, shown in Listing 2, has a simple loop that rotates a single
bit across the parallel port. It uses a BIOS delay function to make the output visible,
so you won’t absolutely need a scope to check this code out.

24
Embedded PCs ISA Bus.book : Chapter 2.fm Page 25 Tuesday, July 1, 1997 7:32 AM

Chapter 2: Chickens and Eggs

Listing 2
Use MON86 to load Rotate.HEX through the serial port. The LED and switch hardware
described in Chapter 1 will show you the results appearing on the parallel printer port.
The code shown here should be assembled with Dunfield’s ASM86 assembler; the
syntax is slightly different than Microsoft’s MASM or Borland’s TASM, but no more
unusual than some other assemblers.

%& '((
$
 )*'(+, -!.!!!
 #/*' ( -0
$
%-1 % / #/ %
2 )#/ #""!
$
-3 ) -!
-3 #)
$
 )* 4 -"! .
 )*(  567.."
 #3*'
 2 '
$
  #) %.!
  )
$
8  9%-1

Dunfield’s assemblers can produce either Intel or Motorola HEX files and MON86
will accept either flavor without any special attention. However, if you plan to send
the files to an EPROM programmer or use them as an input to other programs, be
sure you select the appropriate assembler command line switches.

MON86 does not echo the characters it receives while transferring the HEX data,
which means you may have to configure your comm program to not wait for the end
of each line. If the comm program seems to hang after sending the first line, the
two programs are probably locked in this deadly embrace. Cancel the transfer, reset
the comm program’s options, and try again.

Dunfield’s HEXFMT utility will transform Rotate.HEX into Rotate.BIN, which the
diskette boot loader will pull directly into RAM. This is the main advantage of
changing MON86’s default : you can debug programs using MON86, then
boot them directly from diskette with our loader, without making any changes.

The C compiler forms the last piece of the puzzle, as you might expect. It turns out
that the effort is almost anticlimactic because Dunfield has done nearly all of the
required work already.

25
Embedded PCs ISA Bus.book : Chapter 2.fm Page 26 Tuesday, July 1, 1997 7:32 AM

The Embedded PC’s ISA Bus

Micro-C Startup
This may come as a shock to some C firmware programmers, but there’s some
startup code that runs immediately after the CPU comes out of a hardware reset,
long before your 7:; function gets control. Regardless of whether you program
in C on a microcontroller or an x86 CPU, you must understand the how, what, and
why of that startup code. Only after the startup code runs successfully can your
program execute your instructions.

On PCs running a standard operating system, of course, all this is taken care of for
you. Now that our target system runs without even DOS, it’s time to learn more
about the machinery you’ve been taking for granted all along.

The “bare metal” startup begins when an x86 CPU emerges from hardware reset by
fetching the first instruction. Each of the 8086, 80286, 80386, 80486, and Pentium
CPUs start with slightly different -< register values, but the system board maps
the resulting physical address to FFFF0 (a.k.a. F000:FFF0) in the ROM BIOS.

As I mentioned earlier, the PC’s BIOS handles all the initializations required to get
from that first instruction fetch to a system that can boot an operating system or,
better yet, your embedded program. If you are writing x86 embedded code without
the luxury of a BIOS, you must know the details of the target system’s hardware so
you can provide all the right startup functions.

Several vendors offer “BIOS kits” that reduce the tedium of rolling your own
BIOS. Even if you don’t use all the standard functions, starting with known-good
code can trim months off your schedule. Check the Sources appendix and the ads
in your favorite magazines; this is a small but significant niche market.

For our present purpose, however, the BIOS sets up the hardware, reads our boot
loader from the diskette, sets up the segment registers, and branches to the loader.
Our code reads in the first DOS file, sets up the segment registers, and branches to
whatever is at offset 0100. That’s where the C startup code must begin.

Listing 3 shows the top part of 8086RLPT.ASM, Micro-C’s 2 memory model
startup code. It sets up the segment registers (again), clears the uninitialized
variables, and starts the C program with a #// to the 7:; function. If the
7:; function returns, the default Micro-C startup code invokes the  2 '=
Terminate Program DOS function, which is appropriate for DOS-based programs.

I replaced the termination code with a simple 8  back to the top, but even that
isn’t strictly necessary. As you will see later, our embedded C programs never end

26
Embedded PCs ISA Bus.book : Chapter 2.fm Page 27 Tuesday, July 1, 1997 7:32 AM

Chapter 2: Chickens and Eggs

Listing 3
The Micro-C startup code for the Tiny memory model loads the segment registers, clears
the uninitialized variables, and calls the main() function. I modified the code just after the
CALL instruction to restart the program rather than invoke a DOS function we don’t have.

%&'((
$
% >? $ $$$7:;@
 #)- & >7
 --#) ---
 -*'AAA> !.B
 -#) --
 >-#) ->-
$C!D"%# 
 *E7 !D"%#
 )*EFGE7 &D !D"%#
) % #/#/ &D
%> % @
-2 -4 C77
#// 7 >@.77
8  9% $$$0 -@H
$>@ .% - -
@ ) % #3#3 A.(G@
 2'= >@

and that 8  should never be executed. Nevertheless, I feel better with a valid
instruction instead of a guaranteed trip to the weeds; call me compulsive.

Reloading the segment registers three or four times in quick succession is


esthetically displeasing, but of no real consequence because the values are the same.
The way I’ve set things up, each step in the chain is more or less independent of the
others, so the new register loads appeared Just In Case the previous program isn’t
under my control.

Because the diskette boot loader handles only COM files, all the code and data must
reside in one 64 KB segment. This implies all the segment registers have the same
value, which is precisely the definition of the 2 memory model. Micro-C can
also produce -7!! model code, which uses separate Code and Data segments, but
we will get along quite happily with a single segment until we explore BIOS
extensions in Chapter 10.

Console I/O
The Micro-C runtime library includes the usual console I/O functions that connect
.:; and .:;with the outside world. Despite the fact that they’re in a
file called SerIO.ASM, .:; delivers characters from the PC keyboard and
.:; sends them to the video adapter. This makes sense for those embedded

27
Embedded PCs ISA Bus.book : Chapter 2.fm Page 28 Tuesday, July 1, 1997 7:32 AM

The Embedded PC’s ISA Bus

applications that use PC hardware, but our code doesn’t yet have the luxury of
standard PC I/O. Remmber what’s missing from Photo 1 in the previous chapter?

Fortunately, it’s easy to substitute the corresponding serial I/O routines. While the
BIOS serial functions are not adequate for real life serial I/O, they will suffice for
our immediate purposes. Higher performance is, as Steve Ciarcia puts it, “a simple
matter of software” that you can work on when the occasion arises.

Listing 4 shows the Firmware Furnace console I/O routines in SerIOFF.ASM. Use
the SLIB utility from Micro-C’s library utility to replace SerIO.ASM in Tiny.LIB:

slib i=tiny.lib a=serioff.asm r=serio.asm

Your code must call :; to specify the bit rate and COM port number. The
data rate is limited to 9600 b/s, the maximum allowed by BIOS function
 2 5 #3I((. For speeds up to 19200 b/s, use #3I(5. Beyond that,
however, you must twiddle the serial port hardware directly.

Although :; can set up any one of the four standard serial ports, the
typical integrated I/O board has two ports, so MON86 uses COM2. You may use
the same port for both your C program and the debugger, but the output can be
confusing at times.

Finally, we are ready for a C program…

Listing 4
Micro-C’s default console I/O routines use the target system’s BIOS video and keyboard
functions. This code substitutes the corresponding BIOS serial I/O functions, which, while
not adequate for heavy-duty use, are good enough to get us started.

$%!.7 - #- !


$>70"""J-#4GG>" !
$
$GGGGGGGGGGGGGGGGGGG
$-!
$:0 ;
$#7  7
$
  4- &7.B
 4)- >- -#-
 >-4)
 #)5K4L .0:.B" ;
 )* -0!!
 *E00 -0!0
%> >
-#-M -. 

Listing continues on next page

28
Embedded PCs ISA Bus.book : Chapter 2.fm Page 29 Tuesday, July 1, 1997 7:32 AM

Chapter 2: Chickens and Eggs

Listing continued from previous page

 #//
>& #/ .0!"@
# #/*, :  "!;
 /* 0=<(,<
% / #//
#  #/*'>( .!!10
% #/*'(+ - "
 #3*( 4 - .70
 )=K4L & 70:.B"!;
> ) B I(
 E )  !
 2 '5 4 -!D
$7"7.!".77.
 4)E  "@
# 4)4) .1""@
 #)*'((5( 7>-4 -"
 >-#)
 )>-<K4)L .""
# )*'(((5 77"7.!
 #/) ..0
% #/*'(+ .%2-N2%:";
2 )#/
%>2
$
$GGGGGGGGGGGGG
$20! 4 -G..0!0
$2"@4 -0."!
$
E00 M ( (
M ( 
M +(( =
M (( +
M =(( 5
M =5(( 
M 5 ((
M  (( ,
$
$
$M!
  4)- #"".B
 -=K4)L &
E  #/K-L &.
  - -B@
#  #/#/ >" E
8C E O@
#// E. M
8  9E !!
$
$M.1 >M/ >9P%!
$
.  4)- #"".B
 #)=K4)L &..
E. #// E. M!
  #/*'(# 1!E
8 C E B
 #/*'( #"".
8  9E. M

Listing continues on next page

29
Embedded PCs ISA Bus.book : Chapter 2.fm Page 30 Tuesday, July 1, 1997 7:32 AM

The Embedded PC’s ISA Bus


Listing continued from previous page

$
$M.1!
$
.  4)- #"".B
 #)=K4)L &..
$M4 Q4 -.!!
E.  )E  
 #3*'( M.
 2 '5 !!4 -
E %>2
$
$3!..
$%!1..#/
$
1.  #3*'(+ -R
 )E  
 2 '5 #B4 -
2>-2 #3*'( .B""
8C 1. "
 #3*'(= &..
 )E  
 2 '5 #B4 -
) % #3#3 .!0
%>2
$
$2 ..: !;
$
.B.  #3*'(+ -R
 )E  
 2 '5 #B4 -
2>-2 #3*'( .B""
 #)G 7 .
8C E.. ..0!
 #3*'(= &.
 )E  
 2 '5 #B4 -
) % #3#3 "." !
E.. %>2
$
$%..1!
$
. #// 1. M .."
%>2
$
$2 ..:1%9P >M/ >!;
$
.B.  #3*'(+ -R
 )E  
 2 '5 #B4 -
2>-2 #3*'( .B""
 #)*( 7
8C E.. ..
 #3*'(= &..
 )E  
 2 '5 #B4 -
) % #3#3 "." !
E.. %>2

Listing continues on next page

30
Embedded PCs ISA Bus.book : Chapter 2.fm Page 31 Tuesday, July 1, 1997 7:32 AM

Chapter 2: Chickens and Eggs

Listing continued from previous page

$
$%..1%9P >M/ >!
$
.#//1.M ."
) %#3#3C3&3
 #/*'(
8 CE  6
 #/*'(# >M/ >
%>2
$
$%.<:0 D;
$
 4)-#"".B
 -5K4)L&0 ""
) %))C)
E=#//.&..
 #/*'( 4.B.E
8CE+O"!
 #/*',A!E
8CE+O"!
 #/*'(#>" !E
8CE5O"!
 )=K4)L#1"E
8#>E=O"J..
 K-L#/M
 -#".
 )#".!
#//E.M
8 9E=#"."
$!.. 70 
E+# ))#0E
8CE=O
 #/*'( 4.B
#//E. 
 #/*JJ-.
#//E. 
 #/*'( 4.B
#//E. 
>-4.B
>)%".!
8 9E=#"."
$ 1!7
E5#//E.>.
 PK-L*(C7
 #))%!
%>2
'<E =

Why do some labels start with question marks? They mark local branch targets that will
not be called from code outside this file. Refer to the Micro-C documentation for more
details on the special treatment applied to those labels by the assembler.

31
Embedded PCs ISA Bus.book : Chapter 2.fm Page 32 Tuesday, July 1, 1997 7:32 AM

The Embedded PC’s ISA Bus

Say “Hello!”
Back before C compilers (excuse me, Application Development Environments)
required Windows 95, came on CD-ROMs, and soaked up hard disk space
denominated in tenths of gigabytes, the first C program had one essential line:

 :S3!!1!"HTS;U

Fortunately for us, Micro-C still retains that charming simplicity. Hello.C, shown in
Listing 5, uses  :; to send out the obligatory message through the target
system’s serial I/O routines described above.

Our Hello.C program must not “fall out the bottom” of its main loop, because there
is no operating system to regain control. As you’ll see throughout this book,
essentially all our embedded programs run continuously from power-on to
shutdown. High octane embedded systems require real operating systems with
dynamically loaded programs, but we don’t need that level of performance just to
explore the ISA bus.

Hello.C uses a 1! loop to hold the do-forever code. In this case we increment a
counter, display the value, and call a BIOS function to waste about half a second.

Listing 5
The canonical First C Program prints “Hello, world!” and returns to the operating system.
Our ISA-bus target system doesn’t have an operating system, so, after this version of
Hello.C displays its message, it begins an endless loop showing the contents of a simple
counter. A BIOS function provides a half-second delay between displays.

*.!"9 ( P
*.!"S<T7. T.7T ( 0S

*" / >/#O Q$  567.." $Q

"U

7:;V

: ((;U Q$! $Q


:S3!!1!"HTS;U
I(U

1!:2%>;V
 :S<WTSFF;U
7V
 )*/ >/#O
 )*(
 #3*'
 2 '
X
X

32
Embedded PCs ISA Bus.book : Chapter 2.fm Page 33 Tuesday, July 1, 1997 7:32 AM

Chapter 2: Chickens and Eggs

The delay is essential because there is no point in sending continuous 9600 b/s
data: each line would take only about 10 milliseconds, and you just can’t read text
off the screen that fast.

Micro-C includes a Command Coordinator that runs the preprocessors, compiler,


assembler, linker, and so forth in the right order with the appropriate files, as well as
a character-based Integrated Development Environment. I prefer the command-
line compiler, mostly because that’s what I started out with, and use this command
line (in a batch file, of course) to recompile the program on the host system:

cc86 hello -ciklmop m=t

The result appears in file Hello.HEX with Intel HEX format. Boot MON86 from the
floppy in the target system, then use the Load command. Send Hello.HEX from your
host system to the target system using your comm program’s ASCII file transfer
function, then do a G 0100 to start Hello.

After you’re comfortable with Micro-C, you may want to omit some of the
compiler switches. The -k option keeps all the intermediate files, generating quite a
clutter in your \temp subdirectory, and is of use mostly while you familiarize
yourself with the compiler. The -c option includes all of your C language comments
in the assembler output, which can inhibit the peephole optimizer’s best efforts.

Because MON86 uses COM2 for debugging output and Hello uses COM1 for
normal output, you must have two serial ports on your host PC to monitor the
action. This is one of the big advantages of a multitasking operating system like
Windows 95 or OS/2: simply run two cables, start two comm program sessions,
and watch their windows update simultaneously.

You can also use a PC with a single port and one comm program, but you must
switch the cable from the target system’s COM2 port to COM1 after starting Hello.
You’ll miss the 3!!M!"H output message, but the counter values should
come through correctly and display on your host system.

You can use MON86 to step through your C programs at the assembler level, set
breakpoints, and dump memory. After you’re sure the code is solid, use HEXFMT to
convert the HEX file to a COM file just as you did for Rotate.HEX:

hexfmt hello.hex -b w=hello.bin

Copy that file to a diskette with the boot loader from Chapter 1, pop it in the target
system’s drive, and hit the Reset button. You should see the same output from
COM1 as you did when running it under MON86.

33
Embedded PCs ISA Bus.book : Chapter 2.fm Page 34 Tuesday, July 1, 1997 7:32 AM

The Embedded PC’s ISA Bus

At this point you have everything required to develop moderately complex


embedded programs running on a standard x86 system board. The diskette boot
loader reads a program from disk into the target system’s RAM without using an
operating system or specialized development hardware. Micro-C provides the
programming essentials in a well documented, comprehensible package. Your
program sends trace information through the serial port to your host system.

OK, ball’s in your court…

Release Notes
The files for this chapter include all the demo program source code, HEX, and BIN
files, as well as the serial port code in SerIOFF.ASM. There are several useful batch
file to set up Micro-C’s environment variables, too. See the ReadMe.txt files in both
this chapter’s subdirectory and the \ISABus\Code\Micro-C subdirectory.

You’ll need Dunfield’s 8086 Micro-C Developer’s Kit to compile and assemble the
source code. The debuggers described above are a part of the package, as well as
numerous utility programs and debugging features that I haven’t mentioned. See
the Sources appendix for pointers to the DDS Web page.

Of course, you might prefer a different compiler. The disadvantage of the Borland,
Microsoft, and similar high-end PC C compilers is that they are primarily intended
for use with DOS and Windows. Adapting them to a DOS-less embedded system
is possible, but it’s not a trivial exercise. We’ll explore this topic in much more detail
in Chapter 11.

However, if you already have a favorite x86 C compiler, take a look at its 2
model startup code and see what you can do. You must verify that the generated
code has no DOS or Windows calls, which probably rules out the normal character
I/O routines (if not all the startup code), and write your program without using any
DOS-based library routines. Give it a try and see how it works!

34

You might also like