2011-10-17 34 views
9

W moim kursie sieci komputerowych powinniśmy nauczyć się programowania portów równoległych za pomocą natywnych rejestrów (jak przy użyciu poleceń typu outportb). Nie mam portu równoległego (ponieważ mieszkam w 2011 r.), Ale chcę ćwiczyć programy (zainstalowałem stary Turbo 3 IDE przy użyciu dosbox). Czy istnieje program emulujący porty równoległe, na przykład program this emulujący porty szeregowe?Wirtualny emulator portu równoległego

+6

+1 dla "ponieważ mieszkam w 2011 roku" :-) –

+0

Dlaczego po prostu nie chcesz tego naśladować? Napisz własną wersję outportb(). –

+0

Jestem pewna, że ​​gdybyś poszła z 10 $, ktoś podarowałby ci starą Pentium :) – Earlz

Odpowiedz

0

Wygląda na to, że dosbox może nie obsługiwać portów równoległych bez patches. Okazuje się również, że porty równoległe mają także różne porty. Ale nawet gdyby obsługiwały porty równoległe, nadal potrzebowałbyś czegoś na drugim końcu - albo sterownika debugowania w systemie operacyjnym hosta, albo czegoś w rodzaju adaptera USB na port równoległy (dostępny u zwykłych sprzedawców).

Czy możesz powiedzieć więcej o tym, dlaczego chcesz się dowiedzieć o parallel port? Jest to najczęściej martwy interfejs w 2011 roku, jak sugerujesz. Jeśli naprawdę chcesz grać z niskopoziomowymi I/O w układzie równoległym, możesz zajrzeć na platformę Arduino.

+0

Nie chcę bawić się gównem, tylko że są na nim 3 zadania laboratoryjne i nie chcę iść do laboratorium, w którym przechowywane są stare systemy Windows 98. –

+0

wystarczająco dobrze - ale czy trzeba migać trochę diod LED podłączonych do portu równoległego, wydrukować jakieś rzeczy lub coś zupełnie innego? – ObscureRobot

+0

dwa komputery muszą rozmawiać za pomocą portów szeregowych –

0

Nie znam żadnego oprogramowania od ręki, choć nie zdziwiłbym się, gdyby Linux Wine dobrze poradził sobie z obsługą portu równoległego, chociaż nie wiem, czy można go całkowicie zwirtualizować, gdy brakuje mu fizycznego LPT.

Kiedy muszę przeprowadzić testy zgodności ze starszymi wersjami, zawsze jestem zaskoczony, jak łatwo jest znaleźć stary komputer tanio.

Niestety, jest to wysoce skoncentrowane na regionach, ale należy odwiedzić lokalny sklep odsprzedaży lub recykling komputerowy. Na przykład w Portland odwiedziłbym Free Geek i wartość firmy i nie spodziewam się zapłacić więcej niż 15 USD. Jeśli twój czas jest wart wiele, jest to prawdopodobnie bardziej przystępne niż zakłócanie pracy z emulatorami, a następnie zastanawiasz się, jakie one są dobre.

2

Ponieważ środowisko jest fałszywe, to znaczy, że nie masz rzeczywistego portu do zabawy, możesz równie dobrze emulować funkcjonalność portu w twoim programie.

Oto jak to zrobić w systemie Windows za pomocą 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; 
} 

wyjściowa:

C:\>PortEmu.exe 
portb=0x0 
portb=0x55 
portb=0xFF 
portw=0xAAAA 
portd=0x12345678 
portd=0x1234AA55 

Wystarczy zmienić realizację ReadPort() i WritePort() zrobić coś bardziej użyteczne lub więcej zgodnie z działaniem portu drukarki.

+0

Możesz zająć się komunikacją TCP/IP za kulisami (w ReadPort() i WritePort()), aby rzeczywiście komunikować się między 2 komputerami. –