Intel 8080 kit
Re: Intel 8080 kit
Bardziej miałem na myśli pełne 16-bit, więc osobiście poszedłbym w stronę V50, bo jeszcze jest dostępny (V40 też niczego sobie, to taki V20 na sterydach). Dlaczego taki kaprys? Optymalizuję port Basic z Z80 na Z8000, męcząc "testem" Mandelbrot i po zmianach wyszło mi, że Z8002 taktowany 6MHz deklasuje V20 z zegarem 10MHz zarówno w trybie 8080 jak i x86. Dlatego chcę sprawdzić czy to jest wina 8-bitowej szyny, czy te procesory są naprawdę aż tak "biedne", czy może moja optymalizacja jest lepsza, niż oryginalny soft Microsoft na x86. To dużo pytań, bez odpowiedzi.
Re: Intel 8080 kit
tapy pisze:Bardziej miałem na myśli pełne 16-bit, więc osobiście poszedłbym w stronę V50, bo jeszcze jest dostępny (V40 też niczego sobie, to taki V20 na sterydach).
V50 to już mikrokontroler z peryferiami w środku. Odpowiednikiem 8086 jest V30. Mam nawet płytę z PC/XT z tym procesorem. Fajnie byłoby znowu się pobawić. Niestety padła mi klawiatura XT, więc jest mały kłopot.
"If A = success, then the formula is A = X + Y + Z.
X is work. Y is play. Z is keep your mouth shut."A. Einstein
X is work. Y is play. Z is keep your mouth shut."A. Einstein
Re: Intel 8080 kit
Obsługa układu 8255
Wspomniany układ jest bardzo popularnym programowalnym portem równoległym. Zawiera w sobie dwa porty PORTA oraz PORTB jako porty 8-bitowe, które można skonfigurować do pracy jako wejście albo jako wyjście (oba w sposób niezależny). Do tego dochodzi kolejny port (PORTC), który może być podzielony na dwa 4-bitowe, z których każda połówka ma możliwość niezależnego skonfigurowania kierunku pracy. Dodatkowo istnieje możliwość manipulowania pojedynczymi bitami PORTC. Nad tym wszystkim „panuje” rejestr sterujący: zapisy do tego rejestru definiują tryb i kierunek pracy jak również odpowiednie zapisy manipulują pojedynczymi bitami (w zakresie ustawienia na stan jedynki jak i zera). Te dwa podstawowe rodzaje poleceń są rozróżniane jednym bitem w wysyłanych do portu kontrolnego danych: najbardziej znaczący bit = 1 to zapis dotyczący trybu i kierunku pracy wszystkich portów. W sytuacji gdy ten bit = 0, zapis dotyczy ustawienia/zerowania wskazanego bitu PORTC. Ta cecha została wykorzystana w obsłudze alfanumerycznego wyświetlacza LCD jak i do obsługi klawiatury. PORTA i połowa PORTC obsługuje moduł LCD, PORTB i druga połowa PORTC obsługuje klawiaturę matrycową. W przypadku modułu LCD, kierunek pracy PORTA jest konfigurowany w zależności od potrzeb (zapis danych oraz poleceń do LCD to wyjście, odczyt statusu LCD to wejście). Dolna połowa PORTC obsługuje linie sterujące LCD (RS, RW i E). Do obsługi klawiatury, PORTB jest wczytującym stan kolumn klawiatury (zawsze wejściem) oraz druga połowa PORTC wymusza stan na liniach rzędów klawiatury (zawsze wyjściem).
Konfiguracja portów to zapis mvi a , 080h + P8255A_out… , gdzie zawsze jest ustawiony najbardziej znaczący bit (80h) i definiuje kierunki pracy portów w zależności od potrzeb. Port 8255 jest identyfikowany w systemie przez adresy w przestrzeni adresowej IO (LCDPort i KBDPort mają ten sam adres, a istnienie dwóch identyfikatorów zwiększa jedynie czytelność programu źródłowego).
Kod: Zaznacz cały
LCDPort .equ 0A0h
KBDPort .equ 0A0h
( . . . )
P8255PortA .equ 0
P8255PortB .equ 1
P8255PortC .equ 2
P8255Control .equ 3Kod: Zaznacz cały
P8255A_out .equ 0000000b
P8255A_inp .equ 0010000b
P8255B_out .equ 0000000b
P8255B_inp .equ 0000010b
P8255CL_out .equ 0000000b
P8255CH_out .equ 0000000b
P8255CL_inp .equ 0000001b
P8255CH_inp .equ 0001000b
( . . . )
SetLCDOutputDataBus ;procedure SetLCDOutputDataBus ;
;begin (* SetLCDOutputDataBus *)
; LCDPort.PortA := <output> ;
mvi a , 080h + P8255A_out + P8255B_inp + P8255CL_out + P8255CH_out
out LCDPort + P8255Control ;
ret ;end (* SetLCDOutputDataBus *) ;
;*******************************************
SetLCDInputDataBus ;procedure SetLCDInputDataBus ;
;begin (* SetLCDInputDataBus *)
; LCDPort.PortA := <input> ;
mvi a , 080h + P8255A_inp + P8255B_inp + P8255CL_out + P8255CH_out
out LCDPort + P8255Control ;
ret ;end (* SetLCDInputDataBus *) ;Linie sterujące modułem LCD (RS, RW i E) są obsługiwane przez połowę PORTC (jako wyjście) jako niezależne sterowaniu odpowiednimi liniami.
Kod: Zaznacz cały
SetLCDEBit .equ 00000101b
ClrLCDEBit .equ 00000100b
SetLCDRWBit .equ 00000011b
ClrLCDRWBit .equ 00000010b
SetLCDRSBit .equ 00000001b
ClrLCDRSBit .equ 00000000b
( . . . )
EPulse ;procedure EPulse ;
;begin (* EPulse *)
mvi a , SetLCDEBit ; LCDPort.PortC[E]:= 1 ;
out LCDPort + P8255Control ;
call LCDDelay ; LCDDelay ;
mvi a , ClrLCDEBit ; LCDPort.PortC[E]:= 0 ;
out LCDPort + P8255Control ;
ret ;end (* EPulse *) ;
;*******************************************
LCDOutC ;procedure LCDOutC ( Data[A] : byte ) ;
;begin (* LCDOutC *)
push psw ;
call SetLCDOutputDataBus ; SetLCDOutputDataBus ;
mvi a , ClrLCDRSBit ; LCDPort.PortC[RS]:= 0 ;
out LCDPort + P8255Control ;
mvi a , ClrLCDRWBit ; LCDPort.PortC[RW]:= 0 ;
out LCDPort + P8255Control ;
pop psw ;
out LCDPort + P8255PortA ; LCDPort.PortA := Data ;
call EPulse ; EPulse ;
ret ;end (* LCDOutC *) ;Jeżeli chodzi o klawiaturę, to cyklicznie w przerwaniach od czasu poszukiwany jest naciśnięty klawisz. Po wymuszeniu stanu na liniach rzędów wczytywany jest stan kolumn.
Kod: Zaznacz cały
HardvSetRowKbd ;procedure HardvSetRowKbd ( Row[A] : byte ) ;
;begin (* HardvSetRowKbd *)
; case KbdModInstance.RowCounter of
lda KbdModInstance + KbdModInstanceT.RowCounter
cpi 0 ; 0 :
jnz HvdSeRSrv_1 ;
mvi a , 00001000b ; KBDPort.PortC[4] := 0 ;
out KBDPort + P8255Control ;
mvi a , 00001011b ; KBDPort.PortC[5] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001101b ; KBDPort.PortC[6] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001111b ; KBDPort.PortC[7] := 1 ;
out KBDPort + P8255Control ;
jmp HvdSeRSrv_0 ;
HvdSeRSrv_1 ;
cpi 1 ; 1 :
jnz HvdSeRSrv_2 ;
mvi a , 00001001b ; KBDPort.PortC[4] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001010b ; KBDPort.PortC[5] := 0 ;
out KBDPort + P8255Control ;
mvi a , 00001101b ; KBDPort.PortC[6] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001111b ; KBDPort.PortC[7] := 1 ;
out KBDPort + P8255Control ;
jmp HvdSeRSrv_0 ;
HvdSeRSrv_2 ;
cpi 2 ; 2 :
jnz HvdSeRSrv_3 ;
mvi a , 00001001b ; KBDPort.PortC[4] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001011b ; KBDPort.PortC[5] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001100b ; KBDPort.PortC[6] := 0 ;
out KBDPort + P8255Control ;
mvi a , 00001111b ; KBDPort.PortC[7] := 1 ;
out KBDPort + P8255Control ;
jmp HvdSeRSrv_0 ;
HvdSeRSrv_3 ;
cpi 3 ; 3 :
jnz HvdSeRSrv_4 ;
mvi a , 00001001b ; KBDPort.PortC[4] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001011b ; KBDPort.PortC[5] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001101b ; KBDPort.PortC[6] := 1 ;
out KBDPort + P8255Control ;
mvi a , 00001110b ; KBDPort.PortC[7] := 0 ;
out KBDPort + P8255Control ;
jmp HvdSeRSrv_0 ;
HvdSeRSrv_4 ; end (* case *) ;
HvdSeRSrv_0 ;
ret ;end (* HardvSetRowKbd *) ;
( . . . )
HardvInpKbd ;function HardvInpKbd : byte[A] ;
;begin (* HardvInpKbd *)
in KBDPort + P8255PortB ; HardvInpKbd := KBDPort.PortB ;
ret ;end (* HardvInpKbd *) ;Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse
Re: Intel 8080 kit
Obsługa układu 8250
8250 to układ obsługi transmisji szeregowej z wbudowanym wewnątrz generatorem sygnału taktującego transmisją. Zawiera wewnątrz również podzielnik by uzyskać oczekiwaną prędkość transmisji. W obecnym zastosowaniu układ obsługuje jedynie przesyłanie danych (operowanie liniami modemowymi nie jest aktywowane → wejściowe dla 8250 na schemacie są sprzętowo wysterowane do stanu aktywnego). Nie zaistnieje możliwość zgłoszenia przerwania w wyniku zmian tych linii modemowych (poza tym programowo konfiguruje się ten kontroler jakie generuje on generuje).
Przed rozpoczęciem transmisji należy go odpowiednio skonfigurować. Realizuje to funkcja UARTHardwareInit z jednym parametrem, gdzie do akumulatora należy wpisać podzielnik determinujący prędkość transmisji (dla 9600 bps wynosi on 12). Dodatkowo należy wyczyścić kolejki FIFO nadajnika oraz odbiornika.
Kod: Zaznacz cały
SerialSpeed9600 .equ 12
( . . . )
mvi a , SerialSpeed9600 ; UARTHardwareInit ( SerialSpeed9600 ) ;
call UARTHardwareInit ;
call ResetSerialFifo ; ResetSerialFifo ;
( . . . )
ResetSerialFifo ;procedure ResetSerialFifo ;
;begin (* ResetSerialFifo *)
mvi a , 0 ; UARTReciev . CycFr := 0 ;
sta UARTReciev + RXDRecT.CycFr
sta UARTReciev + RXDRecT.CycTo
; UARTReciev . CycTo := 0 ;
sta UARTTransm + TXDRecT.CycFr
; UARTTransm . CycFr := 0 ;
sta UARTTransm + TXDRecT.CycTo
; UARTTransm . CycTo := 0 ;
mvi a , IdleState ; UARTTransm . State := IdleState ;
sta UARTTransm + TXDRecT.State
ret ;end (* ResetSerialFifo *) ;Zainicjowanie kontrolera 8250 do pracy wymaga wpisania podzielnika prędkości, trybu transmisji, ustawienia wyjściowych linii modemowych oraz określenia jakie przerwania są zgłaszane do 8259. Układ jest 7-komórkowy w przestrzeni adresowej, toteż poszczególne rejestry mają indywidualne adresy w obrębie 8250. Wpisanie podzielnika jest trochę „pokrętne”: w pierwszej kolejności należy wpisać do rejestru sterującego LineControlRegister (ten sam, który służy do określenia trybu transmisji) liczbę 80 hex (ma być ustawiony najbardziej znaczący bit). W kolejnym kroku wpisać do DataRegister (ten sam, do którego wysyła się i odbiera dane szeregowe) część młodszą podzielnika oraz do InterruptEnRegister (ten sam, w którym specyfikuje się generowane przerwania) część starszą (ogólnie podzielnik jest 16-bitowy a do uzyskania prędkości 600 .. 115200 bps jest on jednobajtowy). Później konfiguruje się tryb transmisji, tu używany jest N81 → 8 bitów, bez parzystości i jednym bitem stopu (słowo sterujące w żadnej kombinacji nie zawiera ustawionego najwyższego bitu, więc 8250 nie rozpozna tego zapisu jako późniejszy wpis podzielnika). Przed włączeniem przerwań warto wygarnąć z rejestrów śmieci (aktywacja może spowodować natychmiastowe wygenerowanie przerwania). Na koniec wpis do rejestru InterruptEnRegister określa jakie przerwania generuje 8250 (tu są od nadajnika oraz odbiornika).
Kod: Zaznacz cały
DataRegister .equ 0
InterruptEnRegister .equ 1
InterruptIdRegister .equ 2
LineControlRegister .equ 3
ModemControlRegister .equ 4
LineStatusRegister .equ 5
ModemStatusRegister .equ 6
( . . . )
N81Mode .equ 03h
( . . . )
UARTHardwareInit ;procedure UARTHardwareInit
( SerialSpeed[a] : byte ) ;
;begin (* UARTHardwareInit *)
push psw ;
; (* ustawienie w UART rozszerzenia
; adresowego do zaprogramowania predkosci *)
mvi a , 80h ; Serial8250+LineControlRegister := 80h ;
out Serial8250 + LineControlRegister
; (* mlodszy bajt podzielnika predkosci *)
pop psw ; Serial8250+DataRegister := SerialSpeed ;
out Serial8250 + DataRegister ;
; (* starszy bajt podzielnika predkosci *)
mvi a , 0 ; Serial8250+InterruptEnRegister := 0 ;
out Serial8250 + InterruptEnRegister
; (* zaprogramowania trybu N81Mode *)
mvi a , N81Mode
; Serial8250+LineControlRegister := N81Mode ;
out Serial8250 + LineControlRegister
; (* zaprogramowania stanu linii modemowych→
; wszystkie do stanu aktywnego *)
mvi a , 0bh ; Serial8250+ModemControlRegister := 0BH ;
out Serial8250 + ModemControlRegister
; (* wygarniecie smieci z roznych rejestrow *)
; ? := Serial8250 + LineStatusRegister ;
in Serial8250 + LineStatusRegister
; ? := Serial8250 + ModemControlRegister ;
in Serial8250 + ModemControlRegister
; ? := Serial8250 + DataRegister ;
in Serial8250 + DataRegister
; ? := Serial8250 + InterruptIdRegister ;
in Serial8250 + InterruptIdRegister
; (* zezwolenie dla UART na przerwania od:
; nadajnik + odbiornik *)
mvi a , 03h ; Serial8250 + InterruptEnRegister ; := 03H ;
out Serial8250 + InterruptEnRegister
ret ;end (* UARTHardwareInit *) ;Układ 8250 zgłasza jeden sygnał przerwania (do 8259), jednak by rozpoznać przyczynę przerwania należy wczytać rejestr InterruptIdRegister, gdzie na bitach jest określona przyczyna przerwania. Obsługa przerwania to:
Kod: Zaznacz cały
SerialInterruptService ;ISR SerialInterruptService ;
; var
; IIR : byte ;
; Port : byte ;
;begin (* SerialInterruptService *)
push psw ;
push b ;
push d ;
push h ;
SerIntSrv_0 ; repeat
; IIR := Serial8250+InterruptIdRegister & 07h ;
in Serial8250 + InterruptIdRegister
ani 07h ; if ( IIR & 0x01 ) = 0 then
cpi 1 ;
jz SerIntSrv_5 ; begin
rrc ; IIR := IIR >> 1 ;
ani 03h ;
; case IIR of
cpi 0 ; 0 : (* 0 0 - Modem status *)
jnz SerIntSrv_1 ;
; Port := Serial8250 + ModemStatusRegister ;
in Serial8250 + ModemStatusRegister
jmp SerIntSrv_0 ;
SerIntSrv_1 ; 1 : (* 0 1 - transmitter *)
cpi 1 ;
jnz SerIntSrv_2 ;
lda UARTTransm + TXDRecT.CycFr
; if UARTTransm.CycFr = UARTTransm.CycTo then
lxi h , UARTTransm + TXDRecT.CycTo
cmp m ;
jnz SerIntSrv_11 ;
mvi a , IdleState ; UARTTransm.State := IdleState ;
sta UARTTransm + TXDRecT.State
jmp SerIntSrv_0 ;
SerIntSrv_11 ; else
; begin
lda UARTTransm + TXDRecT.CycFr
; Serial8250+DataRegister:= UARTTransm.Buffer[UARTTransm.CycFr] ;
mov c , a ;
mvi b , 0 ;
lxi h , UARTTransm + TXDRecT.Buffer
dad b ;
mov a , m ;
out Serial8250 + DataRegister
; UARTTransm.CycFr:= UARTTransm.CycFr+1 ;
lxi h , UARTTransm + TXDRecT.CycFr
mov a , m ;
inr a ;
ani TXDBuffSize - 1; UARTTransm.CycFr:=UARTTransm.CycFr mod TXDBuffSize ;
mov m , a ;
jmp SerIntSrv_0 ; end ;
SerIntSrv_2 ;
cpi 2 ; 2 : (* 1 0 - reciever *)
jnz SerIntSrv_3 ; begin
lda UARTReciev + RXDRecT.CycTo
; UARTReciev.Buffer[UARTReciev.CycTo]:= Serial8250+DataRegister ;
mov c , a ;
mvi b , 0 ;
lxi h , UARTReciev + RXDRecT.Buffer
dad b ;
in Serial8250 + DataRegister
mov m , a ;
; UARTReciev.CycTo:=UARTReciev.CycTo+1 ;
lxi h , UARTReciev + RXDRecT.CycTo
mov a , m ;
inr a ;
ani RXDBuffSize - 1; UARTReciev.CycTo:=UARTReciev.CycTo mod RXDBuffSize ;
mov m , a ;
jmp SerIntSrv_0 ; end ;
SerIntSrv_3 ;
cpi 3 ; 3 : (* 1 1 - error *)
jnz SerIntSrv_0 ;
; Port := Serial8250 + LineStatusRegister ;
in Serial8250 + LineStatusRegister
jmp SerIntSrv_0 ; end (* case *) ;
; end
; else
; exit ;
; until false ;
SerIntSrv_5 ;
mvi a , 20h ; end of irq
out Controller8259 ;
pop h ;
pop d ;
pop b ;
pop psw ;
ei ;
ret ;Kontroler transmisji szeregowej opiera się o kolejki FIFO w zakresie nadawania oraz odbierania danych. Ich konstrukcje są następujące:
Kod: Zaznacz cały
IdleState .equ 0
BusyState .equ 1
;-------------------------------------------
TXDBuffSize .equ 128
RXDBuffSize .equ 16
;-------------------------------------------
TXDRecT .struct ; TXDRecT = record
CycFr .byte ; CycFr : byte ;
CycTo .byte ; CycTo : byte ;
State .byte ; State : byte ;
Buffer .byte TXDBuffSize ; Buffer : array [ 0 .. TXDBuffSize - 1 ] of byte ;
.endstruct ; end (* record *) ;
;-------------------------------------------
RXDRecT .struct ; RXDRecT = record
CycFr .byte ; CycFr : byte ;
CycTo .byte ; CycTo : byte ;
Buffer .byte RXDBuffSize ; Buffer : array [ 0 .. RXDBuffSize - 1 ] of byte ;
.endstruct ; end (* record *) ;
;-------------------------------------------
( . . . )
.org RAMSpace
UARTTransm .TXDRecT
UARTReciev .RXDRecTOdbiór danych z 8250 wchodzi do UARTRecv bezwarunkowo (najwyżej dane się nadpiszą), realizacja znajduje się w powyższej funkcji obsługi przerwania. Z tą kolejką FIFO związane są dwie funkcja: sprawdzenia, czy w FIFO są dane do odczytania (SerialDataPresent) oraz odczytanie kolejnego bajtu (GetSerial).
Kod: Zaznacz cały
SerialDataPresent ;function SerialDataPresent : boolean ;
;begin (* SerialDataPresent *)
; if UARTTransm.CycFr = UARTTransm.CycTo then
lxi h , UARTTransm + TXDRecT.CycFr
mov a , m ;
lxi h , UARTTransm + TXDRecT.CycTo
cmp m ;
jnz SerDatPre_0 ;
mvi a , 0 ; SerialDataPresent := false
ret ; esle
SerDatPre_0 ;
mvi a , 1 ; SerialDataPresent := true ;
ret ;end (* SerialDataPresent *) ;
;*******************************
GetSerial ;function GetSerial : byte[a] ;
;var
; Ch[e] : byte ;
;begin (* GetSerial *)
; Ch:=UARTTransm.Buffer[UARTTransm.CycFr] ;
lda UARTTransm + TXDRecT.CycFr
mov c , a ;
mvi b , 0 ;
lxi h , UARTTransm + TXDRecT.Buffer
dad b ;
mov e , m ;
; UARTTransm.CycFr:=(UARTTransm.CycFr+1) mod RXDBuffSize ;
lxi h , UARTTransm + TXDRecT.CycFr
mov a , m ;
inr a ;
ani RXDBuffSize - 1;
mov m , a ;
mov a , e ; GetSerial := Ch ;
ret ;end (* GetSerial *) ;Nadawanie danych do 8250 jest realizowane przez SendSerial. Jeżeli UART nie pracuje, to pierwszy znak trafia bezpośrednio do 8250 (z odnotowaniem, że jest on już zajęty), kolejne dane trafiają do kolejki FIFO. Zawsze jest sprawdzane, czy jest miejsce w FIFO na zapis nowych danych. Jeżeli jest, następuje zapis do FIFO. W przeciwnym wypadku realizowane jest oczekiwanie do chwili, gdy w buforze pojawi się wolne miejsce (w wyniku wygarniania danych z tej kolejki przez obsługę przerwania).
Kod: Zaznacz cały
SendSerial ;procedure SendSerial ( SerialCh : byte ) ;
;var
; NextInx : byte ;
;begin (* SendSerial *)
di ; DisableInt ;
push psw ;
; if UARTTransm . State = IdleState then
lxi h , UARTTransm + TXDRecT.State
mov a , m ;
cpi IdleState ;
jnz SeSer_1 ; begin
mvi a , BusyState ; UARTTransm . State := BusyState ;
mov m , a ;
pop psw ;
; Serial8250 + DataRegister := SerialCh ;
out Serial8250 + DataRegister
ei ; EnableInt ;
ret ; exit ;
; end ;
SeSer_1 ; repeat
; NextInx:=(UARTTransm.CycTo+1) mod TXDBuffSize ;
lda UARTTransm + TXDRecT.CycTo
inr a ;
ani TXDBuffSize - 1 ;
; if NextInx <> UARTTrans . CycFr then
lxi h , UARTTransm + TXDRecT.CycFr
cmp m ;
jz SeSer_2 ; begin
; UARTTrans.Buffer[UARTTrans.CycTo]:=SerialCh ;
lda UARTTransm + TXDRecT.CycTo
mov c , a ;
mvi b , 0 ;
lxi h , UARTTransm + TXDRecT.Buffer
dad b ;
pop psw ;
mov m , a ;
; UARTTransm.CycTo:=(UARTTransm.CycTo+1) mod TXDBuffSize ;
lxi h , UARTTransm + TXDRecT.CycTo
mov a , m ;
inr a ;
ani TXDBuffSize - 1 ;
mov m , a ;
ei ; EnableInt ;
ret ; exit ;
SeSer_2 ; end ;
ei ; EnableInt ;
nop ; Nop ;
nop ; Nop ;
nop ; Nop ;
di ; EisableInt ;
jmp SeSer_1 ; until false ;
;end (* SendSerial *) ;
( . . . )
SendSerialString ;procedure SendSerialString ( String[hl] : array of byte ) ;
;var
; Data : byte ;
; Inx : byte ;
;begin (* SendSerialString *)
; Inx := 0 ;
SeSerStr_0 ; repeat
mov a , m ; Data = String [ Inx ] ;
inx h ; Inx := Inx + 1 ;
cpi 0 ; if Data = 0 then
jnz SeSerStr_1 ;
ret ; exit ;
SeSerStr_1 ;
push h ;
call SendSerial ; SendSerial ( Data ) ;
pop h ;
jmp SeSerStr_0 ; until false ;
;end (* SendSerialString *) ;Prezentacja działania obsługi układu 8250 to:
Kod: Zaznacz cały
SerialHello .defb "Zestaw edukacyjny z procesorem Intel 8080", 0Dh, 0Ah, 0
( . . . )
lxi h , SerialHello ; SendSerialString ( SerialHello ) ;
call SendSerialString ;I zadziałało:
Na obecnym etapie wiadomo, że cały zestaw jest technicznie sprawny (test pamięci RAM również przechodzi z tym samym algorytmem co w poprzedniej iteracji). Teraz zostało trochę potrudzić się nad „systemem operacyjnym”.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse
Kto jest online
Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 1 gość

