书承上文:http://www.cnblogs.com/long123king/p/3549267.html
我们找一份Lilo的源码来看一下
http://freecode.com/projects/lilo
ftp://metalab.unc.edu/pub/Linux/system/boot/lilo/lilo-22.8.src.tar.gz
first.S就是写到MBR中的,我们刚刚分析了一部分的汇编代码文件
#if 0
2: ; first.S - LILO first stage boot loader with LBA32 support */
3: Copyright 1992-1998 Werner Almesberger.
4: Copyright 1999-2005 John Coffman.
5: All rights reserved.
6:
'COPYING' in the
8: source directory.
9:
#endif
#define LILO_ASM
14:
#define DEBUG 0
16:
#if VERSION_MINOR>=50
18: # define DEBUG_NEW
19:
20: # undef VIDEO_ENABLE
21: # define VIDEO_ENABLE 3
22:
/* adds 0Dh bytes */
/* adds 5h bytes */
/* subs 8h bytes */
/* adds 1h byte */
27:
if DEBUG
29: # define DEBUG_LARGE
30: # endif
#else
32:
/* adds 0Dh bytes */
/* adds 5h bytes */
/* subs 8h bytes */
/* adds 1h byte */
#endif
38:
39:
for those systems that disable the video on boot
41: ! = 0 first stage does not enable video
42: ! = 1 use get vid mode/set vid mode to enable
43: ! = 2 use VGA enable call to enable video
44: ! (cannot use, as code gets too big)
45: ! = 3 use direct mode set (mode 3, CGA, EGA, VGA)
46: ! = 7 use direct mode set (mode 7, MDA)
47: !
#ifndef VIDEO_ENABLE
if VALIDATE==0
50: # define VIDEO_ENABLE 2
else
52: # define VIDEO_ENABLE 2
53: # endif
#endif
55:
do not change the following -- it must correspond to the code in bsect.c
#define RELOCATABLE -1
58:
59:
60: .text
61:
62: .globl _main
63:
64: .org 0
65:
66: zero:
this is missing
68: jmp start
69:
70: stage: .byte STAGE_FIRST
71: .org 4
72: reloc:
#if RELOCATABLE
74: .word theend-zero ! size of the code & params
#else
76: .word 0 ! no size indication
#endif
78: .org 6
79:
80: ! Boot device parameters. They are set by the installer.
81:
83: vers: .word VERSION
long 0 ! map timestamp
85:
for the stage 1 vs stage 2 comparison
87:
long 0 ! raid sector offset
long 0 ! timestamp
long 0 ! volume S/N containing map file
91: prompt: .word 0 ! indicates whether to always enter prompt
92: ! contains many other flags, too
93:
94: d_dev: .byte 0x80 ! map file device code
95: d_flag: .byte 0 ! disk addressing flags
long 0 ! disk addr of second stage index sector
97:
98:
99: edd_packet = 0
100: ;;; .word 16 ! size of packet
101: ;;; .word 1 ! count of bytes to read
102:
103: edd_addr = 4
104: ;;; .word map2 ! where to read
105: ;;; .word *-* ! segment where to read
106:
107: edd_d_addr = 8
long 1 ! low address or CX,DX (geometric)
for search in geo mode
110:
long 0 ! hi address
112:
#if 0
114: ! These locations are referenced as EX_OFF
115: ! (they used to be at CODE_START_1)
116: ext_si: .word 0 ! external interface
117: ext_es: .word 0 ! these locations are referenced in second.S
do not disturb the ordering
this magic number
120: ext_dh: .byte 0 ! not referenced, but must align stack
121: ext_stack:
#endif
123:
/***************************************************/
125: ! The following instruction MUST be
short
127: ! at the start of the file; otherwise
128: ! the boot sector relocation fails.
129: !
130: start:
131: mov ax,#BOOTSEG ! use DS,ES,SS = 0x07C0
/***************************************************/
133:
134: mov ss,ax
for First Stage
136: sti ! now it is safe
137:
138: push dx ! set ext_dl (and ext_dh, which is not used)
139: push bx ! WATCH the order of pushes
140: push es ! set ext_es
141: push si ! set ext_si
142:
#ifdef DEBUG_NEW
144: push ds
145: push es ! just not enough space with debug turned on
#endif
147:
#define JRC_DS_EQ_SS
149:
this !!!
151: mov ds,ax ! address data area
152: xor bp,bp ! shorted addressing
153:
#if VIDEO_ENABLE
155: ! a BIOS has been found where the video interrupt (0x10) trashes DX
156: ! so, we had better be very paranoid about DX
157: !
if VIDEO_ENABLE==2
159: pusha ! protect DX
160: # endif
if VIDEO_ENABLE > 2
162: mov ax,#VIDEO_ENABLE ! set video mode 3 or 7
163: # elif VIDEO_ENABLE==1
164: mov ah,#15 ! get video mode
int 0x10
166: cbw
/* VIDEO_ENABLE==2 */
168: mov ax,#0x1200 ! enable video (VGA)
169: mov bl,#0x36 ! (probably a nop on EGA or MDA)
170: # endif
int 0x10 ! video call
if VIDEO_ENABLE==2
173: popa ! restore DX
174: # endif
#endif
176:
#if (VIDEO_ENABLE&1) == 0
178: mov al,#0x0d ! gimme a CR ...
179: call display
for trashing DX on one BIOS:
181: mov al,#0x0a ! ... an LF ...
182: call display
#endif
184:
#if defined(DEBUG_NEW)
186: mov ah,dl
187: call bout ! code in AH
#endif
'L' ...
190: call display
191:
192: lagain:
for restart
194:
195: push ds
196: pop es ! use buffer at end of boot sector
197:
198: cmp dl,#EX_DL_MAG ! possible boot command line (chain.S)
199: jne boot_in_dl
200: mov dl,dh ! code passed in DH instead
201: boot_in_dl:
202:
for volume search
204: mov dh,[d_dev](bp) ! map device to DH
205:
#if VALIDATE
207: mov ax,dx ! copy device code to AL
208: and ah,#0x80 ! AH = 00 or 80
209: xor al,ah ! hi-bits must be the same
210: js use_installed
211: cmp al,#MAX_BIOS_DEVICES ! limit the device code
if DL is not valid
#endif
214:
if so marked; viz.,
216:
217: test byte ptr [prompt](bp),#FLAG_MAP_ON_BOOT
218: jnz use_boot ! as passed in from BIOS or MBR loader
219:
220: use_installed:
221: mov dl,dh ! device code to DL
for
223: or esi,esi
224: jz done_search
225:
226: push dx ! save flags
227:
228: mov ah,#8 ! get number of hard disks
229: mov dl,#0x80
230: push bx ! paranoia
int 0x13
232: pop bx
233: jc error
234:
235: movzx cx,dl ! extend to word in CX
236:
#if GEOMETRIC
238: mov dx,#0x80-1 ! device 80, flags=0
#else
240: mov dx,#LBA32_FLAG*256+0x80-1 ! device 80, flags=LBA32
#endif
242:
243: vagain:
244: inc dx
245: xor eax,eax
#if GEOMETRIC
247: inc ax ! geometric addressing
#endif
249: call disk_read ! read
250:
251: cmp esi,[PART_TABLE_OFFSET-6](bx)
252: je vol_found
253: loop vagain
254:
255: pop dx ! restore specified BIOS code
this point
257:
258: vol_found:
259: ! uses value in DX, stack may have extra value
260:
261: done_search:
262: use_boot:
for later
264:
265: mov dh,[d_flag](bp) ! get device flags to DH
266: mov si,#d_addr
267: call pread ! increments BX
268:
269: mov ah,#0x99 ! possible error code
271: jne error
272:
273: pop si ! point at #map2
274:
#if 1
276: push #SETUP_STACKSIZE/16 + BOOTSEG + SECTOR_SIZE/16*2
277: pop es
#else
279: mov ax,ds ! get segment
280: add ax,#SETUP_STACKSIZE/16 ! + SECTOR_SIZE/16*2
281: mov es,ax
#endif
283: xor bx,bx
284:
285: sload:
using map at DS:SI
auto increment)
288:
289: ! Verify second stage loader signature
290:
291: mov si,#sig ! pointer to signature area
292: mov di,si
293: mov cx,#length ! number of bytes to compare
294: mov ah,#0x9A ! possible error code
295: repe
296: cmpsb ! check Signature 1 & 2
297: jne error ! check Signature 2
298:
#if SECOND_CHECK
/* it would be nice to re-incorporate this check */
do not touch AH (error code)
302: scasb
303: jne error
#endif
305:
306: ! Start the second stage loader DS=location of Params
307:
308: push es ! segment of second stage
309: push bp ! BP==0
310:
'I'
312: call display
313:
314: retf ! Jump to ES:BP
315:
316:
317:
318:
319: disk_error2:
320: mov ah,#0x40 ; signal seek error
321:
return from error
323: error:
324:
#ifndef LCF_NO1STDIAG
326: mov al,#32 ! display a space
327: call display0
328:
329: call bout
#endif
331:
#ifndef DEBUG_LARGE
333: dec byte [zero](bp) ! CLI == 0xFA == 250
334: jz zzz
335:
#ifndef DEBUG_NEW
for First Stage
#else
for First Stage
#endif
for restart
342: jmp near lagain ! redo from start
#endif
344:
345:
346: zzz:
#ifndef DEBUG_NEW
348: hlt
#endif
for Ctrl-Alt-Del
351:
352:
353:
354:
355: ! packet read routine
356:
357: disk_read:
#ifndef JRC_DS_EQ_SS
359: push ds
#endif
361: pusha
362:
#ifndef JRC_DS_EQ_SS
364: push ss
365: pop ds
#endif
367:
368: push bp ! BP==0
369: push bp ! BP==0
370:
371: push eax ! low order disk address
#ifdef DEBUG_LARGE
373: xchg ax,dx
374: call wout
375: xchg ax,dx
376: call dout ! print out disk address
#endif
378: push es ! memory segment ES
379: push bx ! memory offset BX
380: push #1 ! sector count
381: push #16 ! size of packet = 16 bytes
382: mov si,sp ! address of packet DS:SI
383:
384: push bx
385:
386: test dh,#LINEAR_FLAG|LBA32_FLAG
387: jz disk_geometric
388:
389: test dh,#LBA32_FLAG
390: jz disk_convert ; it must be LINEAR
391:
392: mov bx,#0x55AA ;magic number
393: mov ah,#0x41
int 0x13
395: jc disk_convert
396: cmp bx,#0xAA55 ;changed?
397: jne disk_convert
398: test cl,#EDD_PACKET ;EDD packet calls supported
399: jnz disk_edd
400:
401: disk_convert:
402: push dx
403: push es ! protect on floppies
404: mov ah,#8 ! get geometry
int 0x13
406: pop es
407: disk_error3: ! transfer through on CF=1
408: jc error ! disk_error12
409:
#if !CYL1023
411: push cx
412: shr cl,#6 ;;;;
413: xchg cl,ch ;CX is max cylinder number
414: mov di,cx ;DI saves it
415: pop cx
#endif
417: shr dx,#8
418: xchg ax,dx ;AX <- DX
419: inc ax ;AX is number of heads (256 allowed)
420:
for Davide BIOS bug
422: dec cx ; 1..63 -> 0..62; 0->63
423: and cx,#0x003f ;CX is number of sectors
424: inc cx ; allow Sectors==0 to mean 64
425:
426: mul cx ; kills DX also
427: xchg ax,bx ;save in BX
428:
429: mov ax,[edd_d_addr](si) ;low part of address
430: mov dx,[edd_d_addr+2](si) ;hi part of address
431:
432: cmp dx,bx
433: jae disk_error2 ;prevent division error
434:
435: div bx ;AX is cyl, DX is head/sect
#if CYL1023
437: cmp ax,#1023
#else
439: cmp ax,di
#endif
441: ja disk_error2 ;cyl is too big
442:
443: shl ah,#6 ; save hi 2 bits
444: xchg al,ah
445: xchg ax,dx
446: div cl ;AH = sec-1, AL = head
447: or dl,ah ;form Cyl/Sec
448: mov cx,dx
449: inc cx ; sector is 1 based
450:
451: pop dx ! restore device code
452: mov dh,al ! set head#
453: jmp disk_read2
454:
455:
456:
457: disk_edd:
458: mov ah,#0x42
459: disk_int13:
460: pop bx
461:
462: mov bp,#5
463: disk_retry:
464: pusha
int 0x13
#if 0
467: stc
468: mov ah,#0x9C
#endif
470: jnc disk_okay
471:
472: dec bp ! does not alter CF, already 0
with CF=1 & ZF=1
474:
475: xor ax,ax ! reset the disk controller
int 0x13
477: popa ! reset AX,BX,CX,DX,SI
478: dec bp ! fix up BP count
479: jmp disk_retry
480:
481:
482: disk_geometric:
483: push eax
484: pop cx
485: pop ax
486: mov dh,ah
487:
488: disk_read2:
489: mov ax,#0x201 ;read, count of 1
490: jmp disk_int13
491:
492:
493: disk_okay:
494: ; the pusha block is implicitly removed below
495: ;;; mov (si+2*16-1),ah ! set error code
496: ; the error code is never checked
do not touch carry;
498: popa
#ifndef JRC_DS_EQ_SS
500: pop ds
#endif
502: ret
503:
504:
505:
using pointer in DS:SI
507:
508: pread:
509: lodsd ! get address
510: or eax,eax
511: jz done
512: add eax,[raid](bp) ! reloc is 0 on non-raid
513: call disk_read
514:
515: add bh,#SECTOR_SIZE/256 ! next sector
516: done:
517: ret
518:
519:
520:
521:
#if !defined(LCF_NO1STDIAG) || defined(DEBUG_NEW)
523: bout: rol ax,#4 ! bring hi-nibble to position
524: call nout
525: rol ax,#4 ! bring lo-nibble to position
526: nout: and al,#0x0F ! display one nibble
527: daa ! shorter conversion routine
528: add al,#0xF0
char 0..9A..F
#endif
531: ; display - write byte in AL to console
register contents
533: ;
534: display0:
#ifndef LCF_NOVGA
536: display:
#endif
register is changed
539: mov bx,#7 ! BH=0, BL=07
540: mov ah,#14
int 0x10
542: popa ! restore all the registers
#ifdef LCF_NOVGA
544: display:
#endif
546: ret
547:
#ifdef DEBUG_LARGE
549:
550: dout: pushad
551: ror eax,#16
552: call wout
553: ror eax,#16
554: call wout
555: mov al,#0x20 ! space
556: call display
557: popad
558: ret
559:
560: wout: push ax
561: call bout ! put out AH
562: pop ax
563: push ax
564: xchg al,ah
565: call bout ! put out AL (now in AH)
566: pop ax
567: ret
#endif
569:
570: theend:
571:
572: !
for the partition
'first' loads as the boot record of some partition, then
575: ! the space reserved below is not used. But we must reserve the area
case.
577: !
578: !
579: .org MAX_BOOT_SIZE !
for NT, DRDOS, and LiLO volume S/N
581:
for the partition table
583: p_table:
584: .blkb 16
585: .blkb 16
586: .blkb 16
587: .blkb 16
#ifdef FIRST
589: .org *-2
long FIRST ! boot block check
#else
592: .word 0xAA55 ! boot block signature
#endif
594:
595: ! Better be exactly 0x200
596:
597: map2 equ * ! addressed as ES:[map2]