📄 pm12c.c
字号:
/* 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 + -