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

📄 start32.s

📁 linux下从网卡远程启动
💻 S
字号:
/* #defines because ljmp wants a number, probably gas bug *//*	.equ	KERN_CODE_SEG,_pmcs-_gdt	*/#define	KERN_CODE_SEG	0x08	.equ	KERN_DATA_SEG,_pmds-_gdt/*	.equ	REAL_CODE_SEG,_rmcs-_gdt	*/#define	REAL_CODE_SEG	0x18	.equ	REAL_DATA_SEG,_rmds-_gdt	.equ	CR0_PE,1#ifdef	GAS291#define DATA32 data32;#define ADDR32 addr32;#define	LJMPI(x)	ljmp	x#else#define DATA32 data32#define ADDR32 addr32/* newer GAS295 require #define	LJMPI(x)	ljmp	*x */#define	LJMPI(x)	ljmp	x#endif/* Size of segment allocated to first32.c in protected mode */#define	FIRST32SIZE	(6*1024)/* * NOTE: if you write a subroutine that is called from C code (gcc/egcs), * then you only have to take care of %ebx, %esi, %edi and %ebp.  These * registers must not be altered under any circumstance.  All other registers * may be clobbered without any negative side effects.  If you don't follow * this rule then you'll run into strange effects that only occur on some * gcc versions (because the register allocator may use different registers). * * All the data32 prefixes for the ljmp instructions are necessary, because * the assembler emits code with a relocation address of 0.  This means that * all destinations are initially negative, which the assembler doesn't grok, * because for some reason negative numbers don't fit into 16 bits. The addr32 * prefixes are there for the same reasons, because otherwise the memory * references are only 16 bit wide.  Theoretically they are all superfluous. * One last note about prefixes: the data32 prefixes on all call _real_to_prot * instructions could be removed if the _real_to_prot function is changed to * deal correctly with 16 bit return addresses.  I tried it, but failed. *//**************************************************************************START - Where all the fun begins....**************************************************************************//* this must be the first thing in the file because we enter from the top */	.global	_start_start:/* We have to use our own GDT when running in our segment because the old   GDT will have the wrong descriptors for the real code segments */	sgdt	gdtsave		/* save old GDT */	lgdt	gdtarg		/* load ours */	/* reload the segment registers */	movl	$KERN_DATA_SEG,%eax	movl	%eax,%ds	movl	%eax,%es	movl	%eax,%ss	movl	%eax,%fs	movl	%eax,%gs	/* flush prefetch queue, and reload %cs:%eip */	ljmp	$KERN_CODE_SEG,$1f1:	/* save the stack pointer and jump to the routine */	movl	%esp,%eax	movl	%eax,initsp	movl	$RELOC+FIRST32SIZE,%esp	/* change stack */	/* copy the arguments on the stack over */	pushl	12(%eax)		/* bootp */	pushl	8(%eax)			/* header */	pushl	4(%eax)			/* ebinfo */	call	first	/* fall through */_exit:/*	we reset sp to the location just before entering first	instead of relying on the return from first because exit	could have been called from anywhere */	movl	initsp,%ebx	movl	%ebx,%esp	lgdt	gdtsave		/* restore old GDT */	ret	.globl	exitexit:	movl	4(%esp),%eax	jmp	_exit/**************************************************************************CONSOLE_PUTC - Print a character on console**************************************************************************/	.globl	console_putcconsole_putc:	pushl	%ebp	movl	%esp,%ebp	pushl	%ebx	pushl	%esi	pushl	%edi	movb	8(%ebp),%cl	call	_prot_to_real	.code16	movl	$1,%ebx	movb	$0x0e,%ah	movb	%cl,%al	int	$0x10	DATA32 call	_real_to_prot	.code32	popl	%edi	popl	%esi	popl	%ebx	popl	%ebp	ret/**************************************************************************E820_MEMSIZE - Get a listing of memory regions**************************************************************************/	.globl	meme820#define SMAP	0x534d4150meme820:	pushl	%ebp	movl	%esp, %ebp	pushl	%ebx	pushl	%esi	pushl	%edi	movl	8(%ebp), %edi	/* Address to return e820 structures at */	subl	$RELOC, %edi	movl	12(%ebp), %esi	/* Maximum number of e820 structurs to return */	pushl	%esi	call	_prot_to_real	.code16	xorl	%ebx, %ebxjmpe820:		movl	$0xe820, %eax	movl	$SMAP, %edx	movl	$20, %ecx	/* %di was setup earlier */	int	$0x15	jc	bail820	cmpl	$SMAP, %eax	jne	bail820good820:		/* If this is useable memory, we save it by simply advancing %di by	 * sizeof(e820rec)	 */	decl	%esi	testl	%esi,%esi	jz	bail820	addw	$20, %diagain820:	cmpl	$0, %ebx	/* check to see if %ebx is set to EOF */	jne	jmpe820bail820:	DATA32 call	_real_to_prot	.code32	popl	%eax	subl	%esi, %eax	/* Compute how many structure we read */	/* Restore everything else */		popl	%edi	popl	%esi	popl	%ebx	movl	%ebp, %esp	popl	%ebp	ret/**************************************************************************MEMSIZE - Determine size of extended memory**************************************************************************/	.globl	memsizememsize:	pushl	%ebx	pushl	%esi	pushl	%edi	call	_prot_to_real	.code16	stc					# fix to work around buggy	xorw	%cx,%cx				# BIOSes which dont clear/set	xorw	%dx,%dx				# carry on pass/error of						# e801h memory size call						# or merely pass cx,dx though						# without changing them.	movw	$0xe801,%ax	int	$0x15	jc	3f	cmpw	$0,%cx				# Kludge to handle BIOSes	jne	1f				# which report their extended	cmpw	$0,%dx				# memory in AX/BX rather than	je	2f				# CX/DX.  The spec I have read1:	movw	%cx,%ax				# seems to indicate AX/BX 	movw	%dx,%bx				# are more reasonable anyway...2:	andl	$0xffff,%eax	andl	$0xffff,%ebx	shll	$6,%ebx	addl	%ebx,%eax	jmp	4f3:	movw	$0x8800,%ax	int	$0x15	andl	$0xffff,%eax4:	movl	%eax,%esi	DATA32 call	_real_to_prot	.code32	movl	%esi,%eax	popl	%edi	popl	%esi	popl	%ebx	ret/**************************************************************************BASEMEMSIZE - Get size of the conventional (base) memory**************************************************************************/	.globl	basememsizebasememsize:	call	_prot_to_real	.code16	int	$0x12	movw	%ax,%cx	DATA32 call	_real_to_prot	.code32	movw	%cx,%ax	ret/**************************************************************************XSTART - Transfer control to the kernel just loaded in real mode**************************************************************************/	.globl	xstartxstart:	pushl	%ebp	movl	%esp,%ebp	pushl	%ebx	pushl	%esi	pushl	%edi	movl	8(%ebp),%eax/*	Convert to segment:offset form */	movl	%eax,%ebx	andl	$0xF,%eax	andl	$0xFFFFFFF0,%ebx	shll	$12,%ebx	orl	%eax,%ebx	call	_prot_to_real	.code16	movl	$((RELOC<<12)+(1f-RELOC)),%eax	pushl	%eax	pushl	%ebx	lret1:	addw	$4,%sp		/* XXX or is this 10 in case of a 16bit "ret" */	DATA32 call	_real_to_prot	.code32	popl	%edi	popl	%esi	popl	%ebx	popl	%ebp	ret/**************************************************************************_REAL_TO_PROT - Go from REAL mode to Protected Mode**************************************************************************/	.globl	_real_to_prot_real_to_prot:	.code16	cli	cs	ADDR32 lgdt	gdtarg-_start	movl	%cr0,%eax	orl	$CR0_PE,%eax	movl	%eax,%cr0		/* turn on protected mode */	/* flush prefetch queue, and reload %cs:%eip */	DATA32 ljmp	$KERN_CODE_SEG,$1f1:	.code32	/* reload other segment registers */	movl	$KERN_DATA_SEG,%eax	movl	%eax,%ds	movl	%eax,%es	movl	%eax,%ss	addl	$RELOC,%esp		/* Fix up stack pointer */	xorl	%eax,%eax	movl	%eax,%fs	movl	%eax,%gs	popl	%eax			/* Fix up return address */	addl	$RELOC,%eax	pushl	%eax	ret/**************************************************************************_PROT_TO_REAL - Go from Protected Mode to REAL Mode**************************************************************************/	.globl	_prot_to_real_prot_to_real:	.code32	popl	%eax	subl	$RELOC,%eax		/* Adjust return address */	pushl	%eax	subl	$RELOC,%esp		/* Adjust stack pointer */#ifdef	GAS291	ljmp	$REAL_CODE_SEG,$1f-RELOC	/* jump to a 16 bit segment */#else	ljmp	$REAL_CODE_SEG,$1f-_start	/* jump to a 16 bit segment */#endif	/* GAS291 */1:	.code16	movw	$REAL_DATA_SEG,%ax	movw	%ax,%ds	movw	%ax,%ss	movw	%ax,%es	movw	%ax,%fs	movw	%ax,%gs	/* clear the PE bit of CR0 */	movl	%cr0,%eax	andl	$0!CR0_PE,%eax	movl	%eax,%cr0	/* make intersegment jmp to flush the processor pipeline	 * and reload %cs:%eip (to clear upper 16 bits of %eip).	 */	DATA32 ljmp	$(RELOC)>>4,$2f-_start2:	/* we are in real mode now	 * set up the real mode segment registers : %ds, $ss, %es	 */	movw	%cs,%ax	movw	%ax,%ds	movw	%ax,%es	movw	%ax,%ss	sti	DATA32 ret	/* There is a 32 bit return address on the stack */	.code32/**************************************************************************GLOBAL DESCRIPTOR TABLE**************************************************************************/	.align	4_gdt:gdtarg:	.word	0x27			/* limit */	.long	_gdt			/* addr */	.byte	0,0_pmcs:	/* 32 bit protected mode code segment */	.word	0xffff,0	.byte	0,0x9f,0xcf,0_pmds:	/* 32 bit protected mode data segment */	.word	0xffff,0	.byte	0,0x93,0xcf,0_rmcs:	/* 16 bit real mode code segment */	.word	0xffff,(RELOC&0xffff)	.byte	(RELOC>>16),0x9b,0x00,(RELOC>>24)_rmds:	/* 16 bit real mode data segment */	.word	0xffff,(RELOC&0xffff)	.byte	(RELOC>>16),0x93,0x00,(RELOC>>24)gdtsave:	.long	0,0,0			/* previous GDT *//* Other variables */initsp:	.long	0

⌨️ 快捷键说明

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