⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldlinux.asm

📁 这是Linux环境下的bootsyslinux-1.31版本
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		div bx			; Now we have the size of the root dir		mov [RootDirSize],ax		mov [DirScanCtr],ax		add bx,trackbuf-31		mov [EndofDirSec],bx	; End of a single directory sector		add [DataArea1],ax		adc word [DataArea2],byte 0		pop dx			; Reload root directory starting point		pop ax;; Now the fun begins.  We have to search the root directory for; LDLINUX.SYS and load the first sector, so we have a little more; space to have fun with.  Then we can go chasing through the FAT.; Joy!!;sd_nextsec:	push ax		push dx		mov bx,trackbuf		push bx		call getonesec		pop sisd_nextentry:	cmp byte [si],0		; Directory high water mark		je kaboom		mov di,ldlinux_sys		mov cx,11		push si		repe cmpsb		pop si		je found_it		add si,byte 32		; Distance to next		cmp si,[EndofDirSec]		jb sd_nextentry		pop dx		pop ax		add ax,byte 1		adc dx,byte 0		dec word [DirScanCtr]		jnz sd_nextsec;; kaboom: write a message and bail out.;kaboom:		mov si,bailmsg		call writestr		; Returns with AL = 0		cbw			; Sets AH = 0 (shorter than XOR)		int 16h			; Wait for keypress		mov sp,StackBuf-2*3 	; Reset stack		pop si			; BIOS floppy block address		cli		pop word [si]		; Restore location		pop word [si+2]		sti		int 19h			; And try once more to boot...norge:		jmp short norge		; If int 19h returned; this is the end;; found_it: now we compute the location of the first sector, then;	    load it and JUMP (since we're almost out of space);found_it:	; Note: we actually leave two words on the stack here		; (who cares?)		mov al,[bsSecPerClust]		xor ah,ah		mov bp,ax		; Load an entire cluster		mov bx,[si+26]		; First cluster		push bx			; Remember which cluster it was		dec bx			; First cluster is cluster 2		dec bx		mul bx		add ax,[DataArea1]		adc dx,[DataArea2]		mov bx,ldlinux_magic		push bx		call getlinsec		mov si,bs_magic		pop di		mov cx,magic_len		repe cmpsb		; Make sure that the bootsector		jne kaboom		; matches LDLINUX.SYS		jmp ldlinux_ent;; writestr: write a null-terminated string to the console;writestr:wstr_1:         lodsb		and al,al                jz return		mov ah,0Eh		; Write to screen as TTY		mov bx,0007h		; White on black, current page		int 10h		jmp short wstr_1;; disk_error: decrement the retry count and bail if zero;disk_error:	dec si			; SI holds the disk retry counter		jz kaboom		xchg ax,bx		; Shorter than MOV		pop bx		pop cx		pop dx		jmp short disk_try_again;; getonesec: like getlinsec, but pre-sets the count to 1;getonesec:		mov bp,1		; Fall through to getlinsec;; getlinsec: load a sequence of BP floppy sector given by the linear sector;	     number in DX:AX into the buffer at ES:BX.	We try to optimize;	     by loading up to a whole track at a time, but the user;	     is responsible for not crossing a 64K boundary.;	     (Yes, BP is weird for a count, but it was available...);;	     On return, BX points to the first byte after the transferred;	     block.;getlinsec:		mov si,[bsSecPerTrack]		div si			; Convert linear to sector/track		mov cx,dx		; Save sector		xor dx,dx		; 32-bit track number		div word [bsHeads]	; Convert track to head/cyl		;		; Now we have AX = cyl, DX = head, CX = sector (0-based)		; for the very first sector, SI = bsSecPerTrack		;gls_nexttrack:	push si		push bp		sub si,cx		; Sectors left on track		cmp bp,si		jna gls_lasttrack		mov bp,si		; No more than a trackful, please!gls_lasttrack:	push ax			; Cylinder #		push dx			; Head #		push bp			; Number of sectors we're transferring		push cx		mov cl,6		; Because IBM was STOOPID		shl ah,cl		; and thought 8 bits were enough					; then thought 10 bits were enough...		pop cx			; Sector #		inc cx			; Sector numbers are 1-based		or cl,ah		mov ch,al		mov dh,dl		mov dl,[bsDriveNumber]		xchg ax,bp		; Sector to transfer count					; (xchg shorter than mov)		mov ah,02h		; Read it!;; Do the disk transfer... save the registers in case we fail :(;		mov si,retry_count	; # of times to retry a disk accessdisk_try_again: push dx		push cx		push bx		push ax		push si		int 13h		pop si		pop bx		jc disk_error;; It seems the following test fails on some machines (buggy BIOS?);;		 cmp al,bl		 ; Check that we got what we asked for;		 jne disk_error;; Disk access successful;		pop bx			; Buffer location		pop si			; Not needed anymore		pop si			; Neither is this		pop si			; Sector transferred count		mov ax,si		; Reduce sector left count		mul word [bsBytesPerSec] ; Figure out how much to advance ptr		add bx,ax		; Update buffer location		pop dx			; Head #		pop ax			; Cyl #		inc dx			; Next track on cyl		cmp dx,[bsHeads]	; Was this the last one?		jb gls_nonewcyl		inc ax			; If so, new cylinder		xor dx,dx		; First head on new cylindergls_nonewcyl:	pop bp			; Sectors left to transfer		xor cx,cx		; First sector on new track		sub bp,si		; Reduce with # of sectors just read		pop si		ja gls_nexttrackreturn:		retbailmsg		db 'Boot failed: change disks and press any key', 0Dh, 0Ah, 0bs_checkpt	equ $			; Must be <= 1E5h		zb 1E3h-($-$$)bs_magic	equ $			; The following 32 bytes should					; match ldlinux_magicldlinux_sys	db 'LDLINUX SYS'	; Looks like this in the root dir		db ' 'bs_version	db version_str		db ' 'bs_date		db datemagic_len	equ $-bs_magicbootsignature	dw 0AA55h;; ===========================================================================;  End of boot sector; ===========================================================================;  Start of LDLINUX.SYS; ===========================================================================;; This "magic number" works well with the "type" command... :-);ldlinux_magic	db 'LDLINUX'missing_dot	db ' '		db 'SYS ', version_str, ' ', datemagic_eof	db 0Dh, 0Ah, 01Ah		zb 220h-($-$$)ldlinux_ent:;; The boot sector left the cluster number of this first LDLINUX.SYS; sector on the stack.	We'll need it later, so we should pop it off;		pop word [RunLinClust];; Tell the user we got this far;		mov si,crlf		call writestr		mov byte [missing_dot],'.'		mov byte [magic_eof],0		mov si,ldlinux_magic		call writestr;; Remember, the boot sector loaded only the first cluster of LDLINUX.SYS.; We can really only rely on a single sector having been loaded.  Hence; we should load the FAT into RAM and start chasing pointers...;		mov bx,FAT			; Where it goes in memory		mov ax,[bsHidden1]		; Hidden sectors		mov dx,[bsHidden2]		add ax,[bsResSectors]		; plus reserved sectors = FAT		adc dx,byte 0		mov bp,[bsFATsecs]		; Sectors/FAT		call getlinsec			; Load it in...;; Fine, now we have the FAT in memory.	How big is a cluster, really?; Also figure out how many clusters will fit in an 8K buffer, and how; many sectors and bytes that is;		mov al,[bsSecPerClust]		; We do this in the boot		xor ah,ah			; sector, too, but there		mov [SecPerClust],ax		; wasn't space to save it		mul word [bsBytesPerSec]		mov [ClustSize],ax		; Bytes/cluster		mov bx,ax		mov ax,trackbufsize		xor dx,dx		div bx		mov [BufSafe],ax		; # of cluster in trackbuf		mul word [SecPerClust]		mov [BufSafeSec],ax		mul word [bsBytesPerSec]		mov [BufSafeBytes],ax		add ax,getcbuf			; getcbuf is same size as		mov [EndOfGetCBuf],ax		; trackbuf, for simplicity;; Now we read the rest of LDLINUX.SYS.	Don't bother loading the first; cluster again, though.;		mov bx,ldlinux_magic		add bx,[ClustSize]		mov si,[RunLinClust]		call nextcluster		xor dx,dx		mov ax,ldlinux_len-1		; To be on the safe side		add ax,[ClustSize]		div word [ClustSize]		; the number of clusters		dec ax				; We've already read one		jz all_read_jmp		mov cx,ax		call getfssec;; All loaded up;all_read_jmp:		mov si,copyright_str		call writestr		jmp all_read;; -----------------------------------------------------------------------------; Subroutines that have to be in the first sector; -----------------------------------------------------------------------------;; getfssec: Get multiple clusters from a file, given the starting cluster.;;	This routine makes sure the subtransfers do not cross a 64K boundary,;	and will correct the situation if it does, UNLESS *sectors* cross;	64K boundaries.;;	ES:BX	-> Buffer;	SI	-> Starting cluster number (2-based);	CX	-> Cluster count (0FFFFh = until end of file);						; 386 checkgetfssec:getfragment:	xor bp,bp			; Fragment sector count		mov ax,si			; Get sector address		dec ax				; Convert to 0-based		dec ax		mul word [SecPerClust]		add ax,[DataArea1]		adc dx,[DataArea2]getseccnt:					; See if we can read > 1 clust		add bp,[SecPerClust]		dec cx				; Reduce clusters left to find		mov di,si			; Predict next cluster		inc di		call nextcluster		jc gfs_eof			; At EOF?		jcxz endfragment		; Or was it the last we wanted?		cmp si,di			; Is file continuous?		jz getseccnt			; Yes, we can getendfragment:	clc				; Not at EOFgfs_eof:	pushf				; Remember EOF or not		push si		push cxgfs_getchunk:		push ax		push dx		mov ax,es			; Check for 64K boundaries.		shl ax,1			; This really belongs in		shl ax,1			; getlinsec, but it would		shl ax,1			; make it not fit in the boot		shl ax,1			; sector.		add ax,bx		xor dx,dx		neg ax		jnz gfs_partseg		inc dx				; Full 64K segmentgfs_partseg:		div word [bsBytesPerSec]	; How many sectors fit?		mov si,bp		sub si,ax			; Compute remaining sectors		jbe gfs_lastchunk		mov bp,ax		pop dx		pop ax		push si				; Save remaining sector count		push ax				; Save position		push dx		push bp				; Save sectors to transfer		call getlinsec		pop bp		pop dx		pop ax		add ax,bp			; Advance sector pointer		adc dx,byte 0		pop bp				; Load remaining sector counter		jmp short gfs_getchunkgfs_lastchunk:	pop dx		pop ax				call getlinsec		pop cx		pop si		popf		jcxz gfs_return			; If we hit the count limit		jnc getfragment			; If we didn't hit EOFgfs_return:	ret;; nextcluster: Advance a cluster pointer in SI to the next cluster;	       pointed at in the FAT tables (note: FAT12 assumed);	       Sets CF on return if end of file.;nextcluster:nextcluster_fat12:		push ax		mov ax,si			; Multiply by 3/2		shr ax,1		pushf				; CF now set if odd		add si,ax		mov si,[FAT+si]		popf		jnc nc_even		shr si,1			; Needed for odd only		shr si,1		shr si,1		shr si,1nc_even:		and si,0FFFh		cmp si,0FF0h			; Clears CF if at end of file		cmc				; But we want it SET...		pop axnc_return:	retnextcluster_fat16:		push ax		push es		mov ax,(fat_seg >> 12)		shl si,1		adc ax,byte 0		mov es,ax		mov si,[es:si]		cmp si,0FFF0h		cmc		pop es		pop ax		ret;; Debug routine;%ifdef debugsafedumpregs:		cmp word [Debug_Magic],0D00Dh		jnz nc_return		jmp dumpregs%endif;; Data that has to be in the first sector;copyright_str   db '  Copyright (C) 1994-', year, ' H. Peter Anvin'crlf		db 0Dh, 0Ah, 0rl_checkpt	equ $				; Must be <= 400h; ----------------------------------------------------------------------------;  End of code and data that have to be in the first sector; ----------------------------------------------------------------------------all_read:;; Check that no moron is trying to boot Linux on a 286 or so.  According; to Intel, the way to check is to see if the high 4 bits of the FLAGS; register are either all stuck at 1 (8086/8088) or all stuck at 0; (286 in real mode), if not it is a 386 or higher.  They didn't

⌨️ 快捷键说明

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