29q| Part IV ■ The Operating System Source Code This chapter discusses each of the important source files, some of the things that tie all of the source files together, and how to build the operating system using the tools included on the CD-ROM. One of my goals was to keep the source code organized in an easy-to-understand fashion. I hope I've met this goal. You may find some of the source files rather large, but most of the dependent functions will be contained in the file you are viewing or reading. You won't have to go searching through hundreds of files to find a three-line function. Comments in the Code You'll find out that I make a lot of comments in my source code. By including many com- ments, I can, a year or two later, go back and figure out what I did. It's not that I couldn't actually figure out the code without the comments; I just expend the time up front instead of later. In fact, sometimes I write the comments describing a small block of code before I actu- ally code it. Doing so helps me think. Calling Conventions I bring up the topic of calling conventions here because, as you look through the code, you will see that much of the assembler looks almost as if it were generated by a compiler. When a human writes this much assembler (and the code is to be interfaced with assembler generated by a compiler), the human becomes a compiler of sorts. Many of the lower-level procedures use registers to pass data back and forth. Quite a few of them, however, use the stack just as a compiler would. Two conventions are used throughout the operating system. The most prominent and the preferred method is pushing parameters left to right, with the called procedure cleaning the stack. The other is a mangled version of what you'd find in most C compilers for functions with an ellipsis (...). I call it mangled ‘be- cause the arguments are still pushed left to right, but the number of variable arguments is passed in the EDI register. The caller cleans the stack in this convention. Organization The MMURTL source code is organized in a modular fashion. Each logical section is con- tained in one file (or more) that is either C or assembler source code. There are also header files for the C source, and there are INCLUDE files for the assembler that tie publics, common variables, and structures together. All source files are located in one directory. There are 29 main source files (excluding header and include files). A brief description of each of the main source files follows:
Chapter 17 ■ Introduction to the Source Code MOSIDTASM This defines the basic Interrupt Descriptor Table (IDT). The IDT is a required table for the Intel processors. This is really just a data position holder in the data segment, because the entries in the IDT are done dynamically. The position of this file in relationship to the others is critical because the offset to the IDT must be identified to the processor. The IDT is the first file in the source, which means its data will be at the lowest address. In fact, it ends up at physical and linear address 0. MOSGDT.ASM This defines the Global Descriptor Table (GDT). This table is also a required table for the Intel processors when they run in protected mode. The GDT is 6K in size. Several selector entries are predefined so you can go directly into protected mode. This ends up at address 800h physical and linear. The position of this file is also critical, because the file is identified to and used by the processor. This must be the second source file in the assembler template file. MOSPDRJVSM This is also a data definition file that sets up the operating system's page directory and first page table. This file should also remain in its current order because I have hard-coded its address in some source modules. MPublics.ASM This is also a table, but it is not used by the processor. This defines the selector entries for all MMURTL public calls. MAIN.ASM This is the first assembler file that contains code. The operating system entry point is located here (the first OS instruction executed). Also some data is defined here. This file should be left in the order I have it in. The ordering for the remainder of the modules is not as important. On the other hand, I haven't tried playing “musical source files” either. Leaving them in their current order would probably be a good idea. Keyboard.ASM The keyboard source goes against my own rule of not combining a device driver with a system service. Keyboard.ASM was one of the first files written, and it works rather well, so I am reluctant to begin rewriting it (although I will, undoubtedly, someday). System services in assembly language are not fun to write or maintain. Chapter 25, “Keyboard Code,” explains all the mysteries behind this table- driven piece of work. Video ASM Video.ASM code and data was also one of the first pieces I wrote. You have to see what you're doing, even in the earliest stages of a project. Chapter 26, “Video Code,” goes into detail on this file's contents. Debugger.ASM This file contains the bulk of the debugger logic. Debugging is never fun when you have to do it at the assembler level. Debugging a debugger is even less fun. UASM.C This file is the debugger disassembler. It is a table-driven disassembler used to display instructions in the debugger. It's not very pretty, but it's effective and accurate. H
330 Part PV ■ The Operating System Source Code DevDrvr-ASM The device-driver interface code and data are contained in this file. This provides the re-entrancy protection and also the proper vectoring (indirect calling) of device-driver functions. Floppy.C Floppy disk device drivers are much harder to write than IDE hard disk drivers. This is one complicated driver. It seems to me that hardware manufacturers could be a little more compassionate toward software people. The reasoning behind controlling the drive motors separately from the rest of the floppy electronics still baffles me. HardlDE.C The IDE hard disk device driver was fairly easy to write. I was sur- prised. You will still see remnants of MFM drive commands in here because I started with that. I think it still works with MFM drives, but I don't have any more to test it. If you have MFM drives, you're on your own. RS232.C This file contains the RS-232 UART driver. It drives two channels, but it can be modified for four, if necessary. It supports the 16550 but only to enable the input buffer (which helps). Parallel. C The simple parallel port driver is contained here. FSys.C This is an MS-DOS FAT-compatible file system. It has only the necessary calls to get the job done. It provides stream access as well as block access to files. JobC.C The program loader and most of the job-related functions are handled in this file. JobCodeASM Lower-level job functions and supporting code for functions in JobC.C are contained in this file. TmrCodcASM The interrupt service routine for the primary system timer — along with all of the timer functions, such as Sleep ( ) — are in this file. IntCode.ASM Interrupt Service Routine (ISR) handling code can be found here. RQBCodcASM Request block management code is in this file. DMACodcASM In many systems, when device driver writers need DMA, they must handle it themselves. This file has routines that handle DMA for the program- mer writing device drivers. They need only to know the channel, how much to move, and the mode. Device driver writers will appreciate this. NumCnvrt.ASM This is some code used internally to convert numbers to text and vice-versa. MemCodcASM The code memory allocation, address aliasing, and management of physical memory can be found in this file. SVCCodcASM System service management code such as RegisterSvc( ) is in this file. MiscCodcASM This file has all the little things you need, but you never know where to put. High-speed string manipulation and comparison, as well as port I/O support, is in this file.
Chapter 17 ■ Introduction to the Source Code Kernel ASM All of the kernel calls and most of the kernel support code is in this file. Chapter 18, “Kernel Code,” discusses the kernel and presents the most important pieces of its code along with discussions of the code. ExceptASM Exception handlers such as those required for processor faults are in this file. Most of them cause you to go directly into the Debugger. InitCodcASM This file has all the helper routines that initialize most of the dynamic operating-system functions. Monitor.C The monitor program is contained in this file. It provides a lot of the OS functionality, but it really isn't part of the operating system. You could replace quite easily. H Building MMURTL MMURTL requires the CM32 compiler (included on the CD-ROM) for the C source files and the DASM assembler (also included on the CD-ROM). One MS-DOS batch file (MakeALL.BAT) will build the entire operating system. This takes about 1.5 minutes on a 486/33. Each of the C source files is turned into an assembler file (which is what the CM32 compiler produces). All of the assembly language source files are then assembled with DASM. DASM produces the operating system RUN file. The RUN file is in the standard MMURTL Run file format, which is described completely in Chapter 28, “DASM: A 32-Bit Intel-Based Assembler.” The only two MS-DOS commands you need are CM32 and DASM. An example of compiling one of the source files is the following: C:\MMURTL> CM32 Monitor.C After all the C source files are compiled, you use the DASM command, as follows: C:\MMURTL> DASM MMURTL. ATF It's truly that simple. If you want an error file, specify /E on the command line after the name. If you want a complete listing of all processor instructions and addresses, specify / L on the command line after the name. The following is the Assembler Template File (ATF). This file is required to assemble complex programs with DASM. The assembler is discussed in detail in Chapter 28, but you don't need to read all the DASM documentation to build MMURTL. ; Assembler Template File for MMURTL V1.0 .DATA ; These first 5 INCLUDES MUST be in this order!!!! .INCLUDE MOSIDT.ASM ; Defines the Interrupt Descriptor Table .INCLUDE MOSGDT.ASM ; 6K for GDT @ 00000800h Physical (1.5 Pages, 6K) $
I
332
Part IV ■ The Operating System Source Code
.INCLUDE MOSPDR.ASM
.INCLUDE MPublics.ASM
.INCLUDE MAIN. ASM
; OS Page Directory & 1st Table (8k)
; Indirect calling address table
; Main OS code and some data & START address
; Ordering for the remainder of the modules is not as important.
; An asterisk (*) by the include file indicates it originates as
; a C source file and must be compiled first with
; CM32 (no switches needed).
INCLUDE Keyboard. ASM
Keyboard ISR and Service
INCLUDE Video. ASM
Video code and data
INCLUDE Debugger. ASM
Code & Data for Debugger
INCLUDE UASM.ASM
Chapter 17 ■ Introduction to the Source Code fTT7 Using Pieces of MMURTL in Other Projects Some of you may find some of the code useful in projects that have absolutely nothing to do with writing an operating system. The same basic warning about the alignment of structures applies. The assembler INCLUDE files that define all the structures actually define offsets from a memory location. This is because DASM doesn't support structures, but you would have no problem setting them up for TASM or MASM. The calling conventions (described earlier) may get you into trouble if you want to use some of the assembler routines from a high-level language. If your C compiler allows it, you can declare functions as Pascal functions (some even use the old PLM type modifier), and they will work fine. Otherwise, you can calculate the correct offsets and fix the EQU statements for access where a C compiler would put them on the stack. You would also need to remove the numbers following the RET and RETF statements so that the caller could clean the stack, as is the C con- vention.
Powered by TurnKey Linux.