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

📄 ldlinux.asm

📁 Windows上的精简Linux系统
💻 ASM
📖 第 1 页 / 共 3 页
字号:
		call getlinsec		mov si,bs_magic		mov di,ldlinux_magic		mov cx,magic_len		repe cmpsb		; Make sure that the bootsector		jne kaboom		; matches LDLINUX.SYS;; Done! Jump to the entry point!;		jmp ldlinux_ent;;; writestr: write a null-terminated string to the console;	    This assumes we're on page 0.  This is only used for early;           messages, so it should be OK.;writestr:.loop:		lodsb		and al,al                jz .return		mov ah,0Eh		; Write to screen as TTY		mov bx,0007h		; Attribute		int 10h		jmp short .loop.return:	ret;; disk_error: decrement the retry count and bail if zero.;	      This gets patched once we have more space to try to;             optimize transfer sizes on broken machines.;disk_error:	dec si			; SI holds the disk retry counter		jz kaboom		; End of patched "call" instruction!		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 EAX 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.;;	     The "stupid patch area" gets replaced by the code;	     mov bp,1 ; nop ... (BD 01 00 90 90...) when installing with;	     the -s option.;;            This routine assumes CS == DS.;; Stylistic note: use "xchg" instead of "mov" when the source is a register; that is dead from that point; this saves space.  However, please keep; the order to dst,src to keep things sane.;getlinsec:		mov esi,[bxSecPerTrack]		;		; Dividing by sectors to get (track,sector): we may have		; up to 2^18 tracks, so we need to use 32-bit arithmetric.		;		xor edx,edx		; Zero-extend LBA to 64 bits		div esi		xor cx,cx		xchg cx,dx		; CX <- sector index (0-based)					; EDX <- 0		; eax = track #		div dword [bxHeads]	; Convert track to head/cyl		;		; Now we have AX = cyl, DX = head, CX = sector (0-based),		; BP = sectors to transfer, SI = bsSecPerTrack,		; ES:BX = data target		;gls_nextchunk:	push si			; <A> bsSecPerTrack		push bp			; <B> Sectors to transfer		; Important - this gets patched with a call.  The call		; assumes cx, si and bp are set up, and can modify bp		; and destroy si.  Until we have the space to do so,		; transfer one sector at a time.gls_set_size:__BEGIN_STUPID_PATCH_AREA:		mov bp,1		; 3 bytes, same as a call insn__END_STUPID_PATCH_AREA:		push ax			; <C> Cylinder #		push dx			; <D> Head #		push cx			; <E> Sector #		shl ah,6		; Because IBM was STOOPID					; and thought 8 bits were enough					; then thought 10 bits were enough...		pop cx			; <E> Sector #		push cx			; <E> Sector #		inc cx			; Sector numbers are 1-based, sigh		or cl,ah		mov ch,al		mov dh,dl		mov dl,[bsDriveNumber]		xchg ax,bp		; Sector to transfer count					; (xchg shorter than mov)		mov si,retry_count	; # of times to retry a disk access;; Do the disk transfer... save the registers in case we fail :(;disk_try_again: 		pusha			; <F>		mov ah,02h		; READ DISK		int 13h		popa			; <F>		jc disk_error;; Disk access successful;		pop cx			; <E> Sector #		mov di,ax		; Reduce sector left count		mul word [bsBytesPerSec] ; Figure out how much to advance ptr		add bx,ax		; Update buffer location		pop dx			; <D> Head #		pop ax			; <C> Cyl #		pop bp			; <B> Sectors left to transfer		pop si			; <A> Number of sectors/track		sub bp,di		; Reduce with # of sectors just read		jz writestr.return	; Done!		add cx,di		cmp cx,si		jb gls_nextchunk		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:	sub cx,si		; First sector on new track		jmp short gls_nextchunkbailmsg:	db 'Boot failed', 0Dh, 0Ah, 0bs_checkpt	equ $			; Must be <= 7DEFh%if 1bs_checkpt_off	equ ($-$$)%ifndef DEPEND%if bs_checkpt_off > 1EFh%error "Boot sector overflow"%endif%endif		zb 1EFh-($-$$)%endifbs_magic	equ $			; From here to the magic_len equ					; must match ldlinux_magicldlinux_name:	db 'LDLINUX SYS'	; Looks like this in the root dir		dd HEXDATE		; Hopefully unique between compilesbootsignature	dw 0AA55hmagic_len	equ $-bs_magic;; ===========================================================================;  End of boot sector; ===========================================================================;  Start of LDLINUX.SYS; ===========================================================================ldlinux_sys:syslinux_banner	db 0Dh, 0Ah%if IS_MDSLINUX		db 'MDSLINUX '%else		db 'SYSLINUX '%endif		db version_str, ' ', date, ' ', 0		db 0Dh, 0Ah, 1Ah	; EOF if we "type" this in DOSldlinux_magic	db 'LDLINUX SYS'		dd HEXDATE		dw 0AA55h;; This area is possibly patched by the installer.  It is located; immediately after the EOF + LDLINUX SYS + 4 bytes + 55 AA + alignment,; so we can find it algorithmically.;		alignb 4, db 0MaxTransfer	dw 00FFh		; Absolutely maximum transfer size		align 4ldlinux_ent:; ; Note that some BIOSes are buggy and run the boot sector at 07C0:0000; instead of 0000:7C00 and the like.  We don't want to add anything; more to the boot sector, so it is written to not assume a fixed; value in CS, but we don't want to deal with that anymore from now; on.;		jmp 0:.next.next:;; Tell the user we got this far;		mov si,syslinux_banner		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...;		xor ax,ax		cwd		inc dx				; DX:AX <- 64K		div word [bxBytesPerSec]	; sectors/64K		mov si,ax		push es		mov bx,fat_seg			; Load into fat_seg:0000		mov es,bx				mov eax,[bsHidden]		; Hidden sectors		add edx,[bxResSectors]		add eax,edx		mov ecx,[bxFATsecs]		; Sectors/FATfat_load_loop:			mov ebp,ecx			; Make sure high EBP = 0		cmp bp,si		jna fat_load		mov bp,si			; A full 64K mobyfat_load:			xor bx,bx			; Offset 0 in the current ES		call getlinsecsr		sub cx,bp		jz fat_load_done		; Last moby?		add eax,ebp			; Advance sector count		mov bx,es			; Next 64K moby		add bx,1000h		mov es,bx		jmp short fat_load_loopfat_load_done:		pop es;; 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 edi,[bxBytesPerSec]		; Used a lot below		mov eax,[SecPerClust]		mov si,ax			; Also used a lot		mul di		mov [ClustSize],eax		; Bytes/cluster		mov bx,ax		mov ax,trackbufsize		; High bit 0		cwd		div bx		mov [BufSafe],ax		; # of cluster in trackbuf		mul si		mov [BufSafeSec],ax		mul di		mov [BufSafeBytes],ax		add ax,getcbuf			; Size of getcbuf is the same		mov [EndOfGetCBuf],ax		; as for trackbuf;; FAT12 or FAT16?  This computation is fscking ridiculous...;		mov eax,[bxSectors]		and ax,ax		jnz have_secs		mov eax,[bsHugeSectors]have_secs:	add eax,[bsHidden]		; These are not included		sub eax,[RootDir]		; Start of root directory		movzx ebx,word [RootDirSize]		sub eax,ebx			; Subtract root directory size		xor edx,edx		div esi				; Convert to clusters		cmp ax,4086			; FAT12 limit		jna is_fat12		; Patch the jump		mov byte [nextcluster+1],nextcluster_fat16-(nextcluster+2)is_fat12:;; Patch gls_set_size so we can transfer more than one sector at a time.;		mov byte [gls_set_size],0xe8	; E8 = CALL NEAR		mov word [gls_set_size+1],do_gls_set_size-(gls_set_size+3)		mov byte [disk_error],0xe8		mov word [disk_error+1],do_disk_error-(disk_error+3);; Now we read the rest of LDLINUX.SYS.	Don't bother loading the first; cluster again, though.;load_rest:		mov cx,[ClustSize]		mov bx,ldlinux_sys		add bx,cx		mov si,[RunLinClust]		call nextcluster		xor dx,dx		mov ax,ldlinux_len-1		; To be on the safe side		add ax,cx		div cx				; 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:		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);;	Returns CF=1 on EOF;getfssec:.getfragment:	xor ebp,ebp			; Fragment sector count		lea eax,[si-2]			; Get 0-based sector address		mul dword [SecPerClust]		add eax,[DataArea].getseccnt:					; See if we can read > 1 clust		add bp,[SecPerClust]		dec cx				; Reduce clusters left to find		lea di,[si+1]		call nextcluster		cmc		jc .eof				; At EOF?		jcxz .endfragment		; Or was it the last we wanted?		cmp si,di			; Is file continuous?		je .getseccnt			; Yes, we can get.endfragment:	clc				; Not at EOF.eof:		pushf				; Remember EOF or not		push si		push cx.getchunk:		push eax		mov ax,es			; Check for 64K boundaries.		shl ax,4		add ax,bx		xor dx,dx		neg ax		setz dl				; DX <- 1 if full 64K segment		div word [bsBytesPerSec]	; How many sectors fit?		mov si,bp		sub si,ax			; Compute remaining sectors		jbe .lastchunk		mov bp,ax		pop eax		call getlinsecsr		add eax,ebp			; EBP<31:16> == 0		mov bp,si			; Remaining sector count		jmp short .getchunk.lastchunk:	pop eax		call getlinsec		pop cx		pop si		popf		jcxz .return			; If we hit the count limit		jnc .getfragment		; If we didn't hit EOF.return:	ret;; getlinsecsr: save registers, call getlinsec, restore registers;getlinsecsr:	pushad		call getlinsec		popad		ret;; nextcluster: Advance a cluster pointer in SI to the next cluster;	       pointed at in the FAT tables.  CF=0 on return if end of file.;nextcluster:		jmp short nextcluster_fat12	; This gets patchednextcluster_fat12:		push bx		push ds		mov bx,fat_seg		mov ds,bx		mov bx,si			; Multiply by 3/2		shr bx,1			; CF now set if odd		mov si,[si+bx]		jnc nc_even		shr si,4			; Needed for odd onlync_even:		and si,0FFFh		cmp si,0FF0h			; Clears CF if at end of file		pop ds		pop bxnc_return:	ret;; FAT16 decoding routine.  Note that a 16-bit FAT can be up to 128K,; so we have to decide if we're in the "low" or the "high" 64K-segment...;nextcluster_fat16:		push ax		push ds		mov ax,fat_seg		shl si,1		jnc .seg0		mov ax,fat_seg+1000h.seg0:		mov ds,ax		mov si,[si]		cmp si,0FFF0h		pop ds		pop ax		ret;; Routine that controls how much we can transfer in one chunk.  Called; from gls_set_size in getlinsec.;do_gls_set_size:		sub si,cx		; Sectors left on track		cmp bp,si		jna .lastchunk		mov bp,si		; No more than a trackful, please!.lastchunk:		cmp bp,[MaxTransfer]	; Absolute maximum transfer size		jna .oktransfer		mov bp,[MaxTransfer].oktransfer:			ret;; This routine captures disk errors, and tries to decide if it is; time to reduce the transfer size.;do_disk_error:		dec si			; Decrement the retry counter		jz kaboom		; If expired, croak		cmp si,2		; If only 2 attempts left		ja .nodanger		mov al,1		; Drop transfer size to 1		jmp short .setsize.nodanger:		cmp si,retry_count-2		ja .again		; First time, just try again		shr al,1		; Otherwise, try to reduce		adc al,0		; the max transfer size, but not to 0.setsize:		mov [MaxTransfer],al.again:		ret;; Debug routine;%ifdef debugsafedumpregs:		cmp word [Debug_Magic],0D00Dh		jnz nc_return		jmp dumpregs%endifrl_checkpt	equ $				; Must be <= 8000hrl_checkpt_off	equ ($-$$)%ifndef DEPEND%if rl_checkpt_off > 400h%error "Sector 1 overflow"%endif%endif; ----------------------------------------------------------------------------;  End of code and data that have to be in the first sector; ----------------------------------------------------------------------------all_read:;; Let the user (and programmer!) know we got this far.  This used to be; in Sector 1, but makes a lot more sense here.;

⌨️ 快捷键说明

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