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

📄 pm12c.c

📁 《自己动手写操作系统》一书的光盘配套代码
💻 C
📖 第 1 页 / 共 2 页
字号:
								/* pm12c.c
******************************************************************************
	pm12c.c - protected-mode demo code
	Christopher Giese <geezer[AT]execpc.com>

	Release date 9/28/98. Distribute freely. ABSOLUTELY NO WARRANTY.
	Assemble pm12a.asm with NASM:
				nasm -f aout -o pm12a.o pm12a.asm
	Compile pm12c.c with DJGPP:
				gcc -c -O2 -o pm12c.o pm12c.c
	Link with DJGPP ld, using pm12.scr script:
				ld -o pm12.com -Tpm12.scr pm12a.o pm12c.o
	or just type:
				make -f pm12.mak

Demonstrates:
	- Interface and linking to C-language code.
	- The beginnings of a libc (standard C library).
	- More elaborate syscalls and error-handling.
	- Scrolling video; moving cursor in putch().
*****************************************************************************/
/*////////////////////////////////////////////////////////////////////////////
	x86.h, x86.c
////////////////////////////////////////////////////////////////////////////*/
/* Portions copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
/*****************************************************************************
	name:	outb
	action:	writes 8-bit Data to Port
*****************************************************************************/
__inline__ void outb(unsigned short Port, unsigned char Data)
{	__asm__ __volatile__ ("outb %1, %0"
		:
		: "d" (Port), "a" (Data)); }
/*****************************************************************************
	name:	disable
	action:	disables all interrupts at the CPU
	returns:old value of EFLAGS
*****************************************************************************/
__inline__ void disable(void)
{	__asm__ __volatile__ (
		"cli\n"
		:
		: ); }
/*****************************************************************************
	name:	enable
	action:	enables interrupts at CPU
*****************************************************************************/
__inline__ void enable(void)
{	__asm__ __volatile__ (
		"sti\n"
		:
		: ); }
/*****************************************************************************
	name:	peekb
	action:	reads 8-bit data from far address Seg:Off
	returns:value read
*****************************************************************************/
__inline__ unsigned char peekb(unsigned short Seg, unsigned long Off)
{	unsigned char RetVal;

	__asm__ __volatile__ ("movw %w1, %%fs \n.byte 0x64 \nmovb (%k2),%w0"
		: "=r" (RetVal)
		: "rm" (Seg), "r" (Off));
	return(RetVal); }
/*****************************************************************************
	name:	peekw
	action:	reads 16-bit data from far address Seg:Off
	returns:value read
*****************************************************************************/
__inline__ unsigned short peekw(unsigned short Seg, unsigned long Off)
{	unsigned short RetVal;

	__asm__ __volatile__ ("movw %w1, %%fs \n.byte 0x64 \nmovw (%k2),%w0"
		: "=r" (RetVal)
		: "rm" (Seg), "r" (Off));
	return(RetVal); }
/*****************************************************************************
	name:	pokeb
	action:	writes 8-bit Data to far address Seg:Off
*****************************************************************************/
__inline__ void pokeb(unsigned short Seg, unsigned long Off, unsigned char Data)
{	__asm__ __volatile__ ("movw %w0,%%fs \n.byte 0x64 \nmovb %w1,(%k2)"
		:
		: "rm" (Seg), "ri" (Data), "r" (Off)); }
/*****************************************************************************
	name:	pokew
	action:	writes 16-bit Data to far address Seg:Off
*****************************************************************************/
__inline__ void pokew(unsigned short Seg, unsigned long Off, unsigned short Data)
{	__asm__ __volatile__ ("movw %w0,%%fs \n.byte 0x64 \nmovw %w1,(%k2)"
		:
		: "rm" (Seg), "ri" (Data), "r" (Off)); }
/*****************************************************************************
	name:	farmemmove
	action:	moves Count bytes from far address SrcSeg:SrcOff to
		far address DstSeg:DstOff
	XXX - convert to assembly, handle overlapping Src and Dst
*****************************************************************************/
void farmemmove(unsigned short DstSeg, unsigned long DstOff, unsigned short SrcSeg, unsigned long SrcOff,
	unsigned Count)
{
	for(; Count; Count--)
		pokeb(DstSeg, DstOff++, peekb(SrcSeg, SrcOff++)); }
/*****************************************************************************
	name:	farmemsetw
	action:	writes 16-bit Data to far address DstSeg:DstOff
		Count times
	XXX - convert to assembly
*****************************************************************************/
void farmemsetw(unsigned short DstSeg, unsigned long DstOff, unsigned short Data, unsigned Count)
{	for(; Count; Count--)
	{	pokew(DstSeg, DstOff, Data);
		DstOff += 2; }}
/*////////////////////////////////////////////////////////////////////////////
	stdarg.h
////////////////////////////////////////////////////////////////////////////*/
/* round up width of objects pushed on stack. The expression before the
& ensures that we get 0 for objects of size 0. */
#define	VA_SIZE(TYPE)		\
	((sizeof(TYPE) + sizeof(_stackitem) - 1) & ~(sizeof(_stackitem) - 1))

/* &(LASTARG) points to the LEFTMOST argument of the function call */
#define	va_start(AP, LASTARG)	\
	(AP=((va_list)&(LASTARG) + VA_SIZE(LASTARG)))

#define va_end(AP)	/* nothing */

#define va_arg(AP, TYPE)	\
	(AP += VA_SIZE(TYPE), *((TYPE *)(AP - VA_SIZE(TYPE))))

typedef char *va_list;
typedef int _stackitem;	/* stack holds nothing narrower than this type */
/*////////////////////////////////////////////////////////////////////////////
	stdio.h
////////////////////////////////////////////////////////////////////////////*/
#define		EOF		(-1l)
#define		NULL		(0ul)

typedef int (*fnptr)(char *Str, char Char);
/*****************************************************************************
	name:	myPrintf
	action:	minimal subfunction for ?printf, calls function
		Fn with arg Ptr for each character to be output
	returns:total number of characters output

	%[flag][width][.prec][mod][conv]
	flag:	-	left justify, pad right w/ blanks	DONE
		0	pad left w/ 0 for numerics
		+	always print sign, + or -
		' '	(blank)
		#	(???)
	width:		(field width)				DONE
	prec:		(precision)
	conv:	d,i	decimal int				DONE
		o	octal					DONE
		x,X	hex					DONE
		f,e,g,E,G float
		c	char					DONE
		s	string					DONE
		p	ptr					DONE
	mod:	N	near ptr
		u	decimal unsigned			DONE
		F	far ptr
		h	short int				DONE
		l	long int				DONE
		L	long double
*****************************************************************************/
/* flags used in processing format string */
#define		VPR_LJ	0x01	/* left justify */
#define		VPR_CA	0x02	/* use A-F instead of a-f for hex */
#define		VPR_SG	0x04	/* signed numeric conversion (%d vs. %u) */
#define		VPR_32	0x08	/* long (32-bit) numeric conversion */
#define		VPR_16	0x10	/* short (16-bit) numeric conversion */
#define		VPR_WS	0x20	/* VPR_SG set and Num was < 0 */

/* largest number handled is 2^32-1, lowest radix handled is 8.
2^32-1 in base 8 has 11 digits (add one for trailing NUL) */
#define		VPR_BUFLEN	12

int myPrintf(fnptr Fn, char *Ptr, const char *Fmt, va_list Args)
{	char *Where, Buf[VPR_BUFLEN], State, Flags;
	unsigned short Count, GivenWd;
	unsigned long Num, Temp;
/* cheap compilers for 8-bit CPUs don't optimize well (if at all), so
we do poor-man's live-range optimization: */
#define	Radix		State
#define	ActualWd	State

	State=Flags=Count=GivenWd=0;
/* begin scanning format specifier list */
	for(; *Fmt; Fmt++)
	{	switch(State)
		{case 0:	/* AWAITING % */
			if(*Fmt != '%')			/* not %... */
			{	Fn(Ptr++, *Fmt);	/* ...just echo it */
				Count++;
				break; }
/* found %, get next char and advance state to check if next char is a flag */
			else
			{	State++;
				Fmt++; }/* FALL THROUGH */
		case 1:		/* AWAITING FLAGS (-) */
			if(*Fmt == '-')
			{	if(Flags & VPR_LJ)	/* %-- is illegal */
					State=Flags=GivenWd=0;
				else Flags |= VPR_LJ;
				break; }
/* not a flag char: advance state to check if it's field width */
			else State++;	/* FALL THROUGH */
		case 2:		/* AWAITING FIELD WIDTH (<number>) */
			if(*Fmt >= '0' && *Fmt <= '9')
			{	GivenWd=10 * GivenWd + (*Fmt - '0');
				break; }
/* not field width: advance state to check if it's a modifier */
			else State++;	/* FALL THROUGH */
		case 3:		/* AWAITING MODIFIER CHARS (lh) */
			if(*Fmt == 'l')
			{	Flags |= VPR_32;
				break; }
			if(*Fmt == 'h')
			{	Flags |= VPR_16;
				break; }
/* not modifier: advance state to check if it's a conversion char */
			else State++;	/* FALL THROUGH */
		case 4:		/* AWAITING CONVERSION CHARS (Xxpndiuocs) */
			Where=Buf + VPR_BUFLEN;
			*--Where=0;
			switch(*Fmt)
			{case 'X':
				Flags |= VPR_CA;/* FALL THROUGH */
			case 'x':
			case 'p':
			case 'n':
				Radix=16;
				goto DO_NUM;
			case 'd':
			case 'i':
				Flags |= VPR_SG;/* FALL THROUGH */
			case 'u':
				Radix=10;
				goto DO_NUM;
			case 'o':

⌨️ 快捷键说明

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