This is the assembly source for the boot sector used by the Linux free operating system. If it looks unfamiliar for intel assembly, that's because it gets run through the standard C preprocessor (CPP) and has comments starting with '!' stripped off... enjoy! :)
! ! SYS_SIZE is the number of clicks (16 bytes) to be loaded. ! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current ! versions of linux which compress the kernel ! #include <linux/config.h> SYSSIZE = DEF_SYSSIZE ! ! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds ! modified by Drew Eckhardt ! modified by Bruce Evans (bde) ! ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves ! itself out of the way to address 0x90000, and jumps there. ! ! bde - should not jump blindly, there may be systems with only 512K low ! memory. Use int 0x12 to get the top of memory, etc. ! ! It then loads 'setup' directly after itself (0x90200), and the system ! at 0x10000, using BIOS interrupts. ! ! NOTE! currently system is at most (8*65536-4096) bytes long. This should ! be no problem, even in the future. I want to keep it simple. This 508 kB ! kernel size should be enough, especially as this doesn't contain the ! buffer cache as in minix (and especially now that the kernel is ! compressed :-) ! ! The loader has been made as simple as possible, and continuous ! read errors will result in a unbreakable loop. Reboot by hand. It ! loads pretty fast by getting whole tracks at a time whenever possible. .text SETUPSECS = 4 ! nr of setup-sectors BOOTSEG = 0x07C0 ! original address of boot-sector INITSEG = DEF_INITSEG ! we move boot here - out of the way SETUPSEG = DEF_SETUPSEG ! setup starts here SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536). ! ROOT_DEV & SWAP_DEV are now written by "build". ROOT_DEV = 0 SWAP_DEV = 0 #ifndef SVGA_MODE #define SVGA_MODE ASK_VGA #endif #ifndef RAMDISK #define RAMDISK 0 #endif #ifndef CONFIG_ROOT_RDONLY #define CONFIG_ROOT_RDONLY 1 #endif ! ld86 requires an entry symbol. This may as well be the usual one. .globl _main _main: #if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */ int 3 #endif mov ax,#BOOTSEG mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub si,si sub di,di cld rep movsw jmpi go,INITSEG ! ax and es already contain INITSEG go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of ! bootsect + length of setup + room for stack ! 12 is disk parm size ! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We ! wouldn't have to worry about this if we checked the top of memory. Also ! my BIOS can be configured to put the wini drive tables in high memory ! instead of in the vector table. The old stack might have clobbered the ! drive table. mov ds,ax mov ss,ax ! put stack at INITSEG:0x4000-12. mov sp,di /* * Many BIOS's default disk parameter tables will not * recognize multi-sector reads beyond the maximum sector number * specified in the default diskette parameter tables - this may * mean 7 sectors in some cases. * * Since single sector reads are slow and out of the question, * we must take care of this by creating new parameter tables * (for the first disk) in RAM. We will set the maximum sector * count to 36 - the most we will encounter on an ED 2.88. * * High doesn't hurt. Low does. * * Segments are as follows: ds=es=ss=cs - INITSEG, * fs = 0, gs is unused. */ ! cx contains 0 from rep movsw above mov fs,cx mov bx,#0x78 ! fs:bx is parameter table address push ds seg fs lds si,(bx) ! ds:si is source mov cl,#6 ! copy 12 bytes cld push di rep movsw pop di pop ds movb 4(di),*36 ! patch sector count seg fs mov (bx),di seg fs mov 2(bx),es ! load the setup-sectors directly after the bootblock. ! Note that 'es' is already set up. ! Also cx is 0 from rep movsw above. load_setup: xor ah,ah ! reset FDC xor dl,dl int 0x13 xor dx, dx ! drive 0, head 0 mov cl,#0x02 ! sector 2, track 0 mov bx,#0x0200 ! address = 512, in INITSEG mov ah,#0x02 ! service 2, nr of sectors mov al,setup_sects ! (assume all on head 0, track 0) int 0x13 ! read it jnc ok_load_setup ! ok - continue push ax ! dump error code call print_nl mov bp, sp call print_hex pop ax jmp load_setup ok_load_setup: ! Get disk drive parameters, specifically nr of sectors/track #if 0 ! bde - the Phoenix BIOS manual says function 0x08 only works for fixed ! disks. It doesn't work for one of my BIOS's (1987 Award). It was ! fatal not to check the error code. xor dl,dl mov ah,#0x08 ! AH=8 is get drive parameters int 0x13 xor ch,ch #else ! It seems that there is no BIOS call to get the number of sectors. Guess ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, ! 15 if sector 15 can be read. Otherwise guess 9. mov si,#disksizes ! table of sizes to try probe_loop: lodsb cb