在我的计算机网络课程中,我们应该通过使用本机寄存器来学习并行端口编程(比如使用outportb之类的命令)。我没有并行端口(因为我住在2011年)但想要练习程序(我使用dosbox安装了旧的turboc 3 IDE)。是否存在模拟并行端口的程序,如this程序模拟串口?
答案 0 :(得分:2)
由于环境是假的,即你没有实际的端口可以使用,你也可以模拟程序中的端口功能。
以下是使用 Structured Exception Handling (SEH)在Windows中执行此操作的方法:
// 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()
的实施,即可根据打印机端口操作执行更有用或更多功能。
答案 1 :(得分:0)
看起来dosbox可能不支持没有patches的并行端口。它还显示virtualbox也doesn't yet support个并行端口。但即使他们确实支持并行端口,你仍然需要另一端的东西 - 主机操作系统上的调试驱动程序,或USB转并行适配器(通常在零售商处可用)。
您能详细说明为什么要了解parallel port吗?正如你的建议,它在2011年是一个基本上死机的界面。如果您真的想要使用低级并行风格的I / O,您可能需要查看Arduino平台。
答案 2 :(得分:0)
我不知道有任何软件,但是如果Linux Wine在支持并行端口方面做得很好,我也不会感到惊讶,虽然我不知道它是否可以在缺少时完全虚拟化物理LPT。
当必须进行遗留兼容性测试时,我总是惊讶于找到一台便宜的旧PC是多么容易。
唉,这是一个高度区域性的,但访问当地的转售商店或电脑回收业务。例如,在波特兰,我会访问Free Geek和Goodwill,并且不会期望支付超过15美元。如果你的时间价值很高,这可能比搞乱仿真器更实惠,然后想知道它们有多好。