2011-10-17 91 views
9

在我的計算機網絡課程中,我們應該通過使用本地寄存器來學習並行端口編程(如使用outportb like命令)。我沒有並行端口(因爲我住在2011年),但想要練習這些程序(我使用dosbox安裝了舊的turboc 3 IDE)。是否有仿真並行端口的程序,如this程序模擬串行端口?虛擬並行端口仿真器

+6

+1「因爲我住在2011」:-) –

+0

你爲什麼不直接效仿它呢?編寫你自己的outportb()版本。 –

+0

我敢肯定,如果你以10美元的價格出行,有人會爲你的目標捐贈一臺舊的奔騰車輛:) – Earlz

回答

0

看起來像dosbox可能不支持並行端口沒有patches。它也出現virtualboxdoesn't yet support並行端口。但即使他們確實支持並行端口,你仍然需要另一端的東西 - 或者是主機操作系統上的調試驅動程序,或者是USB到並行適配器(可在常用零售商處購買)。

你可以多說一下你爲什麼想了解parallel port?正如你所建議的那樣,它在2011年是一個大部分已死的界面。如果你真的想玩低級別的並行式I/O,你可能需要查看Arduino平臺。

+0

我不想玩狗屎,只是有3個實驗室的任務,我不想去舊的Windows 98系統保存的實驗室。 –

+0

夠公平 - 但是你需要閃爍一些LED插入並行端口,打印出一些東西,或完全是其他東西? – ObscureRobot

+0

兩臺計算機需要使用串口進行通訊 –

0

我不知道有什麼軟件可以使用,但如果Linux Wine在支持並行端口方面做得很好,我不會感到驚訝,但我不知道在缺少物理LPT時它是否可以完全虛擬化。

當需要進行傳統兼容性測試時,我總是驚訝於找到一臺舊電腦是多麼容易。

唉,這是高度以地區爲中心,但訪問當地的轉售商店或電腦回收操作。例如,在波特蘭,我會訪問Free Geek和商譽,並不期望支付超過15美元。如果你的時間價值很高,那麼這可能比用模擬器搞亂更實惠,然後想知道它們有多好。

2

既然環境是假的,也就是說你沒有真正的端口來玩,你也可以在你的程序中模擬端口功能。

下面介紹如何使用做到這一點在Windows Structured Exception Handling(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()實施做一些更有用或更符合打印機端口操作。

+0

您可以在後臺(在ReadPort()和WritePort())中進行一些TCP/IP通訊,以實現2臺PC之間的實際通訊。 –