3 Lab Assignment #2 : loader
4 DUE : Week of Jan 23, 2012
7 A simple extension of the MTX booter is a loader, which loads an a.out file
8 into memory for execution. A loader is an essential (utility) function of an
12 Assume bs.s and bc.c are assembly and C source files. Under BCC,
14 ld86 -s bs.o bc.o /usr/lib/bcc/lic.a
16 generates an a.out file consisting of the following parts.
18 |header|Code|Data|...bss.....|
20 where bss is NOT in a.out but its size is recorded in the header.
22 The 32-byte header is composed of 8 longs.
24 0 0x04100301 //(combined I,D space) or 0x04200301=(separate I,D space)
26 2 text size // code size
27 3 data size // initialized data size
28 4 bss size // uninitialized data size ==> cleared to 0
30 6 total memory // ignore this field
31 7 symbolTable size // symbol Table size
33 If a.out has a combined I (Instruction) and D (Data) space, its code segment
34 and data+stack segment are all the same, i.e. CS,DS,and SS must be the same
35 segment during execution. This also means that the entire memory image must
36 be no greater than 64KB. ld86 -i generates a.out with separate I and D
37 spaces, in which case the code segment and data+stack segment will be
38 different, allowing a memory image of 128KB (64KB code segment and 64KB
42 To execute a.out, the loader first reads the file header to determine
44 totalMemorySize = tsize + dsize + bsize + (initial)stack_size
46 where the initial stack_size can be a default value, say 8KB, assuming
47 it can be expanded (if necessary) during execution. If the memory image of
48 a loaded a.out cannot be changed, then a max. default stack_size is usually
49 used. Then the loader allocates the needed memory space by
51 ushort segment = OSmalloc(totalMemorySize);
53 where OSmalloc() is the memroy manager of the OS.
55 Then, the loader loads the |code|data| of a.out into memory (starting at
56 segment) and clears the bss section to 0 (so that all the uninitialized
57 globals start with 0 value). Finally, the OS sends CPU to segment to execute
60 3. LAB2. Specification:
61 Implement a loader that loads an a.out file to memory and execute it.
64 4-1. YOUR MTX booter as in Lab #1. It boots /boot/mtx to the segment 0x1000.
66 4-2. Instead of the real MTX, we shall use a S(Simple)OS generated by the
67 following ts.s and tc.c files.
69 -------------------------------------------------
72 ld86 -d ts.o tc.o /usr/lib/bcc/lic.a
74 cp a.out /fd0/boot/sos (you may name it mtx)
76 -------------------------------------------------
78 (1). ts.s file of SOS:
80 .globl begtext, begdata, begbss ! needed by linker
82 .globl _getc,_putc,_diskr,_setes,_inces,_error ! EXPORT
83 .globl _get_byte,_put_byte, _go ! EXPORT
84 .globl _main,_prints ! IMPORT these
86 .text ! these tell as:
87 begtext: ! text,data,bss segments
88 .data ! are all the same.
95 mov ax,cs ! set segment registers for CPU
96 mov ds,ax ! we know CS=0x1000. Let DS=ES=CS
98 mov ss,ax ! SS = CS ===> all point at 0x1000
100 mov sp,#0 ! SP = 64KB, at 0x2000
102 call _main ! call main() in C
107 !---------------------------------------
108 ! diskr(cyl, head, sector, buf) all count from 0
110 !---------------------------------------
113 mov bp,sp ! bp = stack frame pointer
115 movb dl, #0x00 ! drive 0=FD0
116 movb dh, 6[bp] ! head
117 movb cl, 8[bp] ! sector
118 incb cl ! inc sector by 1 to suit BIOS
120 mov bx, 10[bp] ! BX=buf ==> memory addr=(ES,BX)
121 mov ax, #0x0202 ! READ 2 sectors to (EX, BX)
123 int 0x13 ! call BIOS to read the block
124 jb _error ! to error if CarryBit is on [read failed]
129 !------------------------------
131 !------------------------------
139 bad: .asciz "Error!\n\r"
141 !======================== I/O functions =================================
143 !---------------------------------------------
144 ! char getc() function: returns a char
145 !---------------------------------------------
147 xorb ah,ah ! clear ah
148 int 0x16 ! call BIOS to get a char in AX
151 !----------------------------------------------
152 ! void putc(char c) function: print a char
153 !----------------------------------------------
158 movb al,4[bp] ! get the char into aL
159 movb ah,#14 ! aH = 14
160 movb bl,#0x0B ! bL = CYAN color
161 int 0x10 ! call BIOS to display the char
175 _inces: ! inces() inc ES by 0x40, or 1K
191 opcode: .byte 0xEA ! jmpi
193 segment: .word 0 ! segment
196 !*===========================================================================*
198 !*===========================================================================*
199 ! c = get_byte(segment, offset)
202 mov bp,sp ! stack frame pointer
205 mov es,4[bp] ! load es with segment value
206 mov bx,6[bp] ! load bx with offset from segment
207 seg es ! go get the byte
208 movb al,[bx] ! al = byte
209 xorb ah,ah ! ax = byte
213 ret ! return to caller
215 !*===========================================================================*
217 !*===========================================================================*
218 ! put_byte(char,segment,offset)
221 mov bp,sp ! stack frame pointer
225 mov es,6[bp] ! load es with seg value
226 mov bx,8[bp] ! load bx with offset from segment
227 movb al,4[bp] ! load byte in aL
228 seg es ! go put the byte to [ES, BX]
229 movb [bx],al ! there it goes
234 ret ! return to caller
239 (2). tc.c file of SOS:
241 #include "ext2.h" // EXT2 INODE, DIR struct types
242 #include "io.c" // YOUR printf() with "%c %s %d %x %l\n";
243 #include "loader.c" // YOUR loader.c file
250 printf("\nSimple OS running\n");
252 printf("enter filename to execute : ");
254 segment = 0x2000; // choose a free segment
255 if (load(filename, segment)){
256 printf("jmp to segment %s\n", segment\n");
260 printf("exec ERROR : file not found\n");
267 (3). The executable file /bin/u1 is generated by
268 --------------------------------------------------
271 ld86 -s us.o uc.o /usr/lib/bcc/libc.a
275 --------------------------------------------------
279 .globl begtext, begdata, begbss ! needed by linker
281 .globl _getc,_putc ! EXPORT
282 .globl _main,_prints ! IMPORT these
284 .text ! these tell as:
285 begtext: ! text,data,bss segments
286 .data ! are all the same.
293 mov ax,cs ! set segment registers for CPU
294 mov ds,ax ! we know CS=segment. Let DS=SS
296 mov ss,ax ! SS = CS ===> all point at segment
297 mov sp,#0 ! SP = 64KB
299 call _main ! call main() in C
301 gomtx: jmpi 0, 0x1000 ! jmp back to SOS at 0x1000
304 !---------------------------------------------
305 ! char getc() function: returns a char
306 !---------------------------------------------
308 xorb ah,ah ! clear ah
309 int 0x16 ! call BIOS to get a char in AX
312 !----------------------------------------------
313 ! void putc(char c) function: print a char
314 !----------------------------------------------
319 movb al,4[bp] ! get the char into aL
320 movb ah,#14 ! aH = 14
321 movb bl,#0x0C ! bL = RED color
322 int 0x10 ! call BIOS to display the char
330 #include "io.c" // YOUR gets(), printf(), etc.
337 printf("\nThis is u1 running\n");
339 printf("what's your name? : ");
341 if (strcmp(name, "quit")==0){
342 printf("quit : go back to OS at 0x1000\n");
345 printf("Welcome %s\n", name);
350 ===========================================================================
351 In ~samples/LAB2/ sosimage.bin is a diskimage of a bootable sos system.
352 Download and dump it to a floppy disk. Boot up SOS and try to run it.
353 You only need to replace the booter with YOUR booter from Lab#1
354 AND generate YOUR SOS with YOUR loader.c and io.c files.
355 ===========================================================================
358 1. Develop your own printf(fmt) function, which can print with
359 fmt = "....%c...%s ...%d ... %x ...%l ...\n"
361 2. Use get_byte()/put_byte() to implement YOUR own
363 ushort get_word(segment, offset) ushort segment, offset;
364 int put_word(word, segment, offset) ushort word,segment,offset;
366 functions in C for read/write a word from/to memory (segment,offset).
369 3. Implement YOUR loader.c
371 load(pathname, segment) char *pathname; ushort segment;
373 1. break up pathname into tokens:
374 /a/b/c/d ==> "a", "b", "c", "d" with n=4
376 2. locate the inode of /a/b/c/d: let ip->INODE of file
377 return 0 if can't find the file
379 3. read file header to get size information;
380 print tsize, dsize, bsize
382 3. load a.out data blocks (with header) into segment.
383 move the executable part (|code|dat|....) upward 32 bytes to
384 eliminate the header.
386 4. Clear bss section (after |code|data|) to 0.
388 5. return 1 for success.