* cormen book
[mascara-docs.git] / i86 / mtx-16-bit / docs / 05-link-loader.txt
blobf2547546c3e7ac9581256d00907adc5eb39cdc3f
1 460 Lab Assignment #2
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
9 operating system.
11 1. a.out file format:
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)
25         1 0x00000020
26         2 text size  // code size
27         3 data size  // initialized data size
28         4 bss  size  // uninitialized data size ==> cleared to 0
29         5 0x00000000
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
39    data+stack segment).
41 2. The loader
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
58    a.out.
60 3. LAB2. Specification:
61    Implement a loader that loads an a.out file to memory and execute it.
63 4. HELP Files:
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 -------------------------------------------------
70 bcc  -c tc.c
71 as86 -o ts.o ts.s
72 ld86 -d ts.o tc.o /usr/lib/bcc/lic.a
73 mount /dev/fd0 /fd0
74 cp a.out /fd0/boot/sos   (you may name it mtx)
75 umount /fd0
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.
89 begdata:
90 .bss
91 begbss:
92 .text
94 start:
95         mov     ax,cs                   ! set segment registers for CPU
96         mov     ds,ax                   ! we know CS=0x1000. Let DS=ES=CS
97         mov     es,ax                   ! 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
104 dead:   jmp   dead
107        !---------------------------------------
108        ! diskr(cyl, head, sector, buf)  all count from 0
109        !        4     6     8      10
110        !---------------------------------------
111 _diskr:
112         push  bp
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
119         movb  ch, 4[bp]        ! cyl
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]
126         pop  bp
127         ret
129         !------------------------------
130         !       error & reboot
131         !------------------------------
132 _error:
133         mov  bx, #bad
134         push bx
135         call _prints
137         int  0x19                       ! reboot
139 bad:    .asciz  "Error!\n\r"
141 !======================== I/O functions =================================
143         !---------------------------------------------
144         !  char getc()   function: returns a char
145         !---------------------------------------------
146 _getc:
147         xorb   ah,ah           ! clear ah
148         int    0x16            ! call BIOS to get a char in AX
149         ret
151         !----------------------------------------------
152         ! void putc(char c)  function: print a char
153         !----------------------------------------------
154 _putc:
155         push   bp
156         mov    bp,sp
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
163         pop    bp
164         ret
166 _setes:  push  bp
167          mov   bp,sp
169          mov   ax,4[bp]
170          mov   es,ax
172          pop   bp
173          ret
175 _inces:                         ! inces() inc ES by 0x40, or 1K
176          mov   ax,es
177          add   ax,#0x40
178          mov   es,ax
179          ret
181 _go:  ! go(segment)
182         push   bp
183         mov    sp,bp
184         mov    ax,4[bp]
185         mov    segment,ax
189 ! jmpi   0, segment
191 opcode:    .byte  0xEA     ! jmpi
192            .word  0        ! offset
193 segment:   .word  0        ! segment
196 !*===========================================================================*
197 !*                              get_byte                                     *
198 !*===========================================================================*
199 ! c = get_byte(segment, offset)
200 _get_byte:
201         push bp                 ! save bp
202         mov bp,sp               ! stack frame pointer
203         push es                 ! save es
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
211         pop es                  ! restore es
212         pop bp                  ! restore bp
213         ret                     ! return to caller
215 !*===========================================================================*
216 !*                              put_byte                                     *
217 !*===========================================================================*
218 ! put_byte(char,segment,offset)
219 _put_byte:
220         push bp                 ! save bp
221         mov  bp,sp              ! stack frame pointer
222         push es                 ! save es
223         push bx
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
231         pop  bx                 ! restore bx
232         pop  es                 ! restore es
233         pop  bp                 ! restore bp
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
245 char filename[64];
246 ushort segment;
248 main()
250   printf("\nSimple OS running\n");
251   while(1){
252     printf("enter filename to execute : ");
253     gets(filename);
254     segment = 0x2000;  // choose a free segment
255     if (load(filename, segment)){
256       printf("jmp to segment %s\n", segment\n");
257       go(segment);
258     }
259     else{
260       printf("exec ERROR : file not found\n");
261     }
262   }
267 (3). The executable file /bin/u1 is generated by
268 --------------------------------------------------
269 bcc  -c uc.c
270 as86 -o us.o us.s
271 ld86 -s us.o uc.o /usr/lib/bcc/libc.a
272 mount /dev/fd0 /fd0
273 cp a.out /fd0/bin/u1
274 umount /fd0
275 --------------------------------------------------
277 3-1. us.s file
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.
287 begdata:
288 .bss
289 begbss:
290 .text
292 start:
293         mov     ax,cs                   ! set segment registers for CPU
294         mov     ds,ax                   ! we know CS=segment. Let DS=SS
295         mov     es,ax                   ! ES = CS
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         !---------------------------------------------
307 _getc:
308         xorb   ah,ah           ! clear ah
309         int    0x16            ! call BIOS to get a char in AX
310         ret
312         !----------------------------------------------
313         ! void putc(char c)  function: print a char
314         !----------------------------------------------
315 _putc:
316         push   bp
317         mov    bp,sp
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
324         pop    bp
325         ret
328 3-2 uc.c file
330 #include "io.c"   // YOUR gets(), printf(), etc.
332 main()
334   char name[64];
335   ushort segment;
337   printf("\nThis is u1 running\n");
338   while(1){
339     printf("what's your name? : ");
340     gets(name);
341     if (strcmp(name, "quit")==0){
342        printf("quit : go back to OS at 0x1000\n");
343        return;
344     }
345     printf("Welcome %s\n", name);
347   }
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 ===========================================================================
356 Programming Tasks:
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;
372    {
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.