boot.asm

来自「GNU FreeDOS兼容MS DOS很好的东东.」· 汇编 代码 · 共 528 行 · 第 1/2 页

ASM
528
字号
;; File:;                            boot.asm; Description:;                           DOS-C boot;;                       Copyright (c) 1997;;                           Svante Frey;                       All Rights Reserved;; This file is part of DOS-C.;; DOS-C is free software; you can redistribute it and/or; modify it under the terms of the GNU General Public License; as published by the Free Software Foundation; either version; 2, or (at your option) any later version.;; DOS-C is distributed in the hope that it will be useful, but; WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See; the GNU General Public License for more details.;; You should have received a copy of the GNU General Public; License along with DOS-C; see the file COPYING.  If not,; write to the Free Software Foundation, 675 Mass Ave,; Cambridge, MA 02139, USA.;;;	+--------+ 1FE0:7E00;	|BOOT SEC|;	|RELOCATE|;	|--------| 1FE0:7C00;	|        |;	|--------| 1FE0:3000;	| CLUSTER|;	|  LIST  |;	|--------| 1FE0:2000;	|        |;	|--------| 0000:7E00;	|BOOT SEC| overwritten by max 128k FAT buffer;	|ORIGIN  | and later by max 134k loaded kernel;	|--------| 0000:7C00;	|        |;	|--------|;	|KERNEL  | also used as max 128k FAT buffer;	|LOADED  | before kernel loading starts;	|--------| 0060:0000;	|        |;	+--------+;%define ISFAT12         1;%define ISFAT16         1segment	.text%define BASE            0x7c00                org     BASEEntry:          jmp     short real_start		nop;       bp is initialized to 7c00h%define bsOemName       bp+0x03      ; OEM label%define bsBytesPerSec   bp+0x0b      ; bytes/sector%define bsSecPerClust   bp+0x0d      ; sectors/allocation unit%define bsResSectors    bp+0x0e      ; # reserved sectors%define bsFATs          bp+0x10      ; # of fats%define bsRootDirEnts   bp+0x11      ; # of root dir entries%define bsSectors       bp+0x13      ; # sectors total in image%define bsMedia         bp+0x15      ; media descrip: fd=2side9sec, etc...%define sectPerFat      bp+0x16      ; # sectors in a fat%define sectPerTrack    bp+0x18      ; # sectors/track%define nHeads          bp+0x1a      ; # heads%define nHidden         bp+0x1c      ; # hidden sectors%define nSectorHuge     bp+0x20      ; # sectors if > 65536%define drive           bp+0x24      ; drive number%define extBoot         bp+0x26      ; extended boot signature%define volid           bp+0x27%define vollabel        bp+0x2b%define filesys         bp+0x36%define LOADSEG         0x0060%define FATBUF          0x2000          ; offset of temporary buffer for FAT                                        ; chain;       Some extra variables;%define StoreSI         bp+3h          ;temp store;       To save space, functions that are just called once are;       implemented as macros instead. Four bytes are saved by;       avoiding the call / ret instructions.;       GETDRIVEPARMS:  Calculate start of some disk areas.;%macro		GETDRIVEPARMS	0                mov     si, word [nHidden]                mov     di, word [nHidden+2]                add     si, word [bsResSectors]                adc     di, byte 0              ; DI:SI = first FAT sector                mov     word [fat_start], si                mov     word [fat_start+2], di                mov     al, [bsFATs]                cbw                mul     word [sectPerFat]       ; DX:AX = total number of FAT sectors                add     si, ax                adc     di, dx                  ; DI:SI = first root directory sector                mov     word [root_dir_start], si                mov     word [root_dir_start+2], di                ; Calculate how many sectors the root directory occupies.                mov     bx, [bsBytesPerSec]                mov     cl, 5                   ; divide BX by 32                shr     bx, cl                  ; BX = directory entries per sector                mov     ax, [bsRootDirEnts]                xor     dx, dx                div     bx                mov     word [RootDirSecs], ax  ; AX = sectors per root directory                add     si, ax                adc     di, byte 0              ; DI:SI = first data sector                mov     [data_start], si                mov     [data_start+2], di%endmacro;-----------------------------------------------------------------------		times	0x3E-$+$$ db 0%define loadsegoff_60	bp+loadseg_off-Entry%define loadseg_60	bp+loadseg_seg-Entry;%define LBA_PACKET      bp+0x42;		db      10h  ; size of packet;		db      0        ; const;		dw      1        ; number of sectors to read%define LBA_PACKET       bp-0x40%define LBA_SIZE       word [LBA_PACKET]%define LBA_SECNUM     word [LBA_PACKET+2]%define LBA_OFF        LBA_PACKET+4%define LBA_SEG        LBA_PACKET+6%define LBA_SECTOR_0   word [LBA_PACKET+8 ]%define LBA_SECTOR_16  word [LBA_PACKET+10]%define LBA_SECTOR_32  word [LBA_PACKET+12]%define LBA_SECTOR_48  word [LBA_PACKET+14]%define PARAMS LBA_PACKET+0x10%define RootDirSecs     PARAMS+0x0         ; # of sectors root dir uses%define fat_start       PARAMS+0x2         ; first FAT sector%define root_dir_start  PARAMS+0x6         ; first root directory sector%define data_start      PARAMS+0x0a        ; first data sector;-----------------------------------------------------------------------;   ENTRY;-----------------------------------------------------------------------real_start:		cli		cld		xor	ax, ax		mov	ds, ax		mov     bp, 0x7c00					; a reset should not be needed here;		int     0x13            ; reset drive;		int	0x12		; get memory available in AX;		mov	ax, 0x01e0;		mov	cl, 6		; move boot sector to higher memory;		shl	ax, cl;		sub	ax, 0x07e0		mov	ax, 0x1FE0		mov	es, ax		mov	si, bp		mov	di, bp		mov	cx, 0x0100		rep	movsw                jmp     word 0x1FE0:contloadseg_off	dw	0loadseg_seg	dw	LOADSEGcont:		mov     ds, ax		mov	ss, ax		lea     sp, [bp-0x60]		sti;; Some BIOS don't pass drive number in DL, so don't use it if [drive] is known;		cmp     byte [drive], 0xff ; impossible number written by SYS		jne     dont_use_dl     ; was SYS drive: other than A or B?		mov     [drive], dl     ; yes, rely on BIOS drive number in DLdont_use_dl:				; no,  rely on [drive] written by SYS		mov     LBA_SIZE, 10h		mov     LBA_SECNUM,1    ; initialise LBA packet constants                call    print                db      "FreeDOS",0                GETDRIVEPARMS;       FINDFILE: Searches for the file in the root directory.;;       Returns:;                               AX = first cluster of file                ; First, read the whole root directory                ; into the temporary buffer.                mov     ax, word [root_dir_start]                mov     dx, word [root_dir_start+2]                mov     di, word [RootDirSecs]                les     bx, [loadsegoff_60] ; es:bx = 60:0                call    readDisk                jc      jmp_boot_error		les     di, [loadsegoff_60] ; es:di = 60:0		; Search for KERNEL.SYS file name, and find start cluster.next_entry:     mov     cx, 11                mov     si, filename                push    di                repe    cmpsb                pop     di                mov     ax, [es:di+0x1A]; get cluster number from directory entry                je      ffDone                add     di, byte 0x20   ; go to next directory entry                cmp     byte [es:di], 0	; if the first byte of the name is 0,                jnz     next_entry	; there is no more files in the directory                jc      boot_error	; fail if not foundffDone:                push    ax              ; store first cluster number;                call    print;                db      " FAT",0

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?