📄 io.c
字号:
/* Purpose: Outputs a string of 32-bit words to a hardware port */
/* */
/* Inputs: */
/* */
/* word port */
/* hardware port to write to */
/* */
/* void *buf */
/* Buffer to write data from */
/* */
/* int count */
/* Number of DWORDs to write */
/* */
/* Outputs: */
/* */
/* None */
/* */
/****************************************************************************/
void outsl(UINT16 port, void *buf, int count)
{
_SI = FP_SEG(buf); /* Offset of buf */
_CX = count; /* Number to read */
_DX = port; /* Port */
__emit__(0xf3, 0x66, 0x6F); /* asm REP OUTSD; */
}
/*
************************************************************************
************************************************************************
** **
** xpeek/xpoke routines **
** **
** The pragma statements turn off the warning message: **
** **
** Function should return a value in function ... **
** **
** Since it is the embedded assembly that sets up the return value(s) **
** for ax or dx:ax this warning message is meaningless. Removing it **
** makes a clean build (and let's you more easily notice any "real" **
** warning messages. **
** **
************************************************************************
************************************************************************
*/
int x4gbinitialized = FALSE;
#pragma inline
/*asm P386 */
/* **************************************** */
/* DO NOT PUT ANYTHING AFTER HERE UNLESS */
/* YOU WANT THE "INLINE" PRAGMA TO BE */
/* USED FOR THESE FUNCTIONS TOO. */
/* **************************************** */
/*
The "pragma inline" is only used to force the use of
TASM (Turbo assembler), because the built-in does
not recognize the "eax" register.
*/
#pragma warn -rvl
/* Really -wrvl check that functions return a value (if not void)
The "#pragma warn" means use the "-w" option.
*/
UINT8 mem48[6]; // 1st two bytes is size of GDT, next 4 bytes is address of GDT entries
UINT8 gdt[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* GDT entry 0 (null segment) */
0xFF,0xFF,0x00,0x00,0x00,0x92,0xCF,0xFF /* GDT entry 1 (seg 0, limit 4GB) */
};
void seg4gb(void)
{
/* Sets up a GDT so that all of memory can be addressed.
*/
asm {
mov mem48[0],16 // #bytes in gdt - part of GDT
mov eax,seg gdt // calc physical gdt entry address...
shl eax,4
mov bx,offset gdt
movzx ebx,bx // zero-extend bx into ebx
add eax,ebx // eax is physical address of gdt
mov dword ptr mem48[2],eax
lgdt pword ptr mem48 // Load global descriptor table address
mov bx,08h // Load bx to point to GDT entry 1
push ds
cli // Disable interrupts
mov eax,cr0 // Switch to protected mode...
or eax,1 // ...
mov cr0,eax // now in protected mode
jmp PROTECTION_ENABLED // Clear execution pipe
}
PROTECTION_ENABLED:
asm {
mov gs,bx // Load segment shadow-registers
mov fs,bx // with GDT entry 1 (4GB segment limit)
mov es,bx
mov ds,bx
and al,0FEh // Switch back to real-mode without
mov cr0,eax // resetting the CPU
jmp PROTECTION_DISABLED // Clear execution pipe
}
PROTECTION_DISABLED:
asm {
xor ax,ax // zero out gs/fs to use as base regs
mov gs,ax
mov fs,ax
sti // Enable interrupts
pop ds
}
// DEH - must disable for turbo debugger...
// x4gbinitialized = 1;
}
UINT8 xpeek8( UINT32 address )
{
if( !x4gbinitialized )
seg4gb();
asm {
mov ebx,[address]
mov al,gs:[ebx]
}
}
UINT16 xpeek16( UINT32 address )
{
if( !x4gbinitialized )
seg4gb();
asm {
mov ebx,[address]
mov ax,gs:[ebx]
}
}
UINT32 xpeek32( UINT32 address )
{
if( !x4gbinitialized )
seg4gb();
asm {
mov ebx,[address]
mov eax,gs:[ebx]
push eax
pop ax
pop dx
}
}
#pragma warn +rvl
// turns warning back on
// see comment at beginning section for info on this pragma statement
void xpoke8( UINT32 address, UINT8 data )
{
if( !x4gbinitialized )
seg4gb();
asm {
mov ebx,[address]
mov al,[data]
mov gs:[ebx],al
}
}
void xpoke16( UINT32 address, UINT16 data )
{
if( !x4gbinitialized )
seg4gb();
asm {
mov ebx,[address]
mov ax,[data]
mov gs:[ebx],ax
}
}
void xpoke32( UINT32 address, UINT32 data )
{
if( !x4gbinitialized )
seg4gb();
asm {
mov ebx,[address]
mov eax,[data]
mov gs:[ebx],eax
}
}
void outpl( UINT16 portaddr, UINT32 data )
{
asm {
mov dx,[portaddr]
mov eax,[data]
out dx,eax
}
}
/* INPL - input long word, portaddr - port address */
UINT32 inpl(UINT16 portaddr)
{
asm {
mov dx,[portaddr]
in eax,dx
push eax
pop ax
pop dx
}
}
/* **************************************** */
/* DO NOT PUT ANYTHING AFTER HERE UNLESS */
/* YOU WANT THE "INLINE" PRAGMA TO BE */
/* USED FOR THESE FUNCTIONS TO. */
/* **************************************** */
/*
The "pragma inline" is only used to force the use of
TASM (Turbo assembler), because the built-in does
not recognize the "eax" register.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -