在我的计算机网络课程中,我们应该通过使用本机寄存器来学习并行端口编程(比如使用类似outportb的命令)。我没有并行端口(因为我住在2011),但我想练习一下这些程序(我使用dosbox安装了旧的turboc 3 IDE )。有没有像this程序模拟串口那样模拟并口的程序?
发布于 2011-10-19 05:47:19
因为环境是假的,也就是说你没有实际的端口,你也可以在你的程序中模拟端口功能。
下面是如何在Windows中使用 (SEH)实现这一点:
// Filename: PortEmu.c
// Compiled with Open Watcom 1.9 as: wcl386 PortEmu.c
#include <windows.h>
#include <stdio.h>
#include <conio.h>
// Port state. Holds the last value written by OUT.
// IN reads from it.
volatile UINT32 PortState = 0;
UINT32 ReadPort(UINT16 PortNumber, UINT OperandSize)
{
UNREFERENCED_PARAMETER(PortNumber);
switch (OperandSize)
{
default:
case 8:
return PortState & 0xFF;
case 16:
return PortState & 0xFFFF;
case 32:
return PortState;
}
}
void WritePort(UINT16 PortNumber, UINT OperandSize, UINT32 Value)
{
UNREFERENCED_PARAMETER(PortNumber);
switch (OperandSize)
{
default:
case 8:
PortState = (PortState & ~0xFF) | (Value & 0xFF);
break;
case 16:
PortState = (PortState & ~0xFFFF) | (Value & 0xFFFF);
break;
case 32:
PortState = Value;
break;
}
}
// Exception filter to emulate x86 IN and OUT instructions
// in 32-bit Windows application.
int IoExceptionFilter(LPEXCEPTION_POINTERS ep)
{
CONTEXT* c = ep->ContextRecord;
UINT8* instr = (UINT8*)c->Eip;
int OperandSizeIs16Bit = 0;
switch (ep->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_PRIV_INSTRUCTION:
if (instr[0] == 0x66)
{
OperandSizeIs16Bit = 1;
instr++;
}
switch (instr[0])
{
case 0xE4: // IN AL, imm8
*(UINT8*)&c->Eax = ReadPort(instr[1], 8);
c->Eip += 2 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xE5: // IN (E)AX, imm8
if (OperandSizeIs16Bit)
*(UINT16*)&c->Eax = ReadPort(instr[1], 16);
else
c->Eax = ReadPort(instr[1], 32);
c->Eip += 2 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xEC: // IN AL, DX
*(UINT8*)&c->Eax = ReadPort((UINT16)c->Edx, 8);
c->Eip += 1 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xED: // IN (E)AX, DX
if (OperandSizeIs16Bit)
*(UINT16*)&c->Eax = ReadPort((UINT16)c->Edx, 16);
else
c->Eax = ReadPort((UINT16)c->Edx, 32);
c->Eip += 1 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xE6: // OUT imm8, AL
WritePort(instr[1], 8, (UINT8)c->Eax);
c->Eip += 2 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xE7: // OUT imm8, (E)AX
if (OperandSizeIs16Bit)
WritePort(instr[1], 16, (UINT16)c->Eax);
else
WritePort(instr[1], 32, c->Eax);
c->Eip += 2 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xEE: // OUT DX, AL
WritePort((UINT16)c->Edx, 8, (UINT8)c->Eax);
c->Eip += 1 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
case 0xEF: // OUT DX, (E)AX
if (OperandSizeIs16Bit)
WritePort((UINT16)c->Edx, 16, (UINT16)c->Eax);
else
WritePort((UINT16)c->Edx, 32, c->Eax);
c->Eip += 1 + OperandSizeIs16Bit;
return EXCEPTION_CONTINUE_EXECUTION;
default:
return EXCEPTION_CONTINUE_SEARCH;
}
default:
return EXCEPTION_CONTINUE_SEARCH;
}
}
int main(void)
{
__try
{
outp(0x278, 0x00);
printf("portb=0x%X\n", inp(0));
outp(0x278, 0x55);
printf("portb=0x%X\n", inp(0));
outp(0x278, 0xFF);
printf("portb=0x%X\n", inp(0));
outpw(0x278, 0xAAAA);
printf("portw=0x%X\n", inpw(0));
outpd(0x278, 0x12345678);
printf("portd=0x%X\n", inpd(0));
outpw(0x278, 0xAAAA);
outp(0x278, 0x55);
printf("portd=0x%X\n", inpd(0));
}
__except(IoExceptionFilter(GetExceptionInformation()))
{
}
return 0;
}输出:
C:\>PortEmu.exe
portb=0x0
portb=0x55
portb=0xFF
portw=0xAAAA
portd=0x12345678
portd=0x1234AA55只需更改ReadPort()和WritePort()的实现,以做一些更有用或更符合打印机端口操作的事情。
发布于 2011-10-18 02:25:56
看起来dosbox可能不支持没有patches的并行端口。此外,virtualbox似乎还会doesn't yet support并行端口。但是,即使它们确实支持并行端口,你仍然需要在另一端有一些东西-要么是你主机操作系统上的调试驱动程序,要么是像USB转并行适配器这样的东西(在通常的零售商那里可以买到)。
你能说更多关于你为什么想了解parallel port的原因吗?正如你所说的,它在2011年是一个几乎已经死亡的界面。如果您真的想使用低级并行式I/O,那么您可能需要研究一下Arduino平台。
发布于 2011-10-18 03:19:27
我暂时不知道有什么软件,但如果Linux Wine在支持并行端口方面做得很好,我不会感到惊讶,尽管我不知道在缺乏物理LPT的情况下,它是否可以完全虚拟化。
当不得不做遗留兼容性测试时,我总是惊讶地发现,找到一台便宜的旧PC是多么容易。
遗憾的是,这是高度以地区为中心的,但请访问当地的转售店或计算机回收操作。例如,在波特兰,我会访问Free Geek和Goodwill,不希望花费超过15美元。如果你的时间很有价值,这可能比胡乱摆弄模拟器,然后想知道它们有多好更实惠。
https://stackoverflow.com/questions/7795739
复制相似问题