[PC] Program w EPROM - making of
: sobota 01 cze 2019, 21:47
Terminal ANSI
Wyrzucanie sprawnych rzeczy na śmietnik zawsze boli. Szczególnie dotyczy to urządzeń elektronicznych. Zamiast powiększać góry śmieci, można znaleźć jakieś sensowne zastosowanie dla urządzeń, dla których spokojne oczekiwanie na niebyt jest jedynym celem. Sam mam w szufladzie kilka starych płyt po komputerach PC. W dzisiejszych czasach, przy wyśrubowanych wymaganiach stawianych przez systemy operacyjne, takie płyty nie mają żadnych szans na użycie. Jednak bazując na tych płytach w sensie sprzętowym, możliwe jest wykorzystanie ich w innym zastosowaniu niż zostały zaprojektowane. Wystarczy popatrzeć ile jest budowanych urządzeń bazujących przykładowo na mikrokontrolerach AVR. W porównaniu z płytą PC, środowisko oferowane przez wspomniane mikrokontrolery w wielu przypadkach jest dosyć ubogie. Owszem, takie mikrokontrolery mają rozbudowany zestaw peryferii, ale w porównaniu z zasobami pamięci RAM, to porównywanie nie ma żadnego sensu, małe procki odpadają w przedbiegach. Szeroka gama wyposażenia dodatkowego, jak klawiatura czy karta video również bije mikrokontrolery na głowę.
Więc co stoi na przeszkodzie by zrobić selektywny odzysk?
Prawdę mówiąc, nic. Posiłkując się standardowym kompem, można „wyprodukować” program do umieszczenia w pamięci EPROM dla płyty PC, czyli zastąpić standardowy BIOS swoim własnym programem. Takie rozwiązanie, poza w jakimś sensie funkcją odśmiecającą świat, ma parę fajnych zalet. Wystarczy wspomnieć, że po włączeniu takie urządzenie nie musi bootować z dysku lub sieci. Jest gotowe do działania natychmiast i to jest cenne.
Stworzyć program dla kompa PC to obecnie żadna filozofia. Codziennie powstają tony różnego oprogramowania do uruchomienia pod kontrolą jakiegokolwiek systemu (DOS, windoza, linuch czy cokolwiek innego). Tutaj wszystko jest proste. Inaczej rzecz ma się w przypadku programów do umieszczenia w pamięci EPROM (lub FLASH). Tu obowiązuje troszkę inna filozofia niż ta, do której jesteśmy przyzwyczajeni na co dzień. Ignorowanie pewnych zasad skutkuje tym, że coś może nie zadziałać. Nawet jeżeli program jest „wytrzepany” przykładowo pod DOS, tu może nie zadziałać. Nie mam tu na myśli tego, że zostanie użyta jakaś funkcja DOS'owa, których nie ma w środowisku w przypadku programu zawartego w EPROM. Można latami lampić się na kawałek kodu i nie dostrzegać problemu. Ot choćby to, że pamięć EPROM (oraz FLASH) są pamięciami tylko do odczytu, więc nie da się do nich zapisać. Jakie są gwarancje, że kompilator nam nie „sprzedał” jakiejś niespodzianki?
Nie ma żadnego systemu operacyjnego, więc wszystko należy zrealizować samemu a to nie jest wbrew pozorom takie skomplikowane. Każde zagadnienie da się rozwiązać i można zastosować każdą koncepcję. To jak jazda na rolkach bez trzymanki.
Trochę filozofii
W każdym procku istotny jest stan po sygnale reset. Jakkolwiek jest on wygenerowany (współczesne mikrokontrolery często pozwalają skonfigurować nóżkę reset do funkcji pinu jakiegoś portu, co pozbawia układ wejścia reset) zawsze występuje ciąg czynności realizowanych przy okazji tej operacji. W przypadku procka z rodziny 86 (8086, 8088, 80186, 80286, 80383 itp.) rozpoczęcie realizacji programu zaczyna się od wpisania w rejestr CS (code segment) wartości FFFF hex oraz do rejestru IP (instruction pointer) wartości 0. Dla tych, co nie mają świadomości o poruszanych tematach, informuję, że wymienione procki mają różne tryby pracy: tryb rzeczywisty i tryb ochronny (protekcyjny). Procek po sygnale reset rusza w trybie rzeczywistym (wszystkie dalsze rozważania dotyczą tego trybu) spod adresu CS:IP = FFFF:0 hex. W sensie adresu wystawionego na szynie adresowej jest to: FFFF0 hex czyli 16 bajtów przed końcem pierwszego megabajta w przestrzeni adresowej. W tamtym miejscu ma być zawarta pierwsza instrukcja do wykonania przez procesor.
Realny adres wystawiony na szynę adresową wynika ze złożenia zawartości dwóch rejestrów adresowych. W zależności od charakteru instrukcji używane są różne rejestry, jednak zawsze występuje rejestr typu segmentowego (CS – w przypadku instrukcji skoków, wywołania, SS – w przypadku operacji na stosie) oraz ofsetowego (IP – w przypadku instrukcji skoków, SP – w przypadku stosu). Zapisuje się to symbolicznie jako CS:IP (finalnie wskazuje miejsce w pamięci, gdzie znajduje się wykonanie programu). Podobnie jest w przypadku stosu: mamy rejestr segmentowy SS i rejestr ofsetowy SP. Operacja dotycząca stosu jest adresowana jako SS:SP. To złożenie adresowe przekłada się na adres fizyczny w następujący sposób: CS << 4 + IP (w przypadku skoku lub wywołania procedury), ogólnie: rejestr segmentowy przesunięty o 4 bity i dodany (arytmetycznie) rejestr ofsetowy (łatwo zauważyć, że istnieje wiele różnych kombinacji zawartości rejestrów dających finalnie ten sam adres fizyczny – istnieje duża różnorodność). Oba rejestry są 16-bitowe i ta operacja finalnie daje 20-bitowy adres na szynie adresowej (w trybie pracy Real Mode, w trybie protekcyjnym wygląda to inaczej). Tu warto pamiętać, że procesory 8086 (8088) miały tylko tryb pracy Real Mode. Procesory 80286 miały dodany tryb pracy protekcyjny, ale raczej należy ten model procka uznać za trochę nieudany. Tryb ochronny (protekcyjny) spełniający w pełni swoją rolę pojawił się dopiero w modelu 80386. Oczywiście każdy z tych procków dysponuje trybem real mode i w rzeczywistości startuje w tym trybie po sygnale reset. Przejście do trybu protekcyjnego następuje w wyniku wykonania odpowiedniej instrukcji i nie ma już z niego powrotu (aby wrócić potrzebna jest pomoc z zewnątrz i taką funkcję realizuje między innymi procesor od klawiatury).
Wektory przerwań procka są zawarte w odpowiedniej tabeli. Jest ona umieszczona w pamięci w ściśle określonym adresie (0:0 co daje fizycznie adres 0). Zawartych jest tam 256 wektorów przerwań. Wektor przerwania to jest adres (w sensie rejestru segmentowgo i rejestru ofsetowego – w sumie 4 bajty → cała tabela wektorów przerwań to 1kB) miejsca gdzie znajduje się prawdziwa obsługa przerwania. Tu jest inaczej niż w większości mikrokontrolerów, gdzie w odpowiednim miejscu znajduje się pierwsza instrukcja obsługi przerwania. W prockach x86 wszystkie przerwania należy traktować jako przerwania programowe i raczej trudno mówić tu o przerwaniach sprzętowych. Kontroler przerwań 8259 reagujący na przerwania sprzętowe generuje instrukcję przerwania programowego (po prostu obsługa przerwania wynikająca z reakcji na zdarzenie sprzętowe jest nierozróżnialna od przerwań software'owych.
Programy ładowane do pamięci (binarne) przykładowo pod DOS są ładowane do określonego miejsca w przestrzeni adresowej (wcale nie od zera, tam jest tabela wektorów przerwań). Oznacza to, że muszą w swoim kodzie mieć już wylinkowane adresy (przykładowo adresy skoków). Kompilator (plus linker) generując program nie są w stanie odkreślić w jakim miejscu będzie on umieszczony w fazie wykonania. Zauważmy, że nasza znakomita koleżanka tasza tworząc program dla CA80 generuje go do ściśle określonej lokacji adresowej, tam go ładuje i uruchamia. Nie ma możliwości załadowania i wykonania go w innym miejscu, to nie zadziała. W przypadku PC i procków x86 obowiązują dokładnie te same zasady. Więc jak to się dzieje, że to jakoś działa?
W DOS są dwa formaty binarnych programów wykonywalnych. Są one rozróżniane po rozszerzeniu nadanym dla pliku. Są to *.COM i *.EXE. Program COM jest wylinkowany niejako relatywnie, to znaczy zadziała poprawnie nawet jeżeli będzie załadowany i uruchomiony w wielu miejscach przestrzeni adresowej. Dlaczego? Program COM jest programem jednosegmentowym, czyli mieści się w obrębie adresowym jednego segmentu. Oznacza to, że wszystko jest adresowane relatywnie w obrębie rejestru segmentowego a lokacje adresowa są determinowane jedynie zawartością rejestru ofsetowego. Procesor dysponuje dwoma wariantami instrukcji skoku (wywołania procedury): z adresem długim (far, czyli w kodzie instrukcji skoku podana jest nowa zawartość rejestru segmentowego i rejestru ofsetowego → adres docelowy skoku jest 16-bitów [ofset] i 16 bitów [segment] w sumie 4 bajty) lub krótkim (near, czyli w kodzie instrukcji skoku podana jest nowa zawartość tylko rejestru ofsetowego → adres docelowy nadal wyznacza para rejestrów CS [który nie uległ zmianie] i IP [podany jako operand instrukcji]). Limituje to oczywiście wielkość programu typu COM do maksymalnie 64k. Jeżeli teraz ktoś (przykładowo DOS) załaduje program COM do pamięci na określoną lokację w przestrzeni i go uruchomi (poprzez przykładowo długi skok, to ten COM dalej już sam pojedzie). W takiej sytuacji wszystkie elementy są znane. DOS wie gdzie załadował program (czyli zna wartość rejestru segmentowego odpowiadającą dla programu), początek programu COM jest w stałym miejscu: ORG 100H. Wystarczy wykonać JMP <segm>:100H i już pojedzie (<segm> to miejsce gdzie został załadowany program). Jeżeli w programie nie będzie użytych instrukcji z długim adresem to program się nie zgubi. Dokładnie to istnieje możliwość poznania własnego przeznaczenia, czyli program może dowiedzieć się jaką ma zawartość rejestru segmentowego i w dalszej konsekwencji może już manipulować tą informacją. Przedstawione wyżej (skrótowe) informację są trochę uproszczone, gdyż przed uruchomieniem programu konieczne jest określenie większej liczby rejestrów segmentowych: minimum to jeszcze rejestr segmentowy danych (DS), rejestr segmentowy stosu (SS). Miejsce w przestrzeni adresowej, gdzie może być załadowany program nie jest w pełni dowolne. Gradacja początku programu wynosi 1 paragraf (jest to taka jednostka o wielkości 16 bajtów) → adres fizycznego początku programu musi być podzielny przez 16.
Inaczej sprawa ma się w przypadku programów typu EXE. Taki program może być wielosegmentowy i wymaga w trakcie ładowania do pamięci niewielkich korekt adresowych. Na razie nie będę tego tematu rozwijał i zostawię go na później.
Na początek najprostsza forma rozwiązania opierająca się na przepisaniu programu typu COM do pamięci RAM i tam uruchomienie go.
Po zaprogramowaniu pamięci EPROM, włożeniu kostki do podstawki, sprzęcior jest gotowy do użycia. Jest to płyta PC AT ze złączami typu ISA i prockiem 80386. Ma złącze zasilające w innym standardzie niż współczesne kompy, więc z racji, że aktualnie nie mam sprawnego zasilacza typu AT, dorobiłem przejściówkę. Nie jest to wielki problem, stary standard jest podzbiorem nowego. Zachowując kolorki kabelków można adaptować zasilacz ATX do współdziałania z komputerem AT (napięcie +3,3V nie jest używane, więc można je pominąć). Nie należy zapominać o kabelku „Power Good”, jest istotny. Może się tak zdarzyć, że zasilacz ATX nie ma napięcia -5V (biały kabelek w zasilaczu), nie jest to problem. Można zignorować. To napięcie już od dawna nie jest wykorzystywane i występuje jedynie z powodów historycznych (pierwsze pamięci dynamiczne stosowane w starożytnych kompach wymagały takiego napięcia). Przy okazji do złączki przyłączyłem włącznik bistabilny (łączący kabelek zielony zasilacza z czarnym), co pozwoliło na włączanie zasilania (w czasach starożytnych nie było elektronicznego włączania zasilania i trzeba było ręcami przełożyć odpowiedni hebelek
).Program zawarty w EPROM pełni funkcję terminala ANSI. Każde naciśnięcie znaku na klawiaturze powoduje wysłanie via serial jego kodu, każdy znak przychodzący z serial jest wyświetlany na ekranie plus realizowane są specjalne funkcje ekranowe (chodzi o sekwencje sterujące zgodne ze standardem ANSI). W rzeczywistości zostały trochę poszerzone (dodano kilka funkcji nie występujących w terminalach ANSI). Z racji realizowanej funkcji, płyta główna musi zostać wyposażona w kartę grafiki VGAraz kartę multi IO, która zawiera układy transmisji szeregowej. Zastosowany egzemplarz ma dwa kanały RS232 określane jako COM1 i COM2 (ten drugi to ma nawet złącze typu DB25, w gruncie rzeczy to oba kanały są na smyczce na GOLDPIN, więc co się tam przyłączy, to się ma). Dodatkowo jest port drukarkowy typu CENTRONIX.Razem to się prezentuje następująco:Po odpaleniu:Tu w trakcie prac „zepsuł mi się monitor”. Nie żebym się wkurzył i ze złości czymś w niego rzucił. Po prostu matryca sama wzięła i pękła a ponieważ „ciekłe kryształy” nie wyciekły jeszcze do końca, to jakoś tam działa. Będę musiał zmienić na nowy (tylko jak to powiedzieć: nowych w formacie 3:4 nie ma, więc może tak: na nowy z odzysku).
Program do EPROM (jest w formacie binarnym, nie intel-hex gdyż w tamtych czasach nie umiałem przetwarzać takich plików, a program do EPROM jest wygenerowany przez oryginalne autorskie oprogramowanie z tamtych czasów): (raczej powinien pasować do większości płyt z prockiem 386).
Wyrzucanie sprawnych rzeczy na śmietnik zawsze boli. Szczególnie dotyczy to urządzeń elektronicznych. Zamiast powiększać góry śmieci, można znaleźć jakieś sensowne zastosowanie dla urządzeń, dla których spokojne oczekiwanie na niebyt jest jedynym celem. Sam mam w szufladzie kilka starych płyt po komputerach PC. W dzisiejszych czasach, przy wyśrubowanych wymaganiach stawianych przez systemy operacyjne, takie płyty nie mają żadnych szans na użycie. Jednak bazując na tych płytach w sensie sprzętowym, możliwe jest wykorzystanie ich w innym zastosowaniu niż zostały zaprojektowane. Wystarczy popatrzeć ile jest budowanych urządzeń bazujących przykładowo na mikrokontrolerach AVR. W porównaniu z płytą PC, środowisko oferowane przez wspomniane mikrokontrolery w wielu przypadkach jest dosyć ubogie. Owszem, takie mikrokontrolery mają rozbudowany zestaw peryferii, ale w porównaniu z zasobami pamięci RAM, to porównywanie nie ma żadnego sensu, małe procki odpadają w przedbiegach. Szeroka gama wyposażenia dodatkowego, jak klawiatura czy karta video również bije mikrokontrolery na głowę.
Więc co stoi na przeszkodzie by zrobić selektywny odzysk?
Prawdę mówiąc, nic. Posiłkując się standardowym kompem, można „wyprodukować” program do umieszczenia w pamięci EPROM dla płyty PC, czyli zastąpić standardowy BIOS swoim własnym programem. Takie rozwiązanie, poza w jakimś sensie funkcją odśmiecającą świat, ma parę fajnych zalet. Wystarczy wspomnieć, że po włączeniu takie urządzenie nie musi bootować z dysku lub sieci. Jest gotowe do działania natychmiast i to jest cenne.
Stworzyć program dla kompa PC to obecnie żadna filozofia. Codziennie powstają tony różnego oprogramowania do uruchomienia pod kontrolą jakiegokolwiek systemu (DOS, windoza, linuch czy cokolwiek innego). Tutaj wszystko jest proste. Inaczej rzecz ma się w przypadku programów do umieszczenia w pamięci EPROM (lub FLASH). Tu obowiązuje troszkę inna filozofia niż ta, do której jesteśmy przyzwyczajeni na co dzień. Ignorowanie pewnych zasad skutkuje tym, że coś może nie zadziałać. Nawet jeżeli program jest „wytrzepany” przykładowo pod DOS, tu może nie zadziałać. Nie mam tu na myśli tego, że zostanie użyta jakaś funkcja DOS'owa, których nie ma w środowisku w przypadku programu zawartego w EPROM. Można latami lampić się na kawałek kodu i nie dostrzegać problemu. Ot choćby to, że pamięć EPROM (oraz FLASH) są pamięciami tylko do odczytu, więc nie da się do nich zapisać. Jakie są gwarancje, że kompilator nam nie „sprzedał” jakiejś niespodzianki?
Nie ma żadnego systemu operacyjnego, więc wszystko należy zrealizować samemu a to nie jest wbrew pozorom takie skomplikowane. Każde zagadnienie da się rozwiązać i można zastosować każdą koncepcję. To jak jazda na rolkach bez trzymanki.
Trochę filozofii
W każdym procku istotny jest stan po sygnale reset. Jakkolwiek jest on wygenerowany (współczesne mikrokontrolery często pozwalają skonfigurować nóżkę reset do funkcji pinu jakiegoś portu, co pozbawia układ wejścia reset) zawsze występuje ciąg czynności realizowanych przy okazji tej operacji. W przypadku procka z rodziny 86 (8086, 8088, 80186, 80286, 80383 itp.) rozpoczęcie realizacji programu zaczyna się od wpisania w rejestr CS (code segment) wartości FFFF hex oraz do rejestru IP (instruction pointer) wartości 0. Dla tych, co nie mają świadomości o poruszanych tematach, informuję, że wymienione procki mają różne tryby pracy: tryb rzeczywisty i tryb ochronny (protekcyjny). Procek po sygnale reset rusza w trybie rzeczywistym (wszystkie dalsze rozważania dotyczą tego trybu) spod adresu CS:IP = FFFF:0 hex. W sensie adresu wystawionego na szynie adresowej jest to: FFFF0 hex czyli 16 bajtów przed końcem pierwszego megabajta w przestrzeni adresowej. W tamtym miejscu ma być zawarta pierwsza instrukcja do wykonania przez procesor.
Realny adres wystawiony na szynę adresową wynika ze złożenia zawartości dwóch rejestrów adresowych. W zależności od charakteru instrukcji używane są różne rejestry, jednak zawsze występuje rejestr typu segmentowego (CS – w przypadku instrukcji skoków, wywołania, SS – w przypadku operacji na stosie) oraz ofsetowego (IP – w przypadku instrukcji skoków, SP – w przypadku stosu). Zapisuje się to symbolicznie jako CS:IP (finalnie wskazuje miejsce w pamięci, gdzie znajduje się wykonanie programu). Podobnie jest w przypadku stosu: mamy rejestr segmentowy SS i rejestr ofsetowy SP. Operacja dotycząca stosu jest adresowana jako SS:SP. To złożenie adresowe przekłada się na adres fizyczny w następujący sposób: CS << 4 + IP (w przypadku skoku lub wywołania procedury), ogólnie: rejestr segmentowy przesunięty o 4 bity i dodany (arytmetycznie) rejestr ofsetowy (łatwo zauważyć, że istnieje wiele różnych kombinacji zawartości rejestrów dających finalnie ten sam adres fizyczny – istnieje duża różnorodność). Oba rejestry są 16-bitowe i ta operacja finalnie daje 20-bitowy adres na szynie adresowej (w trybie pracy Real Mode, w trybie protekcyjnym wygląda to inaczej). Tu warto pamiętać, że procesory 8086 (8088) miały tylko tryb pracy Real Mode. Procesory 80286 miały dodany tryb pracy protekcyjny, ale raczej należy ten model procka uznać za trochę nieudany. Tryb ochronny (protekcyjny) spełniający w pełni swoją rolę pojawił się dopiero w modelu 80386. Oczywiście każdy z tych procków dysponuje trybem real mode i w rzeczywistości startuje w tym trybie po sygnale reset. Przejście do trybu protekcyjnego następuje w wyniku wykonania odpowiedniej instrukcji i nie ma już z niego powrotu (aby wrócić potrzebna jest pomoc z zewnątrz i taką funkcję realizuje między innymi procesor od klawiatury).
Wektory przerwań procka są zawarte w odpowiedniej tabeli. Jest ona umieszczona w pamięci w ściśle określonym adresie (0:0 co daje fizycznie adres 0). Zawartych jest tam 256 wektorów przerwań. Wektor przerwania to jest adres (w sensie rejestru segmentowgo i rejestru ofsetowego – w sumie 4 bajty → cała tabela wektorów przerwań to 1kB) miejsca gdzie znajduje się prawdziwa obsługa przerwania. Tu jest inaczej niż w większości mikrokontrolerów, gdzie w odpowiednim miejscu znajduje się pierwsza instrukcja obsługi przerwania. W prockach x86 wszystkie przerwania należy traktować jako przerwania programowe i raczej trudno mówić tu o przerwaniach sprzętowych. Kontroler przerwań 8259 reagujący na przerwania sprzętowe generuje instrukcję przerwania programowego (po prostu obsługa przerwania wynikająca z reakcji na zdarzenie sprzętowe jest nierozróżnialna od przerwań software'owych.
Programy ładowane do pamięci (binarne) przykładowo pod DOS są ładowane do określonego miejsca w przestrzeni adresowej (wcale nie od zera, tam jest tabela wektorów przerwań). Oznacza to, że muszą w swoim kodzie mieć już wylinkowane adresy (przykładowo adresy skoków). Kompilator (plus linker) generując program nie są w stanie odkreślić w jakim miejscu będzie on umieszczony w fazie wykonania. Zauważmy, że nasza znakomita koleżanka tasza tworząc program dla CA80 generuje go do ściśle określonej lokacji adresowej, tam go ładuje i uruchamia. Nie ma możliwości załadowania i wykonania go w innym miejscu, to nie zadziała. W przypadku PC i procków x86 obowiązują dokładnie te same zasady. Więc jak to się dzieje, że to jakoś działa?
W DOS są dwa formaty binarnych programów wykonywalnych. Są one rozróżniane po rozszerzeniu nadanym dla pliku. Są to *.COM i *.EXE. Program COM jest wylinkowany niejako relatywnie, to znaczy zadziała poprawnie nawet jeżeli będzie załadowany i uruchomiony w wielu miejscach przestrzeni adresowej. Dlaczego? Program COM jest programem jednosegmentowym, czyli mieści się w obrębie adresowym jednego segmentu. Oznacza to, że wszystko jest adresowane relatywnie w obrębie rejestru segmentowego a lokacje adresowa są determinowane jedynie zawartością rejestru ofsetowego. Procesor dysponuje dwoma wariantami instrukcji skoku (wywołania procedury): z adresem długim (far, czyli w kodzie instrukcji skoku podana jest nowa zawartość rejestru segmentowego i rejestru ofsetowego → adres docelowy skoku jest 16-bitów [ofset] i 16 bitów [segment] w sumie 4 bajty) lub krótkim (near, czyli w kodzie instrukcji skoku podana jest nowa zawartość tylko rejestru ofsetowego → adres docelowy nadal wyznacza para rejestrów CS [który nie uległ zmianie] i IP [podany jako operand instrukcji]). Limituje to oczywiście wielkość programu typu COM do maksymalnie 64k. Jeżeli teraz ktoś (przykładowo DOS) załaduje program COM do pamięci na określoną lokację w przestrzeni i go uruchomi (poprzez przykładowo długi skok, to ten COM dalej już sam pojedzie). W takiej sytuacji wszystkie elementy są znane. DOS wie gdzie załadował program (czyli zna wartość rejestru segmentowego odpowiadającą dla programu), początek programu COM jest w stałym miejscu: ORG 100H. Wystarczy wykonać JMP <segm>:100H i już pojedzie (<segm> to miejsce gdzie został załadowany program). Jeżeli w programie nie będzie użytych instrukcji z długim adresem to program się nie zgubi. Dokładnie to istnieje możliwość poznania własnego przeznaczenia, czyli program może dowiedzieć się jaką ma zawartość rejestru segmentowego i w dalszej konsekwencji może już manipulować tą informacją. Przedstawione wyżej (skrótowe) informację są trochę uproszczone, gdyż przed uruchomieniem programu konieczne jest określenie większej liczby rejestrów segmentowych: minimum to jeszcze rejestr segmentowy danych (DS), rejestr segmentowy stosu (SS). Miejsce w przestrzeni adresowej, gdzie może być załadowany program nie jest w pełni dowolne. Gradacja początku programu wynosi 1 paragraf (jest to taka jednostka o wielkości 16 bajtów) → adres fizycznego początku programu musi być podzielny przez 16.
Inaczej sprawa ma się w przypadku programów typu EXE. Taki program może być wielosegmentowy i wymaga w trakcie ładowania do pamięci niewielkich korekt adresowych. Na razie nie będę tego tematu rozwijał i zostawię go na później.
Na początek najprostsza forma rozwiązania opierająca się na przepisaniu programu typu COM do pamięci RAM i tam uruchomienie go.
Po zaprogramowaniu pamięci EPROM, włożeniu kostki do podstawki, sprzęcior jest gotowy do użycia. Jest to płyta PC AT ze złączami typu ISA i prockiem 80386. Ma złącze zasilające w innym standardzie niż współczesne kompy, więc z racji, że aktualnie nie mam sprawnego zasilacza typu AT, dorobiłem przejściówkę. Nie jest to wielki problem, stary standard jest podzbiorem nowego. Zachowując kolorki kabelków można adaptować zasilacz ATX do współdziałania z komputerem AT (napięcie +3,3V nie jest używane, więc można je pominąć). Nie należy zapominać o kabelku „Power Good”, jest istotny. Może się tak zdarzyć, że zasilacz ATX nie ma napięcia -5V (biały kabelek w zasilaczu), nie jest to problem. Można zignorować. To napięcie już od dawna nie jest wykorzystywane i występuje jedynie z powodów historycznych (pierwsze pamięci dynamiczne stosowane w starożytnych kompach wymagały takiego napięcia). Przy okazji do złączki przyłączyłem włącznik bistabilny (łączący kabelek zielony zasilacza z czarnym), co pozwoliło na włączanie zasilania (w czasach starożytnych nie było elektronicznego włączania zasilania i trzeba było ręcami przełożyć odpowiedni hebelek
Program do EPROM (jest w formacie binarnym, nie intel-hex gdyż w tamtych czasach nie umiałem przetwarzać takich plików, a program do EPROM jest wygenerowany przez oryginalne autorskie oprogramowanie z tamtych czasów): (raczej powinien pasować do większości płyt z prockiem 386).