* added compilers lcc and bcc (linux86)
[mascara-docs.git] / i86 / mtx / mtx / LAB1.html
blobd289288f9e6b906e3c25228e48267c26fb697e4c
1 <Title>460 Week 1 Notes</Title> <Body bgcolor="#00cccc" text="#000000"><H1>460 Lab Assignment #1</H1><Pre>
2 CS460 Lab Assignment #1
3 ###########################################################################
4 DUE : Week of Jan 16, 2012
5 ###########################################################################
7 1. REQURIEMENT:
8 To deveop a boot program for booting the MTX operating system.
10 2. Background Reading List and Timetable:
11 Notes #2: Booting
13 3-1. Download the MTX image file
14 http://www.eecs.wsu.edu/~cs460/samples/LAB1/mtximage.bin
15 Use it as a VIRTUAL floppy image OR dump it to a REAL floppy disk by
16 dd if=mtximage.bin of=/dev/fd0
17 Then, boot up MTX from the floppy disk.
18 Test run the MTX operating system as demonstrated in class.
20 CONTENTS of the MTX disk image:
22 | B0 | B1 ...................................................... B1339 |
23 --------------------------------------------------------------------------
24 |booter| An EXT2 file system for MTX; kernel=/boot/mtx |
25 --------------------------------------------------------------------------
27 LAB#1 IS FOR YOU TO WRITE A BOOTER PROGRAM TO REPLACE THE booter IN BLOCK#0
28 TO BOOT UP THE MTX KERNEL, which is the image file /boot/mtx.
30 3-2. Download and install the BCC package to YOUR Linux system:
31 http://www.eecs.wsu.edu/~cs460/samples/BCC/
32 Read the HOWTO file for install instructions.
34 3-3. Background: Computer Architecture and Programming Environment
35 Lab#1 assumes the following hardware and software environments.
37 Hardware: Intel X86 based PC running Linux. If you don't have such a PC,
38 try to get one or work on the LAB PCs in Sloan 327.
39 Sofware: BCC compiler-assembler-linker under Linux.
41 When a PC starts, it is in the so-called UNPROTECTED mode, also known as
42 the 16-bit mode. In such a mode, the PC's CPU can only execute 16-bit code
43 and access 1 MB of memory. The diagram below shows the 1MB memory layout,
44 shown in 64KB segments.
46 0x0000 0x1000 ....... 0x9000 0xA000 ... 0xF000
47 -----------------------------------------------------------
48 | | .......... | | BIOS |
49 -----------------------------------------------------------
50 |<-------------- 640KB RAM area --------->|<--- ROM ----->|
52 The CPU's internal registers are
53 segment registers: CS, DS, SS, ES
54 general registers: AX, BX, CX, DX, BP, SI, DI
55 status register : FLAG
56 stack pointer : SP
57 instruction point or program counter: IP
58 All registers are 16-bit wide.
60 The CPU operates as follows:
61 1. At any given time, the CPU can only access FOUR segments of memory,
62 each segment is 64KB in size and pointed by a segment register:
64 CS -> Code segment = program code or instructions
65 DS -> Data segment = static and global data (ONE COPY only)
66 SS -> Stack segment = stack area for calling and local variables.
67 ES -> Extra segment = temp area; may be used for malloc()/mfree()
69 2. The CPU executes in an infinite loop:
71 while (power on){
72 (1). IP points at the instruction in Code segment of memory;
73 (2). Fetch instruction (always from Code segment), so the
74 20-bit physical address is (CS<<4 + IP);
75 (3). Decode the instruction = (opcode, operands);
76 (4). If operands are in memory: load operands into CPU
77 (always from Data segment), so the 20-bit physical
78 address is (DS<<4 + operandAddress)
79 (5). Execute the instruction, which may change IP (by
80 br, jmp, call, ret) OR SP (by push,pop,call,ret).
81 When SP is used, e.g. in push, pop, call, ret, it's
82 always in the Stack sgement, so the 20-bit physical
83 address is (SS<<4 + SP).
84 If result must go back to memory, it's again in the
85 Data segment.
86 (6). Checking for interrupts OR execution error. If so,
87 start exception processing.
90 3. The number of DISTINCT segments presented to the CPU depends on the
91 memory model of the executing program, which in turn is determined by
92 the compiler and linker used to generate the binary executable image.
93 The most often used memory models are
95 SMALL model (COM files): CS=DS=SS all in ONE segment <= 64KB
96 MEDIUM model (EXE files): CS=CodeSegment, DS=SS=Data+Stack segment
97 (up to 128 KB of execution image size)
99 SMALL memory model programs are easier to maintain, for example, they can
100 be loaded to any segment in memory and setup to run correctly with ease.
101 They are typically used in a simple environment such as during booting.
103 Finally, in order to run a SMALL memory model program, the following steps
104 are needed:
105 (1). A C compiler and assembler that generate 16-bit (object) code
106 (2). A linker that combines the object code to generate a ONE-segment
107 binary executable image.
108 We shall use BCC under Linux to do (1) and (2).
109 (3). LOAD the binary executable image into memory (at a segment
110 boundary, of course) and set CPU's CS=DS=SS = loaded segment.
111 Set SP at the HIGH end of the segment.
112 Set IP at the beginning instruction in the segment.
113 Then the CPU will execute the image correctly.
115 3-4. An assembly file bs.s in in the ~cs460/samples/LAB1/ directory.
116 You may download and use it directly.
118 ! bs.s file
119 !============================================================================
120 .globl begtext, begdata, begbss ! needed by linker
121 .text ! these tell as:
122 begtext: ! text,data,bss segments
123 .data ! are all the same.
124 begdata:
125 .bss
126 begbss:
127 .text
128 !============================================================================
130 BOOTSEG = 0x9000 ! Boot block is loaded again to here.
131 SSP = 8192 ! Stack pointer at SS+8KB
133 .globl _main,_prints ! IMPORT symbols
134 .globl _getc,_putc,_diskr,_setes,_inces,_error ! EXPORT symbols
136 !-------------------------------------------------------
137 ! Only one SECTOR loaded at (0000,7C00). Get entire BLOCK in
138 !-------------------------------------------------------
139 mov ax,#BOOTSEG ! set ES to 0x9000
140 mov es,ax
141 xor bx,bx ! clear BX = 0
142 !---------------------------------------------------
143 ! diskio[0,0] to read boot BLOCK to [0x9000,0]
144 !---------------------------------------------------
145 xor dx,dx ! drive 0, head 0
146 xor cx,cx
147 incb cl ! cyl 0, sector 1
148 mov ax, #0x0202 ! READ 1 block
149 int 0x13
151 jmpi start,BOOTSEG ! CS=BOOTSEG, IP=start
153 start:
154 mov ax,cs ! establish segments again
155 mov ds,ax ! we know ES,CS=0x8F00. Let DS=CS
156 mov ss,ax ! SS = CS ===> all point at 0x8F00
157 mov es,ax
158 mov sp,#SSP ! SP = 8KB above 0x90000
160 mov ax,#0x0012 ! 640x480 color
161 int 0x10
163 call _main ! call main() in C
165 test ax, ax
166 je _error
168 jmpi 0,0x1000
171 !======================== I/O functions =================================
172 !---------------------------------------------
173 ! char getc() function: returns a char
174 !---------------------------------------------
175 _getc:
176 xorb ah,ah ! clear ah
177 int 0x16 ! call BIOS to get a char in AX
178 ret
180 !----------------------------------------------
181 ! void putc(char c) function: print a char
182 !----------------------------------------------
183 _putc:
184 push bp
185 mov bp,sp
187 movb al,4[bp] ! get the char into aL
188 movb ah,#14 ! aH = 14
189 movb bl,#0x0D ! bL = cyan color
190 int 0x10 ! call BIOS to display the char
192 pop bp
195 !---------------------------------------
196 ! diskr(cyl, head, sector, buf)
197 ! 4 6 8 10
198 !---------------------------------------
199 _diskr:
200 push bp
201 mov bp,sp ! bp = stack frame pointer
203 movb dl, #0x00 ! drive 0=FD0
204 movb dh, 6[bp] ! head
205 movb cl, 8[bp] ! sector
206 incb cl
207 movb ch, 4[bp] ! cyl
208 mov bx, 10[bp] ! BX=buf ==> memory addr=(ES,BX)
209 mov ax, #0x0202 ! READ 2 sectors to (EX, BX)
211 int 0x13 ! call BIOS to read the block
212 jb _error ! to error if CarryBit is on [read failed]
214 pop bp
217 ! void set_es(unsigned short segment) set ES register to segment
218 _setes:
219 push bp
220 mov bp,sp
221 mov ax,4[bp]
222 mov es,ax
223 pop bp
226 ! void inces() inc ES by 0x40, or 1KB
227 _inces:
228 mov ax,es
229 add ax,#0x40
230 mov es,ax
233 !------------------------------
234 ! error & reboot
235 !------------------------------
236 _error:
237 mov bx, #bad
238 push bx
239 call _prints
241 int 0x19 ! reboot
243 bad: .asciz "Error!"
245 ! end of bs.s file
248 BCC's C compiler prefix every GLOBAL symbol with an underscore, so that main
249 becomes _main, getc becomes _getc, etc.
250 BCC's assembler uses the same convention for global symbols, which must be
251 declared by the .globl statements in assembly code.
253 As shown, bs.s EXPORTs the following functions
254 char getc();
255 void putc(char c);
258 void diskr(int cyl, int head, int sector, char *buf)
259 viod setes(int segment);
260 void inces();
262 which are callable from C.
264 *********** THE LOGIC OF bs.s IS AS FOLLOWS: *************
266 (1). It is to be combined with a .c source file to form a booter code
267 which occupies the boot BLOCK (block#0) of a floppy disk.
269 (2). During booting, BIOS loads 512 bytes of this boot BLOCK to
270 (0x0000,0x7C00) and jumps to it. Although only half in, it can start
271 execution because it does not need any portion that's not yet loaded.
273 (3). It sets ES=0x9000, BX=0 and calls diskr() to load the entire boot
274 BLOCK to 0x9000.
276 (4). Then it jumps to the symbol start relative to 0x9000, and
277 continues to execute from there. This jump sets CS to 0x9000.
279 (5). It sets DS,SS to CS, and SP to 8KB above SS. Note that ES is already
280 set to 0x9000 in (3). Thus, CS,DS,SS and ES all point at the same
281 segment address 0x9000.
283 (6). It then calls YOUR main() in C, which is specified in 3 below.
285 (7). Upon return from C code, bs.s checks the return value, which should be 1
286 if no error. If no error, it jumps to (0x1000, 0) to start up MTX.
287 else; it displays an Error! message and reboot.
289 3. YOUR C code:
291 First, some notes about using BCC's C compiler:
293 (1). Use identifier names <= 8 chars; the compiler will truncate long names
294 to 8 chars, including the leading _
295 (2). Declare all variables BEFORE using them (else compile error)!!!!
296 (3). Declare function parameters OUTSIDE the function heading, e.g.
297 int myfun(x, y) int x; char *y;
300 instead of int myfun(int x, char *y)
303 (You may use the bcc -ansi option to allow ANSI style C statements)
305 (4). Whenever in doubt, use pretheses to ensure correct precedence, e.g.
306 a = b % 2 + 1; should be written as a = (b % 2) + 1; if that's
307 what you meant.
309 Other than these, bcc is very good as it produces excellent error
310 diagnostics.
312 Second, never assume that your program will work. More likely, it will NOT.
313 An easy way to TRACE your program execution, especially for debugging, is to
314 use putc('1'); putc('2'), etc. in your C code. This way you can easily see
315 where the program stopped working.
317 You must implement the main(), gets() and prints(char *s) functions in C.
318 You may use the C library functions strcmp(), strcpy(), strlen(), etc.
319 as long as they do NOT need the support of an operating system. But you may
320 NOT use printf(), scanf(), putchar(), getchar(), ... because these I/O
321 functions depend on the support of an operating system. During booting,
322 there is NO operating system yet!
324 For PRE-LAB1 work, write YOUR main() function to do the following:
326 (1). Print a string "What's your name?".
327 (2). Read in a name string, e.g. "John Smith".
328 (3). Print a string "Welcome, John Smith!".
329 (4). If the name string == NULL, print "bye bye!" and return 1
330 else, loop back to (1) again.
332 LAB#1 IS FOR YOU TO MODIFY THIS SIMPLE main() FUNCTION TO ACTUALLY BOOT
333 UP THE MTX OPERATING SYSTEM.
335 4. HOW TO cross COMPILE and LINK under Linux: (Use these as a sh script)
336 --------------------------------------------------------------
337 echo comiling ......
338 bcc -c main.c
339 as86 -o bs.o bs.s
340 echo linking .......
341 ld86 -d bs.o main.o /usr/lib/bcc/libc.a
342 echo check a.out size
343 ls -l a.out
344 echo dumping a.out to floppy .......
345 dd if=a.out of=/dev/fd0 bs=1024 count=1
346 -------------------------------------------------------------
347 The last step dumps (at most 1KB of) a.out to BLOCK 0 of /dev/fd0.
348 The resulting disk should be bootable.
350 IMPORTANT:
351 ****************************************************************
352 Your a.out must be <= 1024 bytes in order for it to fit in ONE disk block.
354 THERE IS NO FAT IN MY bs.s CODE. The .s type says loud and clear
355 that it's already Slim! If your a.out is too big, it has been eating
356 too much junk food. You must put it on diet until it weighs no more
357 than 1024 pounds (bytes, that is).
358 ****************************************************************
360 5. Compile and link bs.s with YOUR main.c to generate a booter and dump it
361 to BLOCK #0 of a floppy disk. Boot up from the floppy and make sure your
362 program works correctly.
364 6. How to write YOUR I/O functions:
365 During booting, only BIOS is available for I/O. The getc()/putc() fucntions
366 in bs.s calls BIOS to input a char from beyboard/output a char to display.
368 Use getc() to implement YOUR OWN
370 gets(s) char *s; which inputs a string from the keyboard.
372 NOTE: getc() of BIOS does not echo the input char. YOU must echo the
373 input chars to see the chars. While collecting inputs,char *s MUST have
374 memory space to hold the input chars. From the keyboard,the ENTER key
375 ('\r' in C) signifies the end of an input string.
377 Use putc(c) char c; to implement YOUR own
378 prints(s) char *s;
379 which prints a string to the display.
380 ===============================================================================
382 7. MAIN TASK OF LAB#1: DUE and DEMO in Week of Jan. 16, 2012
384 7-1. Refer to the CONTENTS of the MTX disk image:
386 | B0 | B1 ............................ B1339 |
387 ------------------------------------------------
388 |booter| An EXT2 file system for MTX |
389 ------------------------------------------------
391 Block# 0 contains a booter, which can boot up MTX.
392 The remaining parts of the disk is an EXT2 file system (per CS360) with
393 1KB block size. The EXT2 file system contents are
397 -------------------------------------------
398 | | | | | |
399 bin dev etc user sys boot
400 | | | | |
401 commands devFiles passwd userDirs mtx
402 (bootable MTX kernels)
404 where /boot/mtx is a bootable MTX kernel.
406 Write YOUR main() as follows:
408 (1). Prompt for filename to boot, e.g. mtx or image, etc. You may assume
409 that all bootable files are in the /boot directory.
410 (2). Find the file. Recall that "finding a file amounts to finding its
411 inode".
412 (3). From the file's inode, find the disk blocks of the file:
413 i_block[0] to i_block[11] are DIRECT blocks, and
414 i_blokc[12] points to INDIRECT blocks.
415 MTX kerenl has at most 64 (1KB) blocks, so no double-indirect blocks.
417 (4). Load the blocks of /boot/mtx into memory at the segment 0x1000.
418 (5). return 1 to bs.s for OK, return 0 for failure.
419 ==========================================================================
420 (6). If YOUR main() loads the disk blocks of mtx successfully and returns 1
421 bs.s will jump to (0x1000, 0) to start up MTX.
423 7-2. How to read a disk block into memory:
425 The function diskr(cyl, head, sector, buf) in bs.s reads a disk block
426 (2 sectors) at (cyl, head, sector) into memory at the physical address
427 (ES<<4 + buf), i.e. buf is a VIRTUAL address in the segment pointed by ES.
428 For example,
430 ES -> Data segment, buf is the address of a global variable in C, then
431 diskr(cyl, head, sector, buf); reads a block into buf;
432 ES -> 0x2000, buf=0, then diskr(cyl, head, sector, buf); reads a block
433 to (0x2000<<4 + 0), etc.
435 The functions setes(segment); sets ES to any segment,
436 inces(); increment ES by 0x40, which is 1KB.
438 A 1.44MB floppy disk has 80 cylinders, 2 heads per cylinder and 18 sectors
439 under each head. The PHYSICAL layout of a floppy disk is as follows, where
440 cyl, head, sector all count from 0.
442 ----------------------------------------------------------------------
443 |s0 s1 .... s17 | s18 .... s35 | s36 ..... s53|s54 s71| ...
444 ----------------------------------------------------------------------
445 |<-- head 0---->|<--- head 1 -->|<--- head 0 --->|<-- head 1 --->| ....
446 |<--------- ---cyl 0 ---------->|<-------- cyl 1 ------------->| ....
448 A disk block consists of 2 contigious sectors. Given a block number, blk,
449 which counts from 0 to 1339, how to convert blk into (cyl, head, sector)?
450 -------------------------------------------------------------------------
451 Use the Mailman's algorithm (per CS360) to
452 FIGURE OUT THE CONVERSION ALGORITHM YOURSELF
453 -------------------------------------------------------------------------
454 Then write a function
455 get_block(blk, buf) int blk; char buf[];
457 //convert blk to (cyl,head,sector);
458 diskr(cyl, head, sector, buf);
460 which will load the disk block into memory at (ES, buf).