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

📄 boot.s

📁 最早的linux操作系统源代码(3)
💻 S
字号:
!!	boot.s!! boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself! out of the way to address 0x90000, and jumps there.!! It then loads the system at 0x10000, using BIOS interrupts. Thereafter! it disables all interrupts, moves the system down to 0x0000, changes! to protected mode, and calls the start of system. System then must! RE-initialize the protected mode in it's own tables, and enable! interrupts as needed.!! NOTE! currently system is at most 8*65536 bytes long. This should be no! problem, even in the future. I want to keep it simple. This 512 kB! kernel size should be enough - in fact more would mean we'd have to move! not just these start-up routines, but also do something about the cache-! memory (block IO devices). The area left over in the lower 640 kB is meant! for these. No other memory is assumed to be "physical", ie all memory! over 1Mb is demand-paging. All addresses under 1Mb are guaranteed to match! their physical addresses.!! NOTE1 abouve is no longer valid in it's entirety. cache-memory is allocated! above the 1Mb mark as well as below. Otherwise it is mainly correct.!! NOTE 2! The boot disk type must be set at compile-time, by setting! the following equ. Having the boot-up procedure hunt for the right! disk type is severe brain-damage.! The loader has been made as simple as possible (had to, to get it! in 512 bytes with the code to move to protected mode), and continuos! read errors will result in a unbreakable loop. Reboot by hand. It! loads pretty fast by getting whole sectors at a time whenever possible.! 1.44Mb disks:sectors = 18! 1.2Mb disks:! sectors = 15! 720kB disks:! sectors = 9SYSSIZE = 0x2000.globl begtext, begdata, begbss, endtext, enddata, endbss.textbegtext:.databegdata:.bssbegbss:.textBOOTSEG = 0x07c0INITSEG = 0x9000SYSSEG  = 0x1000		! system loaded at 0x10000 (65536).ENDSEG	= SYSSEG + SYSSIZEentry _start_start:	mov	ax,#BOOTSEG	mov	ds,ax	mov	ax,#INITSEG	mov	es,ax	mov	cx,#256	sub	si,si	sub	di,di	rep	movw	jmpi	go,INITSEGgo:	mov	ax,cs	mov	ds,ax	mov	es,ax	mov	ss,ax	mov	sp,#0x400		! arbitrary value >>512	mov	ah,#0x03	! read cursor pos	xor	bh,bh	int	0x10		mov	cx,#24	mov	bx,#0x0007	! page 0, attribute 7 (normal)	mov	bp,#msg1	mov	ax,#0x1301	! write string, move cursor	int	0x10! ok, we've written the message, now! we want to load the system (at 0x10000)	mov	ax,#SYSSEG	mov	es,ax		! segment of 0x010000	call	read_it	call	kill_motor! if the read went well we get current cursor position ans save it for! posterity.	mov	ah,#0x03	! read cursor pos	xor	bh,bh	int	0x10		! save it in known place, con_init fetches	mov	[510],dx	! it from 0x90510.		! now we want to move to protected mode ...	cli			! no interrupts allowed !! first we move the system to it's rightful place	mov	ax,#0x0000	cld			! 'direction'=0, movs moves forwarddo_move:	mov	es,ax		! destination segment	add	ax,#0x1000	cmp	ax,#0x9000	jz	end_move	mov	ds,ax		! source segment	sub	di,di	sub	si,si	mov 	cx,#0x8000	rep	movsw	j	do_move! then we load the segment descriptorsend_move:	mov	ax,cs		! right, forgot this at first. didn't work :-)	mov	ds,ax	lidt	idt_48		! load idt with 0,0	lgdt	gdt_48		! load gdt with whatever appropriate! that was painless, now we enable A20	call	empty_8042	mov	al,#0xD1		! command write	out	#0x64,al	call	empty_8042	mov	al,#0xDF		! A20 on	out	#0x60,al	call	empty_8042! well, that went ok, I hope. Now we have to reprogram the interrupts :-(! we put them right after the intel-reserved hardware interrupts, at! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really! messed this up with the original PC, and they haven't been able to! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,! which is used for the internal hardware interrupts as well. We just! have to reprogram the 8259's, and it isn't fun.	mov	al,#0x11		! initialization sequence	out	#0x20,al		! send it to 8259A-1	.word	0x00eb,0x00eb		! jmp $+2, jmp $+2	out	#0xA0,al		! and to 8259A-2	.word	0x00eb,0x00eb	mov	al,#0x20		! start of hardware int's (0x20)	out	#0x21,al	.word	0x00eb,0x00eb	mov	al,#0x28		! start of hardware int's 2 (0x28)	out	#0xA1,al	.word	0x00eb,0x00eb	mov	al,#0x04		! 8259-1 is master	out	#0x21,al	.word	0x00eb,0x00eb	mov	al,#0x02		! 8259-2 is slave	out	#0xA1,al	.word	0x00eb,0x00eb	mov	al,#0x01		! 8086 mode for both	out	#0x21,al	.word	0x00eb,0x00eb	out	#0xA1,al	.word	0x00eb,0x00eb	mov	al,#0xFF		! mask off all interrupts for now	out	#0x21,al	.word	0x00eb,0x00eb	out	#0xA1,al! well, that certainly wasn't fun :-(. Hopefully it works, and we don't! need no steenking BIOS anyway (except for the initial loading :-).! The BIOS-routine wants lots of unnecessary data, and it's less! "interesting" anyway. This is how REAL programmers do it.!! Well, now's the time to actually move into protected mode. To make! things as simple as possible, we do no register set-up or anything,! we let the gnu-compiled 32-bit programs do that. We just jump to! absolute address 0x00000, in 32-bit protected mode.	mov	ax,#0x0001	! protected mode (PE) bit	lmsw	ax		! This is it!	jmpi	0,8		! jmp offset 0 of segment 8 (cs)! This routine checks that the keyboard command queue is empty! No timeout is used - if this hangs there is something wrong with! the machine, and we probably couldn't proceed anyway.empty_8042:	.word	0x00eb,0x00eb	in	al,#0x64	! 8042 status port	test	al,#2		! is input buffer full?	jnz	empty_8042	! yes - loop	ret! This routine loads the system at address 0x10000, making sure! no 64kB boundaries are crossed. We try to load it as fast as! possible, loading whole tracks whenever we can.!! in:	es - starting address segment (normally 0x1000)!! This routine has to be recompiled to fit another drive type,! just change the "sectors" variable at the start of the file! (originally 18, for a 1.44Mb drive)!sread:	.word 1			! sectors read of current trackhead:	.word 0			! current headtrack:	.word 0			! current trackread_it:	mov ax,es	test ax,#0x0fffdie:	jne die			! es must be at 64kB boundary	xor bx,bx		! bx is starting address within segmentrp_read:	mov ax,es	cmp ax,#ENDSEG		! have we loaded all yet?	jb ok1_read	retok1_read:	mov ax,#sectors	sub ax,sread	mov cx,ax	shl cx,#9	add cx,bx	jnc ok2_read	je ok2_read	xor ax,ax	sub ax,bx	shr ax,#9ok2_read:	call read_track	mov cx,ax	add ax,sread	cmp ax,#sectors	jne ok3_read	mov ax,#1	sub ax,head	jne ok4_read	inc trackok4_read:	mov head,ax	xor ax,axok3_read:	mov sread,ax	shl cx,#9	add bx,cx	jnc rp_read	mov ax,es	add ax,#0x1000	mov es,ax	xor bx,bx	jmp rp_readread_track:	push ax	push bx	push cx	push dx	mov dx,track	mov cx,sread	inc cx	mov ch,dl	mov dx,head	mov dh,dl	mov dl,#0	and dx,#0x0100	mov ah,#2	int 0x13	jc bad_rt	pop dx	pop cx	pop bx	pop ax	retbad_rt:	mov ax,#0	mov dx,#0	int 0x13	pop dx	pop cx	pop bx	pop ax	jmp read_track!/*! * This procedure turns off the floppy drive motor, so! * that we enter the kernel in a known state, and! * don't have to worry about it later.! */kill_motor:	push dx	mov dx,#0x3f2	mov al,#0	outb	pop dx	retgdt:	.word	0,0,0,0		! dummy	.word	0x07FF		! 8Mb - limit=2047 (2048*4096=8Mb)	.word	0x0000		! base address=0	.word	0x9A00		! code read/exec	.word	0x00C0		! granularity=4096, 386	.word	0x07FF		! 8Mb - limit=2047 (2048*4096=8Mb)	.word	0x0000		! base address=0	.word	0x9200		! data read/write	.word	0x00C0		! granularity=4096, 386idt_48:	.word	0			! idt limit=0	.word	0,0			! idt base=0Lgdt_48:	.word	0x800		! gdt limit=2048, 256 GDT entries	.word	gdt,0x9		! gdt base = 0X9xxxx	msg1:	.byte 13,10	.ascii "Loading system ..."	.byte 13,10,13,10        org 510	.word 0xAA55.textendtext:.dataenddata:.bssendbss:

⌨️ 快捷键说明

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