[8085] Molestowanie procka

Kącik dla elektroniki retro - układy, urządzenia, podzespoły, literatura itp.
Awatar użytkownika
gaweł
Geek
Geek
Posty: 1296
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

[8085] Molestowanie procka

Postautor: gaweł » piątek 03 maja 2024, 11:57

Mając uruchomione środowisko z prockiem 8085 można
by zrobić trochę badań i eksperymentów.
Jest wyświetlacz LCD, więc weryfikacja nieudokumentowanych
instrukcji daje się łatwo zrealizować. Na początek
badania związane z przerwaniami połówkowymi.
Generowało mi się trochę „dziwności”, ale później się okazało,
że był błąd w sofcie i po poprawce per saldo
zgadza się z literaturą. Jest jeszcze jedna „dziwność”,
bo nie zauważyłem wpływu operacji zerowania
przerwania 7.5 na działanie całości. Być może problem
jest szerszy i należy go rozpatrywać w szerszej perspektywie.


irq75_000.jpg


Badania przerwania 7.5 w 8085

Mając hardware z prockiem i8085 pomyślałem sobie, że fajnie jest zrobić trochę doświadczeń dotyczących przerwania 7.5 (inne są niestety sprzętowo zablokowane, jak pokazuje schemat), tylko przerwanie 7.5 ma doprowadzony sygnał, pozostałe są uglebione na stałe (przerwanie 5.5 i 6.5 reagują na poziom wysoki, przerwanie 7.5 reaguje na zbocze narastające).
irq75_001.png

Więc by uruchomić przerwanie należy wykonać następujący zapis instrukcją SIM (set interrupt mask).

Kod: Zaznacz cały

Init_hardware                                      ;
        mvi     a , Enable75Inter                  ;
        sim                                        ;
        ret

Wartość i znaczenie bitów w Enable75Inter jest następujące:
irq75_002.png

Jak tego się nie wykona, to procek nie reaguje na przerwania (sprawdziłem). Jak wygląda problematyka po sygnale reset? Przed ustawieniem maski wykonałem instrukcję RIM (read interrupt mask) i stan akumulatora zapisałem w zmiennej do późniejszego wyświetlenia.

Kod: Zaznacz cały

Init_hardware                                      ;
        rim                                        ;
        sta     RIMByte                            ;
        mvi     a , Enable75Inter                  ;
        sim                                        ;
        ret   

By mieć pełna kontrolę nad przerwaniami (czyli generować je samemu), wyjąłem z układu 8253 i dałem taki oto układ (taki ogólnofilozoficzny zadawacz stanów bez dzwonienia styków bazujący na CD4044 – poczwórnym przerzutniku RS).
irq75_003.png

Czerwony kabelek to plus zasilania, niebieski to minus zasilania a pozostałe to wyjścia (jest używane jedno: też czerwony skrajnie prawy).
irq75_004.jpg

irq75_005.jpg

Po odpaleniu programu jest wyświetlony stan konfiguracyjny po resecie.
irq75_006.jpg

Gdzie znaczenie bitów jest następujące:
irq75_007.png

To by się zgadzało z tym, co jest napisane w dokumentacji Intela.
Naciśnięcie przycisku w zadawaczu stanów nie generuje jeszcze nic (jest stan zera: dioda nie świeci).
irq75_008.jpg

Zmiana stanu z zera na jedynkę (zbocze narastające) generuje przerwanie.
irq75_009.jpg

Jego obsługa to:

Kod: Zaznacz cały

        .org    RST75Entry                         ;
        push    psw                                ;
        rim                                        ;
        sta     RIMByte                            ;
        lda     IRQCnt                             ;
        inr     a                                  ;
        sta     IRQCnt                             ;
        mvi     a , 1                              ;
        sta     IRQFlag                            ;
        mvi     a , Cler75FlipFlop                 ;
        sim                                        ;
        pop     psw                                ;
        ei                                         ;
        ret                                        ;

czyli zapamiętanie stanu RIM wewnątrz obsługi przerwania (zmienna RIMByte), zliczenie przerwania (zmienna IRQCnt) i ustawienie flagi, że doszło do przerwania (zmienna IRQFlag). Wyniki są „spożytkowane” w programie „na zewnątrz” przerwania w funkcji main.

Kod: Zaznacz cały

Main                                               ;
        call    InitialiseLCD                      ;
        call    ClrScrLCD                          ;
        lxi     h , HelloMessage                   ;
        call    WriteTextLCD                       ;
        call    NewLineLCD                         ;
        mvi     a , '#'                            ;
        call    WriteChLCD                         ;
        lda     IRQCnt                             ;
        call    DispHex                            ;
        call    DisplayRIM                         ;
Main_0                                             ;
        lda     IRQFlag                            ;
        cpi     0                                  ;
        jz      Main_0                             ;
        mvi     a , 0                              ;
        sta     IRQFlag                            ;
        call    ClrScrLCD                          ;
        mvi     a , '*'                            ;
        call    WriteChLCD                         ;
        lda     IRQCnt                             ;
        call    DispHex                            ;
        call    DisplayRIM                         ;
        call    NewLineLCD                         ;
        rim                                        ;
        sta     RIMByte                            ;
        mvi     a , ' '                            ;
        call    WriteChLCD                         ;
        mvi     a , ' '                            ;
        call    WriteChLCD                         ;
        mvi     a , ' '                            ;
        call    WriteChLCD                         ;
        call    DisplayRIM                         ;
        jmp     Main_0                             ;

W pierwszym wierszu są zapamiętane dane z wnętrza przerwania, w drugim wierszu są spoza obsługi przerwania (z funkcji main).
irq75_010.jpg

Różnice są niewielkie: widać, że przyjęcie przerwania jest połączone z wykonaniem instrukcji blokującej przerwania (DI). W obsłudze przerwania jest jeszcze:

Kod: Zaznacz cały

        .org    RST75Entry                         ;
.
.
.
        mvi     a , Cler75FlipFlop                 ;
        sim                                        ;
.
.
.
        ret                                        ;

irq75_011.png

ale nie zauważyłem różnicy: czy flaga jest zerowana czy nie.
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

Awatar użytkownika
gaweł
Geek
Geek
Posty: 1296
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: [8085] Molestowanie procka

Postautor: gaweł » piątek 03 maja 2024, 18:08

arhl_00.jpg


Instrukcja ARHL procesora 8085

Nieudokumentowana (przynajmniej u Intela) instrukcja ARHL (arytmetycznego przesunięcia w prawo pary rejestrów HL) jest opisana w dokumentacji, którą wyszukał nasz kolega :arrow: Tapy. Przesunięcie arytmetyczne to takie, gdzie najstarszy bit jest powielany (by liczba traktowana w kodzie U2 nie zmieniała znaku), całość jest przesunięta o 1 bit w prawo a najmłodszy bit jaki wychodzi z pary rejestrów HL jest zapisywany do flagi CY. Tą operację można traktować jako dzielenie liczby w kodzie U2 przez 2, natomiast wskaźnik CY zawiera resztę z dzielenia. Program wypisuje swoje epistoły na wyświetlaczu LCD: w pierwszym wierszu są zawartości pary rejestrów przed operacją, w drugim wierszu po operacji oraz pokazany jest stan wskaźnika przeniesienia CY. Program obrabia kilka przykładów i by wszystko nie mignęło na wyświetlaczu, przed każdą prezentacją oczekuje na wystąpienie przerwania 7.5, które ustawia flagę badaną w funkcji main. Powstaje „krokowa” możliwość prezentacji działania instrukcji ARHL.
Wybrane przykłady to:

Kod: Zaznacz cały

        call    StepWait                           ;
        lxi     h , 0001h                          ;
        call    ArhlTest                           ;
        call    StepWait                           ;
        lxi     h , 0002h                          ;
        call    ArhlTest                           ;
        call    StepWait                           ;
        lxi     h , 5555h                          ;
        call    ArhlTest                           ;
        call    StepWait                           ;
        lxi     h , 0aaaah                         ;
        call    ArhlTest                           ;
        call    StepWait                           ;
        lxi     h , 0ffffh                         ;
        call    ArhlTest                           ;

Funkcja testująca to:

Kod: Zaznacz cały

ArhlTest                                           ;
        shld    SaveHLBefore                       ;
        arhl                                       ;
        shld    SaveHLAfter                        ;
        mvi     a , 0                              ;
        aci     0                                  ;
        sta     ProcFlags                          ;
        call    ClrScrLCD                          ;
        lxi     h , HLPrompt                       ;
        call    WriteTextLCD                       ;
        lda     SaveHLBefore + 1                   ;
        call    DispByte                           ;
        lda     SaveHLBefore                       ;
        call    DispByte                           ;
        call    NewLineLCD                         ;
        lxi     h , HLPrompt                       ;
        call    WriteTextLCD                       ;
        lda     SaveHLAfter+ 1                     ;
        call    DispByte                           ;
        lda     SaveHLAfter                        ;
        call    DispByte                           ;
        lxi     h , CPrompt                        ;
        call    WriteTextLCD                       ;
        lda     ProcFlags                          ;
        call    DispBit                            ;
        ret                                        ;

Wyciągnięcie wskaźnika CY to wynik operacji: 0 [mvi a,0] + 0 + CY [aci 0]. Wynik wynosi 0 albo 1 w zależności od stanu wskaźnika CY.
Pierwszy przypadek to liczba 1: 1 podzielić przez 2 = 0 i reszty 1.
arhl_01.jpg

Drugi przypadek: 2 / 2 = 1 reszty 0.
arhl_02.jpg

Trzeci przypadek: 5555hex = 21845 dec / 2 = 10922 dec = 2AAA hex i reszty 1 (nawet się zgadza).
arhl_03.jpg

Kolejny wariant: AAAA hex = -21846 dec / 2 = D555 hex = - 10923 dec i reszty 0.
arhl_04.jpg

Ostatni przypadek: FFFF hex = -1 dec / 2 = FFFF hex = -1 dec i reszty 1. Trochę mnie to zdziwiło, ale jest poprawnie, gdyż -1 * 2 = -2 i do tego dodać resztę (-2 + 1 = -1). Nie ma się do czego przyczepić, jest właściwie.
arhl_05.jpg

Znaczy, że procek kuma co to jest ARHL.
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

Awatar użytkownika
gaweł
Geek
Geek
Posty: 1296
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: [8085] Molestowanie procka

Postautor: gaweł » sobota 04 maja 2024, 11:34

dsub_0.jpg


Instrukcja DSUB procesora 8085

W podobnej technologii zbadane zostało działania instrukcji DSUB (16-bitowej operacji odjęcia od zawartości pary rejestrów HL zawartość pary rejestrów BC z wynikiem pozostawionym w HL). Według dokumentacji Tundry, instrukcja modyfikuje wskaźniki: Z, S, P i CY – znaczy jest przeznaczona do operacji w kodzie naturalnym binarnym, choć również zadziała dla liczb w kodzie U2, ale nie będzie wiadomo, czy nie nastąpiło przepełnienie (wskaźnik V). Podobnie jak poprzednio, program wypisuje swoje epistoły na wyświetlaczu LCD: w pierwszym wierszu są zawartości pary rejestrów przed operacją, w drugim wierszu po operacji oraz pokazany jest stan modyfikowanych wskaźników. Program obrabia kilka przykładów.

Kod: Zaznacz cały

Main_0                                             ;
        call    StepWait                           ;
        lxi     h , 0001h                          ; 0001 hex – 0505 hex
        lxi     b , 0505h                          ;
        call    DsubTest                           ;
        call    StepWait                           ;
        lxi     h , 0505h                          ; 0505 hex – 0505 hex
        lxi     b , 0505h                          ;
        call    DsubTest                           ;
        call    StepWait                           ;
        lxi     h , 0505h                          ; 0505 hex – 0501 hex
        lxi     b , 0501h                          ;
        call    DsubTest                           ;
        jmp     Main_0                             ;

Sama procedura testu to:

Kod: Zaznacz cały

DsubTest                                           ;
        shld    SaveHLBefore                       ;
        lxi     d , SaveBCBefore                   ;
        mov     a , c                              ;
        stax    d                                  ;
        inx     d                                  ;
        mov     a , b                              ;
        stax    d                                  ;
        dsub                                       ;
        shld    SaveHLAfter                        ;
        push    psw                                ;
        pop     d                                  ;
        mov     a , e                              ;
        sta     ProcFlags                          ;
        call    ClrScrLCD                          ;
        lxi     h , HLPrompt                       ;
        call    WriteTextLCD                       ;
        lda     SaveHLBefore + 1                   ;
        call    DispHex                            ;
        lda     SaveHLBefore                       ;
        call    DispHex                            ;
        lxi     h , BCPrompt                       ;
        call    WriteTextLCD                       ;
        lda     SaveBCBefore + 1                   ;
        call    DispHex                            ;
        lda     SaveBCBefore                       ;
        call    DispHex                            ;
        call    NewLineLCD                         ;
        lxi     h , HLPrompt                       ;
        call    WriteTextLCD                       ;
        lda     SaveHLAfter+ 1                     ;
        call    DispHex                            ;
        lda     SaveHLAfter                        ;
        call    DispHex                            ;
        call    DispFlags                          ;
        ret                                        ;

Wydobycie wskaźników jest zrealizowane następująco: akumulator i wskaźniki zapisane na stos i pobrane do jakiejkolwiek pary rejestrów, wskaźniki znajdą się w młodszej części pary rejestrów. Wyświetlenie stanu wskaźników to już operacja iloczynu logicznego stanu zapisanych wszystkich wskaźników i odpowiedniej maski bitowej do wyselekcjonowania poszukiwanego bitu.

Kod: Zaznacz cały

SFlagMask       .equ    10000000b                  ;
ZFlagMask       .equ    01000000b                  ;
ACFlagMask      .equ    00010000b                  ;
PFlagMask       .equ    00000100b                  ;
CYFlagMask      .equ    00000001b                  ;
;***************************************************
DispFlags                                          ;
        lxi     h , SPrompt                        ;
        call    WriteTextLCD                       ;
        lda     ProcFlags                          ;
        ani     SFlagMask                          ;
        call    DispBit                            ;
        lxi     h , ZPrompt                        ;
        call    WriteTextLCD                       ;
        lda     ProcFlags                          ;
        ani     ZFlagMask                          ;
        call    DispBit                            ;
        lxi     h , ACPrompt                       ;
        call    WriteTextLCD                       ;
        lda     ProcFlags                          ;
        ani     ACFlagMask                         ;
        call    DispBit                            ;
        lxi     h , PPrompt                        ;
        call    WriteTextLCD                       ;
        lda     ProcFlags                          ;
        ani     PFlagMask                          ;
        call    DispBit                            ;
        lxi     h , CYPrompt                       ;
        call    WriteTextLCD                       ;
        lda     ProcFlags                          ;
        ani     CYFlagMask                         ;
        call    DispBit                            ;
        ret                                        ;

Finał jest następujący:
dsub_1.jpg

dsub_2.jpg

dsub_3.jpg

Arytmetycznie się zgadza, sprawdziłem za pomocą kalkulatora.
W jednym przypadku było odejmowanie liczby większej od mniejszej, gdzie wynik wyszedł „ujemny”, gdyż został ustawiony wskaźnik zarówno S jak i CY. Ten drugi może posłużyć do operacji 32-bitowych, ale trzeba pokombinować, gdyż nie ma instrukcji odjęcia 16-bitowego z uwzględnieniem CY.
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

tapy
User
User
Posty: 126
Rejestracja: niedziela 14 kwie 2019, 17:09
Kontaktowanie:

Re: [8085] Molestowanie procka

Postautor: tapy » sobota 04 maja 2024, 12:44

Molestowanie procka

... a jak się on odpowiednim władzom poskarży? :lol:

Jak dobrze pamiętam to Phillip Stevens rozszerzył bibliotekę zmiennoprzecinkową w Z88DK która wykorzystywała te niepublikowane instrukcje 8085 co skutkowało, że tego typu operacje były szybsze niż w Z80. Źródła powinny być w dystrybucji Z88DK.

PS. Tak dla zmylenia przeciwnika zawarty tam assembler z88dk-z80asm obsługuje te instrukcje 8085. ;)

Awatar użytkownika
gaweł
Geek
Geek
Posty: 1296
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: [8085] Molestowanie procka

Postautor: gaweł » poniedziałek 06 maja 2024, 21:41

Instrukcja LDHI procesora 8085

ldhi_00.jpg


Badania zawsze warto robić. Właśnie namierzyłem pluskwę w oprogramowaniu emulatora procka (będzie więc poprawka) a przy okazji silnie napiechotną metodą uświadomiłem sobie, że LDHI nie ustawia wskaźników (co wyraźnie jest zaznaczone w dokumentacji). Mnie się ubzdurało, że instrukcja ustawia flagi po operacji, więc są ujęte w sofcie (co później okazało się niepotrzebne, ale… zostało). Dopiero jak mi flagi „w głowie” się nie zgadzały z tymi pokazanymi na wyświetlaczu, to rozum mi wrócił i sprawdziłam w dokumentacji.
Technologia znacząco nie odbiega od poprzednich.
Instrukcja LDHI to dosumowanie do DE operandu immediate i zachowanie wyniku w HL. Test instrukcji to (ponieważ operand LDHI jest immediate, a nie chciało mi się aż tak dłubać, by z kodu wyciągnąć wartość operandu dla LDHI, jest on wpisany do akumulatora, no trzeba zadbać o zgodność operandu z wartością ładowaną do acu):

Kod: Zaznacz cały

Main_0                                             ;
        call    StepWait                           ;
        lxi     h , 0001h                          ;
        mvi     a , 01h                            ;
        ldhi    01h                                ;
        call    LdhiTest                           ;
        call    StepWait                           ;
        lxi     h , 0ffffh                         ;
        mvi     a , 01h                            ;
        ldhi    01h                                ;
        call    LdhiTest                           ;
        call    StepWait                           ;
        lxi     h , 5555h                          ;
        mvi     a , 55h                            ;
        ldhi    55h                                ;
        call    LdhiTest                           ;
        call    StepWait                           ;
        lxi     h , 0AAAAh                         ;
        mvi     a , 10h                            ;
        ldhi    010h                               ;
        call    LdhiTest                           ;
        call    StepWait                           ;
        lxi     h , 0AAAAh                         ;
        mvi     a , 0ffh                           ;
        ldhi    0ffh                               ;
        call    LdhiTest                           ;
        jmp     Main_0                             ;

Sama operacja to:

Kod: Zaznacz cały

DEPrompt        .defb   'DE=',0
HLPrompt        .defb   'HL=',0
ImArgPrompt     .defb   ' argument imediate=',0
CPrompt         .defb   ' CY=',0
LdhiTest                                           ;  DE = HL + <arg>
        sta     ImArg                              ;
        push    psw                                ;
        pop     b                                  ;
        mov     a , c                              ;
        sta     ProcFlags                          ;
        shld    SaveHL                             ;
        push    d                                  ;
        pop     h                                  ;
        shld    SaveDE                             ;
        call    ClrScrLCD                          ;
        lxi     h , HLPrompt                       ;
        call    WriteTextLCD                       ;
        lda     SaveHL + 1                         ;
        call    DispHex                            ;
        lda     SaveHL                             ;
        call    DispHex                            ;
        lxi     h , ImArgPrompt                    ;
        call    WriteTextLCD                       ;
        lda     ImArg                              ;
        call    DispHex                            ;
        call    NewLineLCD                         ;
        lxi     h , DEPrompt                       ;
        call    WriteTextLCD                       ;
        lda     SaveDE + 1                         ;
        call    DispHex                            ;
        lda     SaveDE                             ;
        call    DispHex                            ;
        call    DispFlags                          ;
        ret                                        ;

Uzyskane wyniki są następujące i zgadzają się z kalkulatorem:
ldhi_01.jpg

W następnym wyzerowany wskaźnik Z wywołał głębszą rozkminę.
ldhi_02.jpg

ldhi_03.jpg

ldhi_04.jpg

ldhi_05.jpg
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

Awatar użytkownika
gaweł
Geek
Geek
Posty: 1296
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: [8085] Molestowanie procka

Postautor: gaweł » środa 08 maja 2024, 20:52

vflag_00.jpg



Wskaźnik V procesora 8085

Oficjalnie wskaźnika takowego nie ma tym procesorze, więc jak zbadać coś, czego nie ma. Ana trzeba zbadać…
Zaczęło się od instrukcji RSTV (restartu od wskaźnika nadmiaru V). No jest instrukcja w dokumentacji Tundry, więc zapewne twórcy wiedzą co robią. RSTV to skok do programu na adresie 40 hex i zapewne procek nie będzie miał problemów z wykonaniem takiej instrukcji, ale… coś musi ten wskaźnik ustawić. Z pewnością nie będzie to instrukcja RDEL (poniżej), gdyż:
1. w opisie nie ma wzmianki o zmianie wskaźnika V,
2. w tabelce w zaznaczonej kolumnie wskaźnik V znalazł się przez pomyłkę, instrukcja przesunięć jako instrukcje o charakterze logicznym zwykle nie generują informacji o nadmiarze (robią to typowo instrukcje arytmetyczne),
3. w innym miejscu dokumentacji podano, że wskaźnik V to bit numer 1 w rejestrze statusów i jest ustawiany przez instrukcja arytmetyczne w zakresie 8- i 16-bitów.
vflag_01.png

vflag_02.png

Znaczy, że głównym powodem ustawienia wskaźnika V są wszystkie instrukcje arytmetyczne. Intel do czegoś takiego się nie przyznaje, googiel też nie zdradza tajemnic Intel’a. Pozostaje „reverse engineering”. Do badań nad zmianami wskaźnika V na pierwszy ogień poszła instrukcja ADD (jako 8-bitów) – kilka operacji z różnymi wartościami operandów:

Kod: Zaznacz cały

        call    StepWait                           ;
        mvi     a , 01h                            ;
        mvi     b , 80h                            ;
        call    ArthTest                           ;
        call    StepWait                           ;
        mvi     a , 7fh                            ;
        mvi     b , 01h                            ;
        call    ArthTest                           ;
        call    StepWait                           ;
        mvi     a , 0ffh                           ;
        mvi     b , 0ffh                           ;
        call    ArthTest                           ;
        call    StepWait                           ;
        mvi     a , 0c0h                           ;
        mvi     b , 0ffh                           ;
        call    ArthTest                           ;
        call    StepWait                           ;
        mvi     a , 0c0h                           ;
        mvi     b , 080h                           ;
        call    ArthTest                           ;
        call    StepWait                           ;
        mvi     a , 0c0h                           ;
        mvi     b , 07fh                           ;
        call    ArthTest                           ;

Operacja testu arytmetycznego to:

Kod: Zaznacz cały

APrompt         .defb   ' A=',0
BPrompt         .defb   ' B=',0
RPrompt         .defb   ' R=',0
;***************************************************
ArthTest                                           ;
        lxi     d , Argument1                      ;
        stax    d                                  ;
        lxi     h , Argument2                      ;
        mov     m , b                              ;
        add     b                                  ;
        sta     Result                             ;
        push    psw                                ;
        pop     b                                  ;
        lxi     h , ProcFlags                      ;
        mov     m , c                              ;
        call    ClrScrLCD                          ;
        lxi     h , APrompt                        ;
        call    WriteTextLCD                       ;
        lda     Argument1                          ;
        call    DispHex                            ;
        lxi     h , BPrompt                        ;
        call    WriteTextLCD                       ;
        lda     Argument2                          ;
        call    DispHex                            ;
        call    NewLineLCD                         ;
        lxi     h , RPrompt                        ;
        call    WriteTextLCD                       ;
        lda     Result                             ;
        call    DispHex                            ;
        call    DispFlags                          ;
        ret                                        ;

Pierwszy przykład: 01 hex + 80 hex
vflag_03.jpg

Procek mówi, że wynik to 82 hex i wskaźnik V=0. Kalkulator w kompie potwierdza.
vflag_04.png

1 hex (1 dec) + 80 hex (-128 dec) = 81 hex (-127 dec). Wynik jest poprawny (mieści się na jednym bajcie), więc wskaźnik V=0 → pasuje.

Drugi przykład, to: 7F hex + 01hex
vflag_05.jpg

Tu już bez kalkulatora widać, że jest nadmiar, gdyż argumenty są dodatnie a wynik jest ujemny → wynik jest niepoprawny w sensie arytmetyki w kodzie U2. Przy okazji, procek również sygnalizuje ustawiony wskaźnik V.


Kolejny przykład: ff hex + ff hex
vflag_06.jpg

Wynik to: ff hex (-1 dec) + ff hex (-1 dec) = fe hex (-2 dec), i również bez kalkulatora można stwierdzić, że jest poprawny, co również sygnalizuje procek V=0.

Następny przykład: c0 hex + ff hex
vflag_07.jpg

Dla ludzie jest to: c0 hex (-64 dec) + ff hex (-1 dec) = bf hex (-64 dec) i jest OK, co potwierdza procek poprzez V=0, a ja sprawdziłem na kalkulatorze.
vflag_08.png


Kolejny test to: c0 hex + 80 hex
vflag_09.jpg

Bez kalkulatora widać, że wynik jest krzywy, gdyż c0 hex jest liczbą ujemną (dokładniej to -64 dec), 80 hex jest liczbą ujemną (-128 dec) a ich suma wypada jako liczba dodatnia (40 hex). Procek również to zauważył i ustawił wskaźnik V=1.


Ostatni przypadek: c0 hex + 7F hex
vflag_10.jpg

Normalnie to jest następująco: c0 hex (-64 dec) + 7F hex (127 dec) = 3F hex (63 dec), co można nawet policzyć na palcach. Ja użyłem kalkulatora i jest OK.
vflag_11.png

Znaczy, że procek 8085, robi co trzeba ale zarząd Intel’a do tego się nie przyznaje. Podsumowując, warto sprawdzić jeszcze arytmetykę 16-bitową, ale już mi się nie chciało. Skoro robi to dla 8-bitów to zapewne operacje 16-bitowe też modyfikują wskaźnik V.
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

Awatar użytkownika
gaweł
Geek
Geek
Posty: 1296
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: [8085] Molestowanie procka

Postautor: gaweł » czwartek 09 maja 2024, 13:59

rstv_0.jpg


Instrukcja RSTV procesora 8085

Po eksperymentach ze wskaźnikiem V przyszła kolej na instrukcję RSTV. Napisałem program, w którym w przypadku wystąpienia nadmiaru zostanie wywołane takie „przerwanie softwarowe”, jest to skok pok adres 40 hex. Reakcja na przerwanie jest banalnie prosta: ustawia flagę, że takowe zaistniało.

Kod: Zaznacz cały

RST75Entry      .equ    0003ch
RSTVEntry       .equ    00040h
.
.
.
;***************************************************
        .org    RSTVEntry                          ;
        jmp     RSTVService                        ;
;***************************************************
.
.
.
RSTVService                                        ;
        push    psw                                ;
        mvi     a , 1                              ;
        sta     RstvFlag                           ;
        pop     psw                                ;
        ret                                        ;

Tym razem postanowiłem wypróbować arytmetykę 16-bitową, czyli instrukcję DAD (w wariancie: HL = HL + BC). Zostały przygotowane dwa zestawy wartości argumentów. Pierwszy nie ustawia wskaźnika nadmiaru, drugi ustawia.

Kod: Zaznacz cały

Main_0                                             ;
        call    StepWait                           ;
        lxi     h , 0555h                          ;
        lxi     b , 0777h                          ;
        call    RSTVTest                           ;
        call    StepWait                           ;
        lxi     h , 7fffh                          ;
        lxi     b , 0055h                          ;
        call    RSTVTest                           ;
        jmp     Main_0                             ;

Sama procedura testu zapisuje wartości argumentów i wyników (jak i również wskaźników) do pamięci RAM do późniejszego wyświetlenia na LCD.

Kod: Zaznacz cały

HLPrompt        .defb   'HL=',0
BCPrompt        .defb   ' BC=',0
RPrompt         .defb   ' R=',0
RstvPresent     .defb   '    RSTV zaistnialo',0
;***************************************************
RSTVTest                                           ;
        mvi     a , 0                              ;
        sta     RstvFlag                           ;
        mov     a , l                              ;
        sta     Argument1                          ;
        mov     a , h                              ;
        sta     Argument1 + 1                      ;
        mov     a , c                              ;
        sta     Argument2                          ;
        mov     a , b                              ;
        sta     Argument2 + 1                      ;
        dad     b                                  ;
        push    psw                                ;
        pop     b                                  ;
        mov     a , c                              ;
        sta     ProcFlags                          ;
        rstv                                       ;
        mov     a , l                              ;
        sta     Result                             ;
        mov     a , h                              ;
        sta     Result + 1                         ;
        call    ClrScrLCD                          ;
        lxi     h , HLPrompt                       ;
        call    WriteTextLCD                       ;
        lda     Argument1 + 1                      ;
        call    DispHex                            ;
        lda     Argument1                          ;
        call    DispHex                            ;
        lxi     h , BCPrompt                       ;
        call    WriteTextLCD                       ;
        lda     Argument2 + 1                      ;
        call    DispHex                            ;
        lda     Argument2                          ;
        call    DispHex                            ;
        call    NewLineLCD                         ;
        lxi     h , RPrompt                        ;
        call    WriteTextLCD                       ;
        lda     Result + 1                         ;
        call    DispHex                            ;
        lda     Result                             ;
        call    DispHex                            ;
        call    DispFlags                          ;
        lda     RstvFlag                           ;
        cpi     0                                  ;
        rz                                         ;
        lxi     h , RstvPresent                    ;
        call    WriteTextLCD                       ;
        ret                                        ;

Wszystko wyszło jak powinno. Pierwszy przypadek: 555 hex + 777 hex = CCC hex i flaga nie ustawia się.
rstv_1.jpg

Drugi przypadek ma za zadanie wygenerować wskaźnik V: 7FFF hex + 0055 hex przekracza pojemność 16-bitów → zostaje ustawiony wskaźnik V. Ponieważ za instrukcją DAD jest instrukcja RSTV, nastąpiło wywołanie obsługi wyjątku, która odnotowała ten fakt by o tym zdarzeniu później poinformować.
rstv_2.jpg

Niby wszystko OK (w procku), gorzej jest w programie emulatora. Tam dla operacji arytmetycznych 8-bitowych i 16-bitowych jest wyliczany wskaźnik V.
rstv_3.png

tylko, że dla 8- i 16-bitów źle to rachuje. Gdzieś kiedyś znalazłem formułę określenia wskaźnika V (nawet jest zgodna z tym co podaje dokument Tundry) i się nie zgadza z rzeczywistością, bo przykładowo 7FFF hex → znak argumentu 1 to 0, 0055 hex → znak argumentu 2 to 0 i 8054 hex → znak wyniku to 1. Jak nie rachować, to wychodzie false [ ( 0 and 0 ) or ( 0 and 1 ) or ( 0 and 1) = 0]. Mo i … maliny.
rstv_4.png

Po długich poszukiwaniach w sieci znalazłem w jakiejś akademickiej prezentacji wykładów informację, że:
  • V = 1 gdy suma dwóch liczb dodatnich daje wynik ujemny (proste i nie podlega dyskusji),
  • V = 1 gdy suma dwóch liczb ujemnych daje wynik dodatni (proste i nie podlega dyskusji),
  • nadmiar nie występuje przy dodawaniu liczb przeciwnych znaków (no tu muszę zaufać).
Zmieniłem w programie formułę określającą wartość wskaźnika V na:

Kod: Zaznacz cały

  function ComputeVFlag ( Arg1Flag : boolean ;
                          Arg2Flag : boolean ;
                          ResFlag  : boolean ) : boolean ;

  begin (* ComputeVFlag *)
    ComputeVFlag := ( Arg1Flag and Arg2Flag and ( not ResFlag ) ) or
                    ( ( not Arg1Flag ) and ( not Arg2Flag ) ) and ResFlag ;
  end (* ComputeVFlag *) ;

  function ComputeV16Flag ( OpResult : word ;
                            Arg1     : word ;
                            Arg2     : word ) : boolean ;
  var
    Arg1Flag            : boolean ;
    Arg2Flag            : boolean ;
    ResFlag             : boolean ;

  begin (* ComputeV16Flag *)
    Arg1Flag := ( Arg1 and $8000 ) <> 0 ;
    Arg2Flag := ( Arg2 and $8000 ) <> 0 ;
    ResFlag := ( OpResult and $8000 ) <> 0 ;
    ComputeV16Flag := ComputeVFlag ( Arg1Flag , Arg2Flag , ResFlag ) ;
  end (* ComputeV16Flag *) ;

i tym razem zadziałało. Jest to prowizoryczna poprawka, gdyż jest tylko dla operacji dodawania. W przypadku operacji odejmowania jest deczko inaczej. Znów trzeba poprawić program emulatora.
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

Awatar użytkownika
gaweł
Geek
Geek
Posty: 1296
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: [8085] Molestowanie procka

Postautor: gaweł » niedziela 12 maja 2024, 20:40

jui_00.jpg


Instrukcja JUI procesora 8085

Tak sobie myślę, że nie ma potrzeby macania każdej nieudokumentowanej instrukcji procka. Skoro dotychczas się zgadza, to właściwie nie ma potrzeby podchodzić do reszty z dozą braku zaufania. Jednak nie wszystko jest takie fajne na jakie wygląda. Przymierzyłem się do instrukcji JUI (mniemam, że JNUI jest jej dopełnieniem). Po pierwsze dostępna dokumentacja mnie zaskoczyła (i to dosłownie). W opisie instrukcji JNUI jest fragment, który jest spoza kontekstu, nie pasuje. Występuje dziwna zbieżność z opisem instrukcji wyżej (źle zadziałało kopij/wklej?). Sytuacja powtarza się w JUI.
jui_01.png

Byłem przekonany, że wskaźnik UI dotyczy nadmiaru w operacji inkrement/dekrement pary rejestrów.
jui_02.png

Literalnie rzecz biorąc, nadmiar dotyczy operacji w kodzie U2 a tu jest mowa o inkrementach i dekrementach. Wskaźnik V już istnieje, więc po co?
W drugim dokumencie wskazanym przez kolegę :arrow: Tapy nie ma więcej informacji (no może tylko tyle, że tam wskaźnik nazywa się X5). Może jednak rzeczywiście chodzi o inkrement i dekrement w kodzie binarnym. Sprawdźmy.

Kod: Zaznacz cały

Main_0                                             ;
        call    StepWait                           ;
        lxi     b , 0555h                          ;
        call    JUI1Test                           ;
        call    StepWait                           ;
        lxi     b , 0ffffh                         ;
        call    JUI1Test                           ;
        call    StepWait                           ;
        lxi     b , 0555h                          ;
        call    JUI2Test                           ;
        call    StepWait                           ;
        lxi     b , 0h                             ;
        call    JUI2Test                           ;
        jmp     Main_0                             ;

gdzie są dwa warianty: jeden dotyczy inkrementacji, drugi dekrementacji.

Kod: Zaznacz cały

NutJumpTxt      .defb   '* nie skoczylo *' , 0
JumpTxt         .defb   '* skoczylo *' , 0
BCPrompt        .defb   'BC=',0
;***************************************************
OperationTxt1   .defb   ' operacja inkrementacji' ,0
;***************************************************
JUI1Test                                           ;
        push    b                                  ;
        lxi     h , Argument                       ;
        mov     m , c                              ;
        inx     h                                  ;
        mov     m , b                              ;
        call    ClrScrLCD                          ;
        lxi     h , BCPrompt                       ;
        call    WriteTextLCD                       ;
        lda     Argument + 1                       ;
        call    DispHex                            ;
        lda     Argument                           ;
        call    DispHex                            ;
        lxi     h , OperationTxt1                  ;
        call    WriteTextLCD                       ;
        call    NewLineLCD                         ;
        pop     b                                  ;
        inx     b                                  ;
        jui     JUI1Test_0                         ;
        lxi     h , NutJumpTxt                     ;
        call    WriteTextLCD                       ;
        ret                                        ;
JUI1Test_0                                         ;
        lxi     h , JumpTxt                        ;
        call    WriteTextLCD                       ;
        ret                                        ;

Kod: Zaznacz cały

OperationTxt2   .defb   ' operacja dekrementacji' ,0
;***************************************************
JUI2Test                                           ;
        push    b                                  ;
        lxi     h , Argument                       ;
        mov     m , c                              ;
        inx     h                                  ;
        mov     m , b                              ;
        call    ClrScrLCD                          ;
        lxi     h , BCPrompt                       ;
        call    WriteTextLCD                       ;
        lda     Argument + 1                       ;
        call    DispHex                            ;
        lda     Argument                           ;
        call    DispHex                            ;
        lxi     h , OperationTxt2                  ;
        call    WriteTextLCD                       ;
        call    NewLineLCD                         ;
        pop     b                                  ;
        dcx     b                                  ;
        jui     JUI2Test_0                         ;
        lxi     h , NutJumpTxt                     ;
        call    WriteTextLCD                       ;
        ret                                        ;
JUI2Test_0                                         ;
        lxi     h , JumpTxt                        ;
        call    WriteTextLCD                       ;
        ret                                        ;

No i wyszło, że działa (chyba w interpretacji liczb jako naturalne binarne).
jui_03.jpg

jui_04.jpg
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

Awatar użytkownika
gaweł
Geek
Geek
Posty: 1296
Rejestracja: wtorek 24 sty 2017, 22:05
Lokalizacja: Białystok

Re: [8085] Molestowanie procka

Postautor: gaweł » piątek 07 cze 2024, 23:37

8085.jpg


Badanie procka – wskaźnik UI

Chcąc zmodyfikować program emulatora procesora i8085 w kontekście nieudokumentowanych instrukcji, koniecznością stało się przeprowadzenie kilku badań. Jedyna (znaleziona) informacja o tych instrukcjach znajduje się w PDF’ie od Tundra. Niestety nawet pobieżnie widać, że zawiera ona trochę błędów i jeszcze więcej niedomówień. Nieudokumentowane instrukcje dotyczą również nieudokumentowanych wskaźników, tych przybyło o dwie sztuki. Ich położenie znajduje się w PDF’ie Tundry. Pomimo pomyłek, komuś w końcu trzeba zaufać. Rozłożenie wskaźników pokazuje rysunek:
uiflag00.png

O ile dokumenty nawet Intel’a rozpisują się na temat oficjalnych wskaźników, to na temat dodanych (V i UI) nie ma żadnych informacji (testowany procek jest produkcji Intela, więc sami coś ukrywają). Biorąc na początek wskaźnik UI, w dokumencie Tundry jest informacja, że jest on związany z nadmiarem/niedomiarem w operacjach inkrementu/dekrementu par rejestrów. Wcześniej sprawdziłem, że rzeczywiście ten wskaźnik jest użytkowany przez procki (nawet intelowe). Jednak to jest za mało, by ująć to w programie emulatora. Podstawowe pytanie brzmi: jaka jest interakcja z innymi instrukcjami mogącymi modyfikować wskaźniki?
Powszechnie wiadomo, że wszelkie operacje przesłań między rejestrami, rejestrem i pamięcią, skoków (w tym wywołania podprogramów oraz powroty z nich) nie modyfikują żadnych wskaźników. Ta cecha pozwoliła na drobną automatyzację procesów badawczych. Sam program badawczy „generuje” określony stan wskaźnika UI (przez inkrement/dekrement dla takich zawartości par rejestrów, by doszło do „jego przekręcenia” – to produkuje odpowiedni stan wskaźnika UI).
Jednak wcześniej, by „tło” badań było zawsze jednoznaczne, wszystkie wskaźniki przed „krytyczną” operacją są zerowane. Uzyskałem to poprzez następujący chwyt:

Kod: Zaznacz cały

        lxi     b , 0                              ;
        push    b                                  ;
        pop     psw                                ;

zapis na stos pary rejestrów zawierającej same zera i pobranie jako akumulatora i rejestru wskaźników (sam akumulator się wyzeruje – starsza część pary rejestrów oraz wyzerują się wskaźniki – młodsza część pary rejestrów).
Po instrukcji inkrementu/dekrementu zapisane są wskaźniki do komórki pamięci adresowanej przez HL:

Kod: Zaznacz cały

        push    psw                                ;
        pop     d                                  ;
        mov     m , e                              ;

sam zapis wskaźników do pamięci nie modyfikuje ich, więc bezpośrednio kolejną instrukcją jest jakaś operacja 8-bitowa również z zachowaniem wskaźników. Na koniec zgromadzone dane są pokazane na ekranie LCD. Program wyświetla wszystkie wskaźniki.
Okazuje się, że wskaźnik UI jest również modyfikowany przez operacje 8-bitowe arytmetyczne oraz logiczne i przez pewne instrukcje operacji 16-bitowych. Tego to już nie ma w żadnej dokumentacji, więc „wiedza” jest jedynie wynikiem eksperymentów i wyciągania wniosków. Program w ciekawszych fragmentach jest następujący:

Kod: Zaznacz cały

Main                                               ;
        call    InitialiseLCD                      ;
        call    ClrScrLCD                          ;
        lxi     h , HelloMessage                   ;
        call    WriteTextLCD                       ;
        call    NewLineLCD                         ;
        lxi     h , IRQWaitMessage                 ;
        call    WriteTextLCD                       ;
Main_0                                             ;
        call    StepWait                           ;
        lxi     b , 1111h                          ;
        call    UITestInc                          ;
        call    StepWait                           ;
        lxi     b , 0ffffh                         ;
        call    UITestInc                          ;
        call    StepWait                           ;
        lxi     b , 0                              ;
        call    UITestInc                          ;
        call    StepWait                           ;
        lxi     b , 1111h                          ;
        call    UITestDec                          ;
        call    StepWait                           ;
        lxi     b , 0ffffh                         ;
        call    UITestDec                          ;
        call    StepWait                           ;
        lxi     b , 0                              ;
        call    UITestDec                          ;
        jmp     Main_0                             ;
;***************************************************
SaveArg                                            ;
        lxi     h , Argument                       ;
        mov     m , c                              ;
        inx     h                                  ;
        mov     m , b                              ;
        ret                                        ;
;***************************************************
ClearFlags                                         ;
        lxi     b , 0                              ;
        push    b                                  ;
        pop     psw                                ;
        ret                                        ;
;***************************************************
OthOperation                                       ;
        mvi     a , 55h                            ;
        lxi     h , 1234h                          ;
        lxi     b , 2345h                          ;
        ani     0ffh                               ;    - zeruje UI
;        ori     0ffh                               ;    - ustawia UI
;        xri     0ffh                               ;    - ustawia UI
;        adi     0ffh                               ;    - zeruje UI
;        aci     0ffh                               ;    - zeruje UI
;        sbi     0ffh                               ;    - zeruje UI
;        sui     0ffh                               ;    - zeruje UI
;        cpi     0ffh                               ;    - zeruje UI
;        rlc                                        ;    - nie zmienia UI
;        rrc                                        ;    - nie zmienia UI
;        ral                                        ;    - nie zmienia UI
;        rar                                        ;    - nie zmienia UI
;        inr     a                                  ;    - zeruje UI
;        dcr     a                                  ;    - zeruje UI
;        dad     b                                  ;    - nie zmienia UI
;        arhl                                       ;    - nie zmienia UI
;        dsub                                       ;    - ustawia po swojemu
;        rdel                                       ;    - nie zmienia UI
        ret                                        ;
;***************************************************
BCPrompt        .defb   'BC=',0
;***************************************************
OperationTxtInc .defb   ' operacja inkrementacji' ,0
OperationTxtDec .defb   ' operacja dekrementacji' ,0
;***************************************************
DispInfo                                           ;
        call    ClrScrLCD                          ;
        lxi     h , BCPrompt                       ;
        call    WriteTextLCD                       ;
        lda     Argument + 1                       ;
        call    DispHex                            ;
        lda     Argument                           ;
        call    DispHex                            ;
        ret                                        ;
;***************************************************
UITestInc                                          ;
        push    b                                  ;
        call    SaveArg                            ;
        call    DispInfo                           ;
        lxi     h , OperationTxtInc                ;
        call    WriteTextLCD                       ;
        call    StepWait                           ;
        call    ClrScrLCD                          ;
        call    ClearFlags                         ;
        pop     b                                  ;
        inx     b                                  ;
        lxi     h , ProcFlags1                     ;
        call    SaveFlags                          ;
        call    OthOperation                       ;
        lxi     h , ProcFlags2                     ;
        call    SaveFlags                          ;
        mvi     a , 'A'                            ;
        call    WriteChLCD                         ;
        lda     ProcFlags1                         ;
        call    DispFlags                          ;
        call    NewLineLCD                         ;
        mvi     a , 'B'                            ;
        call    WriteChLCD                         ;
        lda     ProcFlags2                         ;
        call    DispFlags                          ;
        ret                                        ;
;***************************************************
UITestDec                                          ;
        push    b                                  ;
        call    SaveArg                            ;
        call    DispInfo                           ;
        lxi     h , OperationTxtDec                ;
        call    WriteTextLCD                       ;
        call    StepWait                           ;
        call    ClrScrLCD                          ;
        call    ClearFlags                         ;
        pop     b                                  ;
        dcx     b                                  ;
        lxi     h , ProcFlags1                     ;
        call    SaveFlags                          ;
        call    OthOperation                       ;
        lxi     h , ProcFlags2                     ;
        call    SaveFlags                          ;
        mvi     a , 'A'                            ;
        call    WriteChLCD                         ;
        lda     ProcFlags1                         ;
        call    DispFlags                          ;
        call    NewLineLCD                         ;
        mvi     a , 'B'                            ;
        call    WriteChLCD                         ;
        lda     ProcFlags2                         ;
        call    DispFlags                          ;
        ret                                        ;
;***************************************************
SaveFlags                                          ;
        push    psw                                ;
        pop     d                                  ;
        mov     m , e                              ;
        ret                                        ;
;***************************************************
SPrompt         .defb   ' S=',0
ZPrompt         .defb   ' Z=',0
UIPrompt        .defb   ' UI=',0
ACPrompt        .defb   ' AC=',0
PPrompt         .defb   ' P=',0
VPrompt         .defb   ' V=',0
CPrompt         .defb   ' C=',0
;***************************************************
SFlagMask       .equ    10000000b                  ;
ZFlagMask       .equ    01000000b                  ;
UIFlagMask      .equ    00100000b                  ;
ACFlagMask      .equ    00010000b                  ;
PFlagMask       .equ    00000100b                  ;
VFlagMask       .equ    00000010b                  ;
CFlagMask       .equ    00000001b                  ;
;***************************************************
DispFlags                                          ;
        push    psw                                ;
        lxi     h , SPrompt                        ;
        call    WriteTextLCD                       ;
        pop     psw                                ;
        push    psw                                ;
        ani     SFlagMask                          ;
        call    DispBit                            ;
        lxi     h , ZPrompt                        ;
        call    WriteTextLCD                       ;
        pop     psw                                ;
        push    psw                                ;
        ani     ZFlagMask                          ;
        call    DispBit                            ;
        lxi     h , UIPrompt                       ;
        call    WriteTextLCD                       ;
        pop     psw                                ;
        push    psw                                ;
        ani     UIFlagMask                         ;
        call    DispBit                            ;
        lxi     h , ACPrompt                       ;
        call    WriteTextLCD                       ;
        pop     psw                                ;
        push    psw                                ;
        ani     ACFlagMask                         ;
        call    DispBit                            ;
        lxi     h , PPrompt                        ;
        call    WriteTextLCD                       ;
        pop     psw                                ;
        push    psw                                ;
        ani     PFlagMask                          ;
        call    DispBit                            ;
        lxi     h , VPrompt                        ;
        call    WriteTextLCD                       ;
        pop     psw                                ;
        push    psw                                ;
        ani     VFlagMask                          ;
        call    DispBit                            ;
        lxi     h , CPrompt                        ;
        call    WriteTextLCD                       ;
        pop     psw                                ;
        ani     CFlagMask                          ;
        call    DispBit                            ;
        ret                                        ;
;***************************************************
DispHex                                            ;
        push    psw                                ;
        rrc                                        ;
        rrc                                        ;
        rrc                                        ;
        rrc                                        ;
        ani     0FH                                ;
        call    HexChar                            ;
        pop     psw                                ;
        ani     0FH                                ;
        call    HexChar                            ;
        ret                                        ;
;***************************************************
HexTable       .defb '0123456789ABCDEF'            ;
;***************************************************
HexChar                                            ;
        lxi    h , HexTable                        ;
        mov    c , a                               ;
        mvi    b , 0                               ;
        dad    b                                   ;
        mov    a , m                               ;
        call   WriteChLCD                          ;
        ret                                        ;
;***************************************************
StepWait                                           ;
StWt_0                                             ;
        lxi     b , IRQFlag                        ;
        ldax    b                                  ;
        cpi     0                                  ;
        jz      StWt_0                             ;
        mvi     a , 0                              ;
        stax    b                                  ;
        ret                                        ;
;***************************************************
DispBit                                            ;
        cpi     0                                  ;
        jz      DispBI_1                           ;
        mvi     a , '1'                            ;
        call    WriteChLCD                         ;
        ret                                        ;
DispBI_1                                           ;
        mvi     a , '0'                            ;
        call    WriteChLCD                         ;
        ret                                        ;
;***************************************************

Badania
uiflag01.jpg

W podprogramie OthOperation wykonywana jest jedna dodatkowa operacja 8-bitowa. W tym przypadku jest to instrukcja iloczynu logicznego.
Start dla rejestru BC (będzie on inkrementowany/dekrementowany) z zawartością 1111 hex.
uiflag02.jpg

Wykonanie operacji inkrement nie generuje ustawienia wskaźnika UI (UI=0, raport wskaźników w wierszu A). Po wykonaniu dodatkowej operacji iloczynu logicznego UI=0 (wskaźnik może być nie tykany, lub zerowany).
uiflag03.jpg

Inkrement samych jedynek w BC powinien wygenerować ustawienie wskaźnika UI.
uiflag04.jpg

I tak jest w istocie: po instrukcji inx b, wskaźnik UI=1. W dalszej kolejności wykonanie iloczynu logicznego dało wynik UI=0, czyli flaga została zmieniona.
uiflag05.jpg

Inkrement samych zer daje podobny wynik jak inkrement 1111 hex, wskaźnik UI=0 i dalej po instrukcji iloczynu logicznego nadal UI=0.
uiflag06.jpg

uiflag07.jpg

Dekrement 1111 hex nie wniósł żadnych rewolucyjnych zmian: po instrukcji dekrementacji wskaźnik nie jest ustawiony oraz po kolejnej instrukcji 8-bitowego iloczynu logicznego nadal jest wyzerowany.
uiflag08.jpg

uiflag09.jpg

Podobnie jak dekrement samych jedynek.
uiflag10.jpg

uiflag11.jpg

Natomiast dekrement samych zer,
uiflag12.jpg

ustawia wskaźnik UI i następna instrukcja iloczynu logicznego go zeruje.
uiflag13.jpg

Można wysnuć wniosek, że jednak operacje 8-bitowe odciskają swoje piętno na wskaźniku UI związanym z operacją 16-bitowego inkrementy/dekrementu. Wychodzi na to, że iloczyn logiczny zeruje wskaźnik UI.
Inna instrukcja 8-bitowa prowadzi do odmiennego stanu. Użycie instrukcji 8-bitowej sumy logicznej ustawia wskaźnik UI (bez względu na stan wskaźnika UI przed instrukcją sumy logicznej, po jej wykonaniu wskaźnik jest ustawiony).
uiflag14.jpg

uiflag15.jpg

Inna instrukcja (obrotu zawartości akumulatora) nie zmienia stanu wskaźnika: przed obrotem i po obrocie stan wskaźnika jest taki sam.
uiflag16.jpg

uiflag17.jpg

Znacząco odmiennie zachowuje się instrukcja DSUB, która ustawia wskaźnik UI według własnego uznania. Po przebadaniu innych instrukcji tworzy się następująca tabelka:
  • iloczyn logiczny - zeruje UI
  • suma logiczna - ustawia UI
  • suma XOR - ustawia UI
  • suma arytmetyczna - zeruje UI
  • suma arytmetyczna z uwzględnieniem CY - zeruje UI
  • różnica arytmetyczna - zeruje UI
  • różnica arytmetyczna z uwzględnieniem CY - zeruje UI
  • komparacja - zeruje UI
  • obrót rlc - nie zmienia UI
  • obrót rrc - nie zmienia UI
  • obrót ral - nie zmienia UI
  • obrót rar - nie zmienia UI
  • inkrement 8-bitowy - zeruje UI
  • dekrement 8-bitowy - zeruje UI
  • suma 16-bitowa - nie zmienia UI
  • instrukcja arhl - nie zmienia UI
  • instrukcja dsub - ustawia po swojemu
  • instrukcja rdel - nie zmienia UI

Użyty soft:
uiflag.zip
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


Wróć do „Retro”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 8 gości