I8085 - emulator procesora
I8085 - emulator procesora
Emulator procesora i8085
Nadeszła w końcu ta chwila, by zająć się stworzeniem softu dla generatora opartego na procku i8085. Ot wala mi się kilka takich w szufladzie, więc uznałem, że to dobry pomysł, by zatrudnić ich do jakiegoś działania. Sprzęciora już nawet zrobiłem, więc pora na kolejny krok do celu. Jakiś czas tam napisałem sobie program, który kompiluje program w asm i generuje kod binarny w formacie hex. Być może i są jakieś niekomercyjne narzędzia pozwalające na tworzenie softu dla tych procków. Prawdę mówiąc to specjalnie nie szukałem. Zacząłem nawet tworzyć kawałek softu, jednak zaczęło mi się trochę kaszanić w programie. Bo to człowiek już dawno nie pisał w asemblerze, a tu w dodatku jeszcze takim trochę dziwnym, gdyż będąc przyzwyczajony do składni zilogowej, która jest jasna i klarowna, to należy wrócić do składni inteloskiej. Ta już nie jest tak elegancka, ale nie ma co narzekać i wytykać intelowi jakieś uwagi. Chłopcy zrobili to jak zrobili i tyle.
Rozwiązaniem tego problemu jest posiadanie emulatora działania procka: czy to sprzętowego czy programowego. W kwestii emulatorów sprzętowych, to … są absolutnie poza zasięgiem. Ten procek był na topie jakieś 50 lat tamu i dzisiaj, nawet jeżeli takowe istnieją to będą kosztowały majątek. Pozostaje rozwiązanie w wariancie emulatora programowego. Generalnie nie jest to jakiś wielki problem, ot program jak program, jest to napisania. Pozostaje kwestia dostępu do właściwej wiedzy. Tu staje się przydatna moja stara książka, która wniosła wiele w rozumienie techniki mikroprocesorowej: praca zbiorowa, „Modułowe systemy mikrokomputerowe”.
W owej książce jest podana lista instrukcji procka i8080 i rozszerzenia dla procka i8085 (oczywista, że najwięcej miejsca jest poświęcone Z80). Ogólnie wiadomo, że Z80 jest kompatybilny pod względem kodów binarnych z prockami intela dysponując jednak znacząco większą liczbą instrukcji. Ano zostało to zrobione poprzez wykorzystanie „dziur” w kodach intelowych (tych od i8080). Procek i8085 również wykorzystał wolne miejsca, gdyż doszły dwie instrukcje (RIM i SIM). No więc będąc wyposażony w szczegółową wiedzę, postanowiłem stworzyć program emulatora.
Jednak coś mnie tknęło i postanowiłem podane informacje zweryfikować. Dotarłem do oryginalnej dokumentacji tego procka:
gdzie jasno jest postawiona sprawa, że praca zbiorowa jest polskim nadużyciem i mija się trochę z prawdą. Poza tym jest więcej istotnych szczegółów, których znajomość jest niezbędna do stworzenia poprawnie działającego programu.
No i oczywista, jest lista instrukcji wraz z ich kodami. No i nawet bez okularów widać, że procek nie realizuje instrukcji opisanych w polskiej książce.
Powstał mały dylemat: kto mówi prawdę? Tu nie wahałem się zbytnio i zaufałem oryginalnym publikacjom. Przykładowo kod CB hex będący dla ziloga prefiksem rozszerzenia do operacji bitowych, czy ED hex jako rozszerzenie do wielu ciekawych i przydatnych instrukcji czy DD hex i FD hex jako prefiksy do instrukcji operujących na rejestrach indeksowych, których w prockach intelowych nie ma. Te kody (i kilka innych) to są dziury dla procka i8085. Swoją drogą ciekawe co zrobi procek i8085, jak go się przymusi do wykonania tych instrukcji. To może być ciekawy temat badawczy, bo jak coś takiego zbadać? Procek może to olać, zawisnąć a może zrobić coś innego i tajemniczego. No może to kiedyś sprawdzę.
No więc stworzyłem sobie program do śledzenia wykonania programu dla procka i8085. Napisałem go sobie w pascalu (lazarus).
Moim celem jest stworzenie narzędzia pozwalającego na diagnostykę w szerokim zakresie. Wymaga to określenia dla programu wielu informacji, gdyż program wyłapuje przykładowo zapis do pamięci EPROM, odczyt/zapis z pamięci nieistniejącej (gdyż nie ma obowiązku, by do procka była przypięta pamięć wypełniająca całą przestrzeń adresową). Podobnie są monitorowane użycia portów we/wy. Należy wcześniej określić jakie adresy portów są używane i symulacja wykonania programu dla procka i8085 się zatrzyma, jeżeli nie zostaną wyspecyfikowane „legalne” adresy portów. By nie wklepywać tego za każdym razem, jest plik opisujący projekt (symulacji). Oczywiście, wszystkie szczegóły można w dowolnej chwili zmodyfikować.
Przykładowy projekt: w okienku projektu wyświetlone są wszystkie szczegóły dotyczące środowiska, w którym jest uruchamiany program.
System prockowy składa się z pamięci EPROM (lub innej nieulotnej) lokowanej w przestrzeni od 0000 hex do 7FFF hex oraz pamięć RAM lokowana od 8000 hex do FFFF hex. W sumie obie pamięci wypełniają całą przestrzeń. Dodatkowo występują porty wejścia, porty wyjścia (jak przykładowo i8212) czy porty wyjścia/wejścia (jak przykładowo i8255). Dla jednych dostępne są jedynie instrukcje IN, dla innych jedynie OUT lub dla tych trzecich zarówno IN jak i OUT. Również program emulatora wspiera obsługę przerwań. Może to być kontroler zbudowany na bazie i8214, który generuje instrukcje RST 1 … RST 7 lub przerwania połówkowe, które są zintegrowane w samym procku. No i oczywiście przerwanie niemaskowalne TRAP. Te przerwania (niemaskowalne oraz połówkowe) mogą być nieużywane w systemie (ze stałym sygnałem wymuszonym przez odpowiednie przyłączenie wejścia do masy lub VCC), toteż istnieje możliwość, że klikanie na przycisk do zgłaszania przerwania pozostanie bez reakcji.
Manual:
Nadeszła w końcu ta chwila, by zająć się stworzeniem softu dla generatora opartego na procku i8085. Ot wala mi się kilka takich w szufladzie, więc uznałem, że to dobry pomysł, by zatrudnić ich do jakiegoś działania. Sprzęciora już nawet zrobiłem, więc pora na kolejny krok do celu. Jakiś czas tam napisałem sobie program, który kompiluje program w asm i generuje kod binarny w formacie hex. Być może i są jakieś niekomercyjne narzędzia pozwalające na tworzenie softu dla tych procków. Prawdę mówiąc to specjalnie nie szukałem. Zacząłem nawet tworzyć kawałek softu, jednak zaczęło mi się trochę kaszanić w programie. Bo to człowiek już dawno nie pisał w asemblerze, a tu w dodatku jeszcze takim trochę dziwnym, gdyż będąc przyzwyczajony do składni zilogowej, która jest jasna i klarowna, to należy wrócić do składni inteloskiej. Ta już nie jest tak elegancka, ale nie ma co narzekać i wytykać intelowi jakieś uwagi. Chłopcy zrobili to jak zrobili i tyle.
Rozwiązaniem tego problemu jest posiadanie emulatora działania procka: czy to sprzętowego czy programowego. W kwestii emulatorów sprzętowych, to … są absolutnie poza zasięgiem. Ten procek był na topie jakieś 50 lat tamu i dzisiaj, nawet jeżeli takowe istnieją to będą kosztowały majątek. Pozostaje rozwiązanie w wariancie emulatora programowego. Generalnie nie jest to jakiś wielki problem, ot program jak program, jest to napisania. Pozostaje kwestia dostępu do właściwej wiedzy. Tu staje się przydatna moja stara książka, która wniosła wiele w rozumienie techniki mikroprocesorowej: praca zbiorowa, „Modułowe systemy mikrokomputerowe”.
W owej książce jest podana lista instrukcji procka i8080 i rozszerzenia dla procka i8085 (oczywista, że najwięcej miejsca jest poświęcone Z80). Ogólnie wiadomo, że Z80 jest kompatybilny pod względem kodów binarnych z prockami intela dysponując jednak znacząco większą liczbą instrukcji. Ano zostało to zrobione poprzez wykorzystanie „dziur” w kodach intelowych (tych od i8080). Procek i8085 również wykorzystał wolne miejsca, gdyż doszły dwie instrukcje (RIM i SIM). No więc będąc wyposażony w szczegółową wiedzę, postanowiłem stworzyć program emulatora.
Jednak coś mnie tknęło i postanowiłem podane informacje zweryfikować. Dotarłem do oryginalnej dokumentacji tego procka:
gdzie jasno jest postawiona sprawa, że praca zbiorowa jest polskim nadużyciem i mija się trochę z prawdą. Poza tym jest więcej istotnych szczegółów, których znajomość jest niezbędna do stworzenia poprawnie działającego programu.
No i oczywista, jest lista instrukcji wraz z ich kodami. No i nawet bez okularów widać, że procek nie realizuje instrukcji opisanych w polskiej książce.
Powstał mały dylemat: kto mówi prawdę? Tu nie wahałem się zbytnio i zaufałem oryginalnym publikacjom. Przykładowo kod CB hex będący dla ziloga prefiksem rozszerzenia do operacji bitowych, czy ED hex jako rozszerzenie do wielu ciekawych i przydatnych instrukcji czy DD hex i FD hex jako prefiksy do instrukcji operujących na rejestrach indeksowych, których w prockach intelowych nie ma. Te kody (i kilka innych) to są dziury dla procka i8085. Swoją drogą ciekawe co zrobi procek i8085, jak go się przymusi do wykonania tych instrukcji. To może być ciekawy temat badawczy, bo jak coś takiego zbadać? Procek może to olać, zawisnąć a może zrobić coś innego i tajemniczego. No może to kiedyś sprawdzę.
No więc stworzyłem sobie program do śledzenia wykonania programu dla procka i8085. Napisałem go sobie w pascalu (lazarus).
Moim celem jest stworzenie narzędzia pozwalającego na diagnostykę w szerokim zakresie. Wymaga to określenia dla programu wielu informacji, gdyż program wyłapuje przykładowo zapis do pamięci EPROM, odczyt/zapis z pamięci nieistniejącej (gdyż nie ma obowiązku, by do procka była przypięta pamięć wypełniająca całą przestrzeń adresową). Podobnie są monitorowane użycia portów we/wy. Należy wcześniej określić jakie adresy portów są używane i symulacja wykonania programu dla procka i8085 się zatrzyma, jeżeli nie zostaną wyspecyfikowane „legalne” adresy portów. By nie wklepywać tego za każdym razem, jest plik opisujący projekt (symulacji). Oczywiście, wszystkie szczegóły można w dowolnej chwili zmodyfikować.
Przykładowy projekt: w okienku projektu wyświetlone są wszystkie szczegóły dotyczące środowiska, w którym jest uruchamiany program.
System prockowy składa się z pamięci EPROM (lub innej nieulotnej) lokowanej w przestrzeni od 0000 hex do 7FFF hex oraz pamięć RAM lokowana od 8000 hex do FFFF hex. W sumie obie pamięci wypełniają całą przestrzeń. Dodatkowo występują porty wejścia, porty wyjścia (jak przykładowo i8212) czy porty wyjścia/wejścia (jak przykładowo i8255). Dla jednych dostępne są jedynie instrukcje IN, dla innych jedynie OUT lub dla tych trzecich zarówno IN jak i OUT. Również program emulatora wspiera obsługę przerwań. Może to być kontroler zbudowany na bazie i8214, który generuje instrukcje RST 1 … RST 7 lub przerwania połówkowe, które są zintegrowane w samym procku. No i oczywiście przerwanie niemaskowalne TRAP. Te przerwania (niemaskowalne oraz połówkowe) mogą być nieużywane w systemie (ze stałym sygnałem wymuszonym przez odpowiednie przyłączenie wejścia do masy lub VCC), toteż istnieje możliwość, że klikanie na przycisk do zgłaszania przerwania pozostanie bez reakcji.
Manual:
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: I8085 - emulator procesora
phill2k pisze:A ja znalazłem takie cudeńka, może będą pomocne.
No dzięki, ale już napisałem własny program .
Deasemblacja
Dysponując programem binarnym (w zapisie intel-hex), fajnie by było, by na ekranie było widać co się dzieje: co program robi, gdzie jest. Pierwszą czynnością po wczytaniu kodu hex, jest jego desemblacja. Generalnie taka operacja nie jest jednoznaczna, gdyż trudno jest wyrokować o sensie zawartości przykładowo pary rejestrów HL. To może być adres skoku jak w instrukcji PCHL [w wersji zilogowej JP (HL)], to może być adres operandu w instrukcji arytmetycznej lub wręcz może pełnić rolę akumulatora w arytmetyce 16-bitowej. Ładując program intelowski do pamięci program zaczyna proces deasemblacji. Początek jest wiadomo w którym miejscu: adres 0. I tak instrukcja po instrukcji tłumaczony jest kod na prawdopodobną wersję źródłową. Napisałem prawdopodobną, gdyż nie ma gwarancji, że ta czynność będzie zgodna z intencjami autora, a te są tu zawsze nadrzędne. Algorytm deasemblacji jest rekurencyjny (to najprostsza implementacja). I posiłkuje się stałą tablicą opisującą kody instrukcji. Jest wykorzystywana do symulacji działania oraz do deasemblacji.
Patrząc na tą tablicę z istotnego obecnie punktu widzenia (deasemblacja) tabela zawiera liczbę bajtów jakie zajmuje każda instrukcja oraz informację o „zaburzeniach” realizacji instrukcji. Większość instrukcji ma flagę kontynuacji (deasemblacji), przykładowo: ( OpCodeSize : 1 ; Operation : PUSH_D_Operation ; OpCodeName : 'push d' ; Operand : VoidOperand ; OpCodeFlag : ContinueFlag ) , i oznacza, że po deasemblacji tej sztuki jedziemy dalej. Niektóre instrukcje zawierają flagę rozgałęzienia (wszystkie skoki warunkowe, wywołania warunkowe i bezwarunkowe) wykonanie programu skoczy gdzieś lub nie, ale zawsze istnieje możliwość wykonania bezpośrednio kolejnej instrukcji w kodzie, przykładowo: ( OpCodeSize : 3 ; Operation : CALL_Operation ; OpCodeName : 'call ' ; Operand : Direct16Operand ; OpCodeFlag : EntryFlag ) , i oznacza, że po deasemblacji tej sztuki wywoływana jest rekurencyjnie akcja deasemblacji od adresu wskazanego w operandzie i również jedziemy dalej. W instrukcji skoku bezwarunkowego JMP, kończona je bieżąca deasemblacja (program skoczy gdzieś i nie wróci do następnej instrukcji) i startuje rekurencyjnie deasemblacja na adres skoku. Innym wariantem instrukcji są takie, które jedynie kończą deasemblację bieżącego fragmentu i robią skok w miejsce nieokreślone w operandzie, jak RET, czy PCHL. Przykładowy opis to: ( OpCodeSize : 1 ; Operation : RET_Operation ; OpCodeName : 'ret' ; Operand : VoidOperand ; OpCodeFlag : BreakFlag ) .
Jeżeli w projekcie są wskazania na obsługę przerwań, to inicjowana jest deasemblacja na stałe adresy związane z obsługą tych przerwań. Ponieważ nie ma obowiązku, by program obsługiwał przerwania, gdyż to może być trenowany jakiś fragment programu, to nie ma potrzeby deasemblować punktów wejścia do obsługi przerwań. To nawet może okazać się szkodliwe, gdyż istnieje szansa powstania konfliktów: obsługa przerwania może trafić w środek wielobajtowej instrukcji i wtedy to powstaje już kaszana.
Ten algorytm „przechodzi” każde rozgałęzienie programu intelowego, więc to co zostało „nie tykane” może stanowić obszar danych stałych. Program konwertuje te obszary do postaci define byte. Oczywiście w tym wszystkim jest jeden wyjątek: instrukcja PCHL, które realizuje skok, tylko nie wiadomo dokąd (na etapie deaseblacji). W ten oto sposób mogą być „wykryte” fragmenty martwego kodu, który nigdy nie ma szans na wykonanie. Przykładowo (fragment mojego generatora losowego):
Kod: Zaznacz cały
Improved compiler for INTEL 8080/8085 processor, version 2.0, licence: CC BY 3.0
L.NO MEMO CODE SRC
Open file: D:\lazarus_project\I8080\T8080.ASM
1. ;
2. .i8085
3. 0000 ResetEntry .equ 0000h
4. .org ResetEntry
5. 0000 F3 di
6. 0001 310000 lxi sp,0
7. 0000 Stack_top .equ 0h
8. 0004 F3 di ;
9. 0005 310000 lxi sp , Stack_top ;
10. ;
11. 0008 CD1F00 call Init_random ;
12. 000B CD2C00 call CreateNewRandom ;
13. ;
14. 000E CD5900 call Init_variable ;
15. 0011 CD5A00 call Init_hardware ;
16. 0014 CD5B00 call Init_envir ;
17. ;.
18. 0017 Stop_prg ;
19. 0017 C31700 jmp Stop_prg ;
20. ;***************************************************
21. 001A Martwy_kod
22. 001A 00 nop ;
23. 001B 00 nop ;
24. 001C 00 nop ;
25. 001D 00 nop ;
26. 001E 00 nop ;
27. ;***************************************************
28. 001F Init_random ;
29. 001F 210080 lxi h , RandomSeed ;
30. 0022 110280 lxi d , RandomV ;
31. 0025 7E mov a , m ;
32. 0026 12 stax d ;
33. 0027 23 inx h ;
34. 0028 13 inx d ;
35. 0029 7E mov a , m ;
36. 002A 12 stax d ;
37. 002B C9 ret ;
38. ;***************************************************
39. ; RandomV = ( ( MultConst * RandomV ) + AddConst ) ;
40. ; MultConst = 129, AddConst = 9
41. 002C CreateNewRandom
42. ;function CreateNewRandom ( ) : word [HL]
43. 002C 110280 lxi d , RandomV ;
44. 002F 1A ldax d ;
45. 0030 6F mov l , a ;
46. 0031 13 inx d ;
47. 0032 1A ldax d ;
48. 0033 67 mov h , a ;
49. 0034 E5 push h ;
50. 0035 C1 pop b ;
51. 0036 CD5100 call ShiftLBC ;
52. 0039 CD5100 call ShiftLBC ;
53. 003C CD5100 call ShiftLBC ;
54. 003F CD5100 call ShiftLBC ;
55. 0042 CD5100 call ShiftLBC ;
56. 0045 CD5100 call ShiftLBC ;
57. 0048 CD5100 call ShiftLBC ;
58. 004B 09 dad b ;
59. 004C 010900 lxi b , 09h ;
60. 004F 09 dad b ;
61. 0050 C9 ret ;
62. ;***************************************************
63. 0051 ShiftLBC ;
64. ;function ShiftLBC ( Arg [BC] : word ) : word [BC]
65. 0051 79 mov a , c ;
66. 0052 B7 ora a ;
67. 0053 17 ral ;
68. 0054 4F mov c , a ;
69. 0055 78 mov a , b ;
70. 0056 17 ral ;
71. 0057 47 mov b , a ;
72. 0058 C9 ret ;
73. ;***************************************************
74. 0059 Init_variable ;
75. 0059 C9 ret ;
76. ;***************************************************
77. 005A Init_hardware ;
78. 005A C9 ret ;
79. ;***************************************************
80. 005B Init_envir ;
81. 005B C9 ret ;
82. .org 08000h ;
83. 8000 RandomSeed .word 1 ;
84. 8002 RandomV .word 1 ;
85. .end ;
Close file: D:\lazarus_project\I8080\T8080.ASM
Compilation :successful
Zawiera fragment kodu, do którego nie prowadzi żadna droga w trakcie wykonania programu. Jego deasemblacja to:
Jednak czasami jest to informacja nie do końca prawdziwa. Przykładowo:
Kod: Zaznacz cały
Improved compiler for INTEL 8080/8085 processor, version 2.0, licence: CC BY 3.0
L.NO MEMO CODE SRC
Open file: D:\lazarus_project\I8080\T8080.ASM
1. ;
2. .i8085
3. 0000 ResetEntry .equ 0000h
4. 007B Data8 .equ 123
5. .org ResetEntry
6. 0000 F3 di
7. 0001 310000 lxi sp,0
8. 0004 210A00 lxi h,subr
9. 0007 E9 pchl
10. 0008 00 nop ; to jest martwy kod
11. 0009 00 nop ; to jest martwy kod
12. 000A subr:
13. 000A CE7B ACI Data8
14. 000C 8F ADC A
15. 000D 88 ADC B
16. 000E 89 ADC C
17. 000F 8A ADC D
18. 0010 8B ADC E
19. 0011 8C ADC H
20. 0012 8D ADC L
21. 0013 EB XCHG
22. 0014 8E ADC M
23. 0015 87 ADD A
24. 0016 80 ADD B
25. 0017 81 ADD C
26. 0018 82 ADD D
27. 0019 83 ADD E
28. 001A 84 ADD H
29. 001B 85 ADD L
30. 001C 86 ADD M
31. 001D C67B ADI Data8
32. 001F A7 ANA A
33. 0020 A0 ANA B
34. 0021 A1 ANA C
35. 0022 A2 ANA D
36. 0023 A3 ANA E
37. 0024 A4 ANA H
38. 0025 A5 ANA L
39. 0026 A6 ANA M
40. 0027 E67B ANI Data8
41. 0029 2F CMA
42. 002A 3F CMC
43. 002B BF CMP A
44. 002C B8 CMP B
45. 002D B9 CMP C
46. 002E BA CMP D
47. 002F BB CMP E
48. 0030 BC CMP H
49. 0031 BD CMP L
50. 0032 BE CMP M
51. 0033 C33300 Loop JMP Loop
52. .end
Close file: D:\lazarus_project\I8080\T8080.ASM
Compilation :successful
Daje następujący wynik:
Do zaznaczonego fragmentu nie prowadzi żadna jawna ścieżka wywołania a prawdziwa rzeczywistość wyjaśni się dopiero w trakcie symulacji wykonania programu. Zaistnienie zdarzenia, gdzie następuje próba wykonania czegoś, co zostało zakwalifikowane jako blok stałych danych, generuje zatrzymanie i pytanie, czy „mamy ochotę to naprawić”.
Istnieje taka możliwość i realizowana jest deasemblacja „w biegu”. Fragment tego fragmentu nadal pozostaje oznaczony jako martwy kod (tym razem już prawdziwy).
Istnieje możliwość zapisania do pliku wyniku deasemblacji po kliknięciu prawym klawiszem myszki.
Powstała postać „źródłowa” jest następująca:
Kod: Zaznacz cały
; ***************************************
; ** Deasemblacja kodu procesora i8085 **
; ** przez program emulatora I8085 **
; ** Licencja: CC BY 3.0 **
; ***************************************
.org 00000h
L0000: di
lxi sp,00000h ; 00000
lxi h,0000Ah ; 00010
pchl
.defb 000h ; 000
.defb 000h ; 000
L000A: aci 07Bh ; 123
adc a
adc b
adc c
adc d
adc e
adc h
adc l
xchg
adc m
add a
add b
add c
add d
add e
add h
add l
add m
adi 07Bh ; 123
ana a
ana b
ana c
ana d
ana e
ana h
ana l
ana m
ani 07Bh ; 123
cma
cmc
cmp a
cmp b
cmp c
cmp d
cmp e
cmp h
cmp l
cmp m
L0033: jmp L0033
.end
I tak to wyszła nieoczekiwanie fajna funkcja dotycząca wyłapywania martwego kodu.
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: I8085 - emulator procesora
Dzięki phill2k, pozycja 8080 8085 Software Design okazała się nawet całkiem ciekawa.
Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse
Re: I8085 - emulator procesora
gaweł pisze: Te kody (i kilka innych) to są dziury dla procka i8085.
i8085 nie ma dziur w liście rozkazów, są tam zdefiniowane i jednolite dla każdego producenta instrukcje o których intel nie był łaskaw wspomnieć, by nie utrzymywać popularności procesorów 8-bit po premierze swojego 8086, a które były zawarte już w pierwszych maskach NMOS tego procesora. 8085 to niechciane dziecko marketingu tej firmy. Na tym forum o nich wspomniałem, a do tych instrukcji przyznaje się tylko kanadyjska firma Tundra, reszta producentów o nich milczy.
Re: I8085 - emulator procesora
tapy pisze:i8085 nie ma dziur w liście rozkazów, są tam zdefiniowane i jednolite dla każdego producenta instrukcje o których intel nie był łaskaw wspomnieć, by nie utrzymywać popularności procesorów 8-bit po premierze swojego 8086, a które były zawarte już w pierwszych maskach NMOS tego procesora. 8085 to niechciane dziecko marketingu tej firmy. Na tym forum o nich wspomniałem, a do tych instrukcji przyznaje się tylko kanadyjska firma Tundra, reszta producentów o nich milczy.
A faktycznie, przypominam sobie. Ściągnąłem PDF Tundry i porównałem z informacją w książce "Modułowe systemy mikroprocesorowe". Generalnie informacje są zbieżna i występuje jedynie różnica w nazwie dwóch instrukcji. W dokumentacji Tundry podane są informacje o zachowaniu się wskaźników, co dla emulatora jest niezmiernie istotne i rozszerzę swój program emulatora o nowe instrukcje. Będzie super.
Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse
Re: I8085 - emulator procesora
Korekta do nowych możliwości
Jak obiecałem, tak i robię, ale pojawił się niespodziewany problem (chyba, że czegoś nie rozumiem). Otóż, w dokumentacji "nieautoryzowanych" instrukcji jest:
W instrukcji LHLX występuje jednobajtowy operand i to się kłóci z moim wyobrażeniem. Z opisu nie wynika, by ta instrukcja wymagała operandu, więc WTF?
Jak obiecałem, tak i robię, ale pojawił się niespodziewany problem (chyba, że czegoś nie rozumiem). Otóż, w dokumentacji "nieautoryzowanych" instrukcji jest:
W instrukcji LHLX występuje jednobajtowy operand i to się kłóci z moim wyobrażeniem. Z opisu nie wynika, by ta instrukcja wymagała operandu, więc WTF?
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: I8085 - emulator procesora
To jakiś chochlik, instrukcja jest jednobajtowa w nomenklaturze ziloga wyglądała by tak: LD HL, (DE)
Re: I8085 - emulator procesora
tapy pisze:To jakiś chochlik...
No popatrz, każdy może się pomylić. Dokumentacja zapewne ma kilkadziesiąt lat i nikt nie zauważył...? Jak na wszystko trzeba uważać
W każdym bądź razie już zmodyfikowałem swój kompiler, by akceptował nowe instrukcje i można było bardziej przetestować emulator, w końcu ktoś musi wygenerować rozszerzone kody. Kompiler działa:
Kod: Zaznacz cały
Improved compiler for INTEL 8080/8085 processor, version 2.1, licence: CC BY 3.0
L.NO MEMO CODE SRC
Open file: D:\microgeek\asm8080\T8085.ASM
1. ;
2. ; ***************************************************
3. ; * *
4. ; * *
5. ; * zbior instrukcji mikroprocesora 8085 *
6. ; * *
7. ; * *
8. ; ***************************************************
9. ;
10. .i8085
11. .org 0
12. 1234 Data16 .equ 1234h
13. 0056 Data8 .equ 56h
14. 0000 48656C6C Hello .defb 'Hello world'
0004 6F20776F
0008 726C64
15. 000B 76 HLT ; 76
16. 000C CE56 ACI Data8 ; CE56
17. 000E 8F ADC A ; 8F
18. 000F 88 ADC B ; 88
19. 0010 89 ADC C ; 89
20. 0011 8A ADC D ; 8A
21. 0012 8B ADC E ; 8B
22. 0013 8C ADC H ; 8C
23. 0014 8D ADC L ; 8D
24. 0015 8E ADC M ; 8E
25. 0016 87 ADD A ; 87
26. 0017 80 ADD B ; 80
27. 0018 81 ADD C ; 81
28. 0019 82 ADD D ; 82
29. 001A 83 ADD E ; 83
30. 001B 84 ADD H ; 84
31. 001C 85 ADD L ; 85
32. 001D 86 ADD M ; 86
33. 001E C656 ADI Data8 ; C656
34. 0020 A7 ANA A ; A7
35. 0021 A0 ANA B ; A0
36. 0022 A1 ANA C ; A1
37. 0023 A2 ANA D ; A2
38. 0024 A3 ANA E ; A3
39. 0025 A4 ANA H ; A4
40. 0026 A5 ANA L ; A5
41. 0027 A6 ANA M ; A6
42. 0028 E656 ANI Data8 ; E656
43. 002A CD3412 CALL Data16 ; CD3412
44. 002D DC3412 CC Data16 ; DC3412
45. 0030 FC3412 CM Data16 ; FC3412
46. 0033 2F CMA ; 2F
47. 0034 3F CMC ; 3F
48. 0035 BF CMP A ; BF
49. 0036 B8 CMP B ; B8
50. 0037 B9 CMP C ; B9
51. 0038 BA CMP D ; BA
52. 0039 BB CMP E ; BB
53. 003A BC CMP H ; BC
54. 003B BD CMP L ; BD
55. 003C BE CMP M ; BE
56. 003D D43412 CNC Data16 ; D43412
57. 0040 C43412 CNZ Data16 ; C43412
58. 0043 F43412 CP Data16 ; F43412
59. 0046 EC3412 CPE Data16 ; EC3412
60. 0049 FE56 CPI Data8 ; FE56
61. 004B E43412 CPO Data16 ; E43412
62. 004E CC3412 CZ Data16 ; CC3412
63. 0051 27 DAA ; 27
64. 0052 09 DAD B ; 09
65. 0053 19 DAD D ; 19
66. 0054 29 DAD H ; 29
67. 0055 39 DAD SP ; 39
68. 0056 3D DCR A ; 3D
69. 0057 05 DCR B ; 05
70. 0058 0D DCR C ; 0D
71. 0059 15 DCR D ; 15
72. 005A 1D DCR E ; 1D
73. 005B 25 DCR H ; 25
74. 005C 2D DCR L ; 2D
75. 005D 35 DCR M ; 35
76. 005E 0B DCX B ; 0B
77. 005F 1B DCX D ; 1B
78. 0060 2B DCX H ; 2B
79. 0061 3B DCX SP ; 3B
80. 0062 F3 DI ; F3
81. 0063 FB EI ; FB
82. 0064 76 HLT ; 76
83. 0065 DB56 IN Data8 ; DB56
84. 0067 D356 OUT Data8 ; D356
85. 0069 3C INR A ; 3C
86. 006A 04 INR B ; 04
87. 006B 0C INR C ; 0C
88. 006C 14 INR D ; 14
89. 006D 1C INR E ; 1C
90. 006E 24 INR H ; 24
91. 006F 2C INR L ; 2C
92. 0070 34 INR M ; 34
93. 0071 03 INX B ; 03
94. 0072 13 INX D ; 13
95. 0073 23 INX H ; 23
96. 0074 33 INX SP ; 33
97. 0075 DA3412 JC Data16 ; DA3412
98. 0078 FA3412 JM Data16 ; FA3412
99. 007B C33412 JMP Data16 ; C33412
100. 007E D23412 JNC Data16 ; D23412
101. 0081 C23412 JNZ Data16 ; C23412
102. 0084 F23412 JP Data16 ; F23412
103. 0087 EA3412 JPE Data16 ; EA3412
104. 008A E23412 JPO Data16 ; E23412
105. 008D CA3412 JZ Data16 ; CA3412
106. 0090 3A3412 LDA Data16 ; 3A3412
107. 0093 0A LDAX B ; 0A
108. 0094 1A LDAX D ; 1A
109. 0095 2A3412 LHLD Data16 ; 2A3412
110. 0098 013412 LXI B,Data16 ; 013412
111. 009B 113412 LXI D,Data16 ; 113412
112. 009E 213412 LXI H,Data16 ; 213412
113. 00A1 313412 LXI SP,Data16 ; 313412
114. 00A4 7F MOV A,A ; 7F
115. 00A5 78 MOV A,B ; 78
116. 00A6 79 MOV A,C ; 79
117. 00A7 7A MOV A,D ; 7A
118. 00A8 7B MOV A,E ; 7B
119. 00A9 7C MOV A,H ; 7C
120. 00AA 7D MOV A,L ; 7D
121. 00AB 7E MOV A,M ; 7E
122. 00AC 47 MOV B,A ; 47
123. 00AD 40 MOV B,B ; 40
124. 00AE 41 MOV B,C ; 41
125. 00AF 42 MOV B,D ; 42
126. 00B0 43 MOV B,E ; 43
127. 00B1 44 MOV B,H ; 44
128. 00B2 45 MOV B,L ; 45
129. 00B3 46 MOV B,M ; 46
130. 00B4 4F MOV C,A ; 4F
131. 00B5 48 MOV C,B ; 48
132. 00B6 49 MOV C,C ; 49
133. 00B7 4A MOV C,D ; 4A
134. 00B8 4B MOV C,E ; 4B
135. 00B9 4C MOV C,H ; 4C
136. 00BA 4D MOV C,L ; 4D
137. 00BB 4E MOV C,M ; 4E
138. 00BC 57 MOV D,A ; 57
139. 00BD 50 MOV D,B ; 50
140. 00BE 51 MOV D,C ; 51
141. 00BF 52 MOV D,D ; 52
142. 00C0 53 MOV D,E ; 53
143. 00C1 54 MOV D,H ; 54
144. 00C2 55 MOV D,L ; 55
145. 00C3 56 MOV D,M ; 56
146. 00C4 5F MOV E,A ; 5F
147. 00C5 58 MOV E,B ; 58
148. 00C6 59 MOV E,C ; 59
149. 00C7 5A MOV E,D ; 5A
150. 00C8 5B MOV E,E ; 5B
151. 00C9 5C MOV E,H ; 5C
152. 00CA 5D MOV E,L ; 5D
153. 00CB 5E MOV E,M ; 5E
154. 00CC 67 MOV H,A ; 67
155. 00CD 60 MOV H,B ; 60
156. 00CE 61 MOV H,C ; 61
157. 00CF 62 MOV H,D ; 62
158. 00D0 63 MOV H,E ; 63
159. 00D1 64 MOV H,H ; 64
160. 00D2 65 MOV H,L ; 65
161. 00D3 66 MOV H,M ; 66
162. 00D4 6F MOV L,A ; 6F
163. 00D5 68 MOV L,B ; 68
164. 00D6 69 MOV L,C ; 69
165. 00D7 6A MOV L,D ; 6A
166. 00D8 6B MOV L,E ; 6B
167. 00D9 6C MOV L,H ; 6C
168. 00DA 6D MOV L,L ; 6D
169. 00DB 6E MOV L,M ; 6E
170. 00DC 77 MOV M,A ; 77
171. 00DD 70 MOV M,B ; 70
172. 00DE 71 MOV M,C ; 71
173. 00DF 72 MOV M,D ; 72
174. 00E0 73 MOV M,E ; 73
175. 00E1 74 MOV M,H ; 74
176. 00E2 75 MOV M,L ; 75
177. 00E3 3E56 MVI A,Data8 ; 3E56
178. 00E5 0656 MVI B,Data8 ; 0656
179. 00E7 0E56 MVI C,Data8 ; 0E56
180. 00E9 1656 MVI D,Data8 ; 1656
181. 00EB 1E56 MVI E,Data8 ; 1E56
182. 00ED 2656 MVI H,Data8 ; 2656
183. 00EF 2E56 MVI L,Data8 ; 2E56
184. 00F1 3656 MVI M,Data8 ; 3656
185. 00F3 00 NOP ; 00
186. 00F4 B7 ORA A ; B7
187. 00F5 B0 ORA B ; B0
188. 00F6 B1 ORA C ; B1
189. 00F7 B2 ORA D ; B2
190. 00F8 B3 ORA E ; B3
191. 00F9 B4 ORA H ; B4
192. 00FA B5 ORA L ; B5
193. 00FB B6 ORA M ; B6
194. 00FC F656 ORI Data8 ; F656
195. 00FE E9 PCHL ; E9
196. 00FF C1 POP B ; C1
197. 0100 D1 POP D ; D1
198. 0101 E1 POP H ; E1
199. 0102 F1 POP PSW ; F1
200. 0103 C5 PUSH B ; C5
201. 0104 D5 PUSH D ; D5
202. 0105 E5 PUSH H ; E5
203. 0106 F5 PUSH PSW ; F5
204. 0107 17 RAL ; 17
205. 0108 1F RAR ; 1F
206. 0109 D8 RC ; D8
207. 010A C9 RET ; C9
208. 010B 07 RLC ; 07
209. 010C F8 RM ; F8
210. 010D D0 RNC ; D0
211. 010E C0 RNZ ; C0
212. 010F F0 RP ; F0
213. 0110 E8 RPE ; E8
214. 0111 E0 RPO ; E0
215. 0112 0F RRC ; 0F
216. 0113 C7 RST 0 ; C7
217. 0114 CF RST 1 ; CF
218. 0115 D7 RST 2 ; D7
219. 0116 DF RST 3 ; DF
220. 0117 E7 RST 4 ; E7
221. 0118 EF RST 5 ; EF
222. 0119 F7 RST 6 ; F7
223. 011A FF RST 7 ; FF
224. 011B C8 RZ ; C8
225. 011C 9F SBB A ; 9F
226. 011D 98 SBB B ; 98
227. 011E 99 SBB C ; 99
228. 011F 9A SBB D ; 9A
229. 0120 9B SBB E ; 9B
230. 0121 9C SBB H ; 9C
231. 0122 9D SBB L ; 9D
232. 0123 9E SBB M ; 9E
233. 0124 DE56 SBI Data8 ; DE56
234. 0126 223412 SHLD Data16 ; 223412
235. 0129 F9 SPHL ; F9
236. 012A 323412 STA Data16 ; 323412
237. 012D 02 STAX B ; 02
238. 012E 12 STAX D ; 12
239. 012F 37 STC ; 37
240. 0130 97 SUB A ; 97
241. 0131 90 SUB B ; 90
242. 0132 91 SUB C ; 91
243. 0133 92 SUB D ; 92
244. 0134 93 SUB E ; 93
245. 0135 94 SUB H ; 94
246. 0136 95 SUB L ; 95
247. 0137 96 SUB M ; 96
248. 0138 D656 SUI Data8 ; D656
249. 013A EB XCHG ; EB
250. 013B AF XRA A ; AF
251. 013C A8 XRA B ; A8
252. 013D A9 XRA C ; A9
253. 013E AA XRA D ; AA
254. 013F AB XRA E ; AB
255. 0140 AC XRA H ; AC
256. 0141 AD XRA L ; AD
257. 0142 AE XRA M ; AE
258. 0143 EE56 XRI Data8 ; EE56
259. 0145 E3 XTHL ; E3
260. 0146 20 RIM ; 20
261. 0147 30 SIM ; 30
262. 0148 10 ARHL ; 10
263. 0149 08 DSUB ; 08
264. 014A DD3412 JNUI Data16 ; DD3412
265. 014D FD3412 JUI Data16 ; FD3412
266. 0150 2856 LDHI Data8 ; 2856
267. 0152 3856 LDSI Data8 ; 3856
268. 0154 ED LHLX ; ED
269. 0155 18 RDEL ; 18
270. 0156 CB RSTV ; CB
271. 0157 D9 SHLX ; D9
272. .end
Close file: D:\microgeek\asm8080\T8085.ASM
Compilation :successful
Map information about constants and labels:
Data16 CONST=1234 hex [0001001000110100 bin,4660 dec]
Data8 CONST=0056 hex [0000000001010110 bin,86 dec]
Hello LABEL:0000 hex
Code stored in file: D:\microgeek\asm8080\T8085.hex
Poprawiony kompiler (opisany <tutaj>):
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: I8085 - emulator procesora
Dzięki za ten temat. Oderwałem się na chwilę od moich zabawek.
Jednak jest coś, co mnie męczy: czy jest ktoś, kto miał przyjemność używać CA85?
Pobawiłbym się...
Jednak jest coś, co mnie męczy: czy jest ktoś, kto miał przyjemność używać CA85?
Pobawiłbym się...
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
"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: I8085 - emulator procesora
O kurcze... SA80
SA80, miałem okazję tego dotknąć na studiach. Nawet czas by się zgadzał, pierwsza połowa lat 80-tych. Znajomy naukowiec robił badania (a przy okazji doktorat) na politechnice. Tak jakoś wyszło, że mu pomagałem troszkę. Robił jakieś pomiary, były przetworniki AC. Bosze, myśmy na tym próbowali implementować zmienny przecinek... To były szalone czasy, ale z drugiej strony fascynujące.
A tak przy okazji, to był mój poligon za Z80.
SA80, miałem okazję tego dotknąć na studiach. Nawet czas by się zgadzał, pierwsza połowa lat 80-tych. Znajomy naukowiec robił badania (a przy okazji doktorat) na politechnice. Tak jakoś wyszło, że mu pomagałem troszkę. Robił jakieś pomiary, były przetworniki AC. Bosze, myśmy na tym próbowali implementować zmienny przecinek... To były szalone czasy, ale z drugiej strony fascynujące.
A tak przy okazji, to był mój poligon za Z80.
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: I8085 - emulator procesora
Z CA80 miałem kontakt w technikum. Nauczyciel podstaw automatyki był kolegą Stanisława Gardynika. Studiowali razem, a potem spotykali się na "Perskim". Przychodził do szkoły ze swoim SA80, ale był też szkolny egzemplarz (praca dyplomowa sprzed 2-3 lat). Tak mnie zaciekawił, że chciałem mieć swój, więc przywoził mi z Warszawy części po kilka scalaków na miesiąc, aż uzbierał się cały. W tym czasie "szkolny" miałem w domu. Kiedy mój był gotowy, okazało się, że wyświetla "CA80" - była to nowa wersja. Mam go do dzisiaj, ale CA85 mnie ominął.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
"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: I8085 - emulator procesora
No to jesteś stary zawodnik w te klocki
Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse
Re: I8085 - emulator procesora
gaweł pisze:No to jesteś stary zawodnik w te klocki
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
"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: I8085 - emulator procesora
Kolejne rozszerzenia i korekty
W związku z tym, że zostają uwzględnione "nieoficjalne" instrukcje, program emulatora ulega modyfikacji i rozszerzeniu. Z dokumentacji wynika, że dochodzą dwa wskaźniki w rejestrze PSW: V - wskaźnik nadmiaru w operacjach w kodzie U2 oraz UI - wskaźnik nadmiaru dla operacji INX i DCX. Trochę mnie to dziwi i niepokoi, gdyż wskaźnik nadmiaru dotyczy operacji w kodzie U2. Znaczy, że inkrementacja i dekrementacji par rejestrów musi być traktowana jako operacja ze znakiem, jakie to ma zastosowanie?
Dodatkowo zaistnienie instrukcji RSTV (obsługa przerwania w sytuacji wystąpienia nadmiaru V) generuje powstanie kolejnego wektora przerwań z punktem wejścia do obsługi na adresie 40 hex. To z kolei poszerza możliwość konfiguracji projektu o obsługę przerwania od takiego zdarzenia.
W związku z tym, że zostają uwzględnione "nieoficjalne" instrukcje, program emulatora ulega modyfikacji i rozszerzeniu. Z dokumentacji wynika, że dochodzą dwa wskaźniki w rejestrze PSW: V - wskaźnik nadmiaru w operacjach w kodzie U2 oraz UI - wskaźnik nadmiaru dla operacji INX i DCX. Trochę mnie to dziwi i niepokoi, gdyż wskaźnik nadmiaru dotyczy operacji w kodzie U2. Znaczy, że inkrementacja i dekrementacji par rejestrów musi być traktowana jako operacja ze znakiem, jakie to ma zastosowanie?
Dodatkowo zaistnienie instrukcji RSTV (obsługa przerwania w sytuacji wystąpienia nadmiaru V) generuje powstanie kolejnego wektora przerwań z punktem wejścia do obsługi na adresie 40 hex. To z kolei poszerza możliwość konfiguracji projektu o obsługę przerwania od takiego zdarzenia.
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: I8085 - emulator procesora
Konfiguracja
Po uruchomieniu programu emulatora, mamy możliwość otwarcia istniejącego projektu lub utworzenie nowego. Po kliknięciu na „Nowy proj.” program poprosi o wszystkie niezbędne informacje. Należą do nich:
Przycisk „Konf. Przerw.” służy do określenia przerwań, jakie są obsługiwane w programie. Wśród znanych dotychczas przerwań pojawia się nowe. Program został rozbudowany o kolejną pozycję: przerwania od nadmiaru arytmetycznego: RSTV.
Wszystkie wprowadzone dane środowiskowe są wyświetlone w okienku:
Można je zapisać do pliku i posiłkować się tym plikiem na przyszłość.
Teraz pozostało załadować kod programu (znana pliku jest już znana). Przy tej operacji sprawdzana jest zgodność wklepanych danych z załadowanym kodem. Głównie chodzi tu o obsługę przerwań, gdzie każde z nich ma swój indywidualny adres obsługi – w ładowanym kodzie na adresach specyfikowanych przerwań musi wystąpić kod programu.
Oczywiście program nie jest w stanie sprawdzić na tym etapie, czy rzeczywiście jest to kod obsługi przerwań. Program emulatora jest jedynie narzędziem wsparcia i nie zwalnia „od myślenia” użytkownika.
Przykładowa postać źródłowa programu intelowego jest następująca:Emulator „zauważył”, że w kodzie binarnym programu w lokacji adresowej przewidzianej do obsługi przerwania coś jest.
Po uruchomieniu programu emulatora, mamy możliwość otwarcia istniejącego projektu lub utworzenie nowego. Po kliknięciu na „Nowy proj.” program poprosi o wszystkie niezbędne informacje. Należą do nich:
- nazwa projektu:
- nazwa pliku z kodem binarnym programu:
- określenie przestrzeni adresowej pamięci ROM (na program) – od .. do
- określenie przestrzeni adresowej pamięci RAM – od .. do
Przycisk „Konf. Przerw.” służy do określenia przerwań, jakie są obsługiwane w programie. Wśród znanych dotychczas przerwań pojawia się nowe. Program został rozbudowany o kolejną pozycję: przerwania od nadmiaru arytmetycznego: RSTV.
Wszystkie wprowadzone dane środowiskowe są wyświetlone w okienku:
Można je zapisać do pliku i posiłkować się tym plikiem na przyszłość.
Teraz pozostało załadować kod programu (znana pliku jest już znana). Przy tej operacji sprawdzana jest zgodność wklepanych danych z załadowanym kodem. Głównie chodzi tu o obsługę przerwań, gdzie każde z nich ma swój indywidualny adres obsługi – w ładowanym kodzie na adresach specyfikowanych przerwań musi wystąpić kod programu.
Oczywiście program nie jest w stanie sprawdzić na tym etapie, czy rzeczywiście jest to kod obsługi przerwań. Program emulatora jest jedynie narzędziem wsparcia i nie zwalnia „od myślenia” użytkownika.
Przykładowa postać źródłowa programu intelowego jest następująca:Emulator „zauważył”, że w kodzie binarnym programu w lokacji adresowej przewidzianej do obsługi przerwania coś jest.
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: I8085 - emulator procesora
Emulacja programu
Program ciągle się rozwija i ulega zmianom. Jednocześnie przechodzi testy. Ponieważ pewne działania wymagają określonej kolejności (w sensie klikania na przyciski, gdyż przykładowo trudno kliknąć na „wykonaj krok” jeżeli nie jest załadowany program), to jego działanie zostało rozbudowane o funkcjonalność „wskazującą na możliwy kolejny krok”. Obecnie po uruchomieniu programu mamy dostępne przyciski pozwalające na utworzenie lub otwarcie pliku projektu. Istnieje również możliwość upuszczenia nazwy pliku projektu na formę programu, co jest równoznaczne z otwarciem tego konkretnego pliku.
Jako przykład będę posługiwał się następującym plikiem źródłowym (który należy skompilować by uzyskać program binarny). Zawiera on obsługą przerwań sprzętowych i jakiś tam zestaw instrukcji (które właściwie nie tworzą jakiegoś sensownego programu, na to przyjdzie czas później).
Po otwarciu pliku projektu istnieje możliwość jego modyfikacji lub załadowania kodu programu binarnego.
Oczywiście zmienia się zestaw dostępnych operacji. Jeżeli projekt nie jest modyfikowany można załadować program binarny klikając na „Ładuj hex” (jego nazwa jest już wpisana z plik projektu). Jeżeli w trakcie symulacji zostaną dostrzeżone własne błędy, to można zmodyfikować program źródłowy (ten dla intela), skompilować i ponownie kliknąć na „Ładuj hex” (nie ma konieczności zamykania programu emulatora lub ponownego otwierania projektu). Po załadowaniu kodu, program jest deasemblowany i jest postać jest pokazana w okienku.
W tym przykładzie wszystkie skoki i wywołania są „jawne”, więc nie ma „potencjalnych” martwych kodów. Po kliknięciu na „Krok” lub „Uruchom” program staruje i nie ma już możliwości „grzebania” w konfiguracji projektu. By wrócić do tej możliwości program należy zatrzymać klikając na „Zatrzymaj” (to nic, że program „stoi”, gdyż został puszczony krokowy, ale jest w kontekście <uruchomiony>, więc będzie wymagał zatrzymania, by stały się dostępne pewne jego funkcje). Załadowanie wskaźnika stosu powoduje, że zostaje wyświetlony stos – zawartość pamięci wskazana przez rejestr SP. Stos jest pokazany oczywiście „od tyłu” i widać tu dosyć przypadkowe wartości. Funkcją programu jest wypełnienie wszystkich pamięci RAM losową zawartością po każdym kliknięciu na „Reset”. Załadowanie kodu programu (Ładuj hex) również jest połączone z automatycznym resetem.
Wykonanie instrukcji EI DI (odblokowanie przerwań), sygnalizuje możliwość przyjęcia klasycznych (w sensie procka i8080) przerwań sprzętowych.
Kliknięcie na przerwanie niemaskowalne (TRAP) powoduje skod do jego obsługi, która zatrzymuje program w ciasnej pętli (skok do samego siebie).
Fajnie jest wiedzieć, co i gdzie zaszło? Co to wiadomo: TRAP, ale gdzie? Po kliknięciu prawym klawiszem z powstałego menu wybieramy „Kolejka wywołań”.
Wyświetlona jest istniejąca kolejka wywołań: normalnych wywołań oraz obsługi przerwań.
Pokazany tekst można sobie zapisać do pliku, co może być pomocne przy analizie programu. Ponieważ program został zatrzymany w obsłudze przerwań, to pozostaje jedynie przycisk „Reset” i wszystko wraca na początek.
Załadowanie czegokolwiek z pamięci do jakiegokolwiek rejestru pokazuje docelowe lub źródłowe miejsce w pamięci w okienku danych. To wyświetlenie jest takim krokiem w „przyszłość”, stan pokazanego obszaru danych jest jeszcze przed wykonaniem instrukcji. Poniżej LHLD z podanym adresem 1AB hex pokazuje, że do pary HL zostanie wpisane 1234 hex (starsza część jest na starszym adresie).
Przed kolejną instrukcją SHLD w okienku danych pokazana jest zawartość pamięci jeszcze przed wykonaniem instrukcji, która jest losowa (bo to pamięć RAM wypełniona losowo w wyniku akcji reset).
Ponieważ kolejna instrukcja ładuje do HL stałą i program próbuje pokazać, gdzie to wskazuje, to nie widać skutku operacji zapisu.
Możliwym wyjściem jest kliknięcie prawym klawiszem i z powstałego menu wybrać:
am był adres 8002 hex, więc taki zostaje wpisany.
Wcześniej było C994 hex, teraz tam jest 1234 hex.
By wrócić, wystarczy kliknąć na pole HL.
Identycznie kliknięcie na DE lub BC również pokazuje w okienku pamięć adresowaną przez odpowiednie pary rejestrów. Również programowe załadowanie czegokolwiek do tych par rejestrów daje w reakcji wyświetlenie danych zawartych w przestrzeni adresowej.
Program ciągle się rozwija i ulega zmianom. Jednocześnie przechodzi testy. Ponieważ pewne działania wymagają określonej kolejności (w sensie klikania na przyciski, gdyż przykładowo trudno kliknąć na „wykonaj krok” jeżeli nie jest załadowany program), to jego działanie zostało rozbudowane o funkcjonalność „wskazującą na możliwy kolejny krok”. Obecnie po uruchomieniu programu mamy dostępne przyciski pozwalające na utworzenie lub otwarcie pliku projektu. Istnieje również możliwość upuszczenia nazwy pliku projektu na formę programu, co jest równoznaczne z otwarciem tego konkretnego pliku.
Jako przykład będę posługiwał się następującym plikiem źródłowym (który należy skompilować by uzyskać program binarny). Zawiera on obsługą przerwań sprzętowych i jakiś tam zestaw instrukcji (które właściwie nie tworzą jakiegoś sensownego programu, na to przyjdzie czas później).
Kod: Zaznacz cały
;
; ***************************************************
; * *
; * zbior instrukcji mikroprocesora 8080 *
; * *
; ***************************************************
;
; .i8080
.i8085
ResetEntry .equ 0000h
RST1Entry .equ 0008h
RST2Entry .equ 0010h
RST3Entry .equ 0018h
RST4Entry .equ 0020h
TRAPEntry .equ 0024h
RST5Entry .equ 0028h
RST55Entry .equ 002Ch
RST6Entry .equ 0030h
RST65Entry .equ 0034h
RST7Entry .equ 0038h
RST75Entry .equ 003Ch
;
Data8 .equ 56h
.org ResetEntry
di
lxi sp,0
jmp StartProg
.org RST1Entry
jmp RST1Service
.org RST2Entry
jmp RST2Service
.org RST3Entry
jmp RST3Service
.org RST4Entry
jmp RST4Service
.org TRAPEntry
jmp TRAPService
.org RST5Entry
jmp RST5Service
.org RST55Entry
jmp RST55Service
.org RST6Entry
jmp RST6Service
.org RST65Entry
jmp RST65Service
.org RST7Entry
jmp RST7Service
.org RST75Entry
jmp RST75Service
RST1Service
nop
nop
ei
ret
RST2Service
nop
nop
ei
ret
RST3Service
nop
nop
ei
ret
RST4Service
nop
nop
ei
ret
TRAPService
jmp TRAPService
ret
RST5Service
nop
nop
ei
ret
RST55Service
nop
nop
ei
ret
RST6Service
nop
nop
ei
ret
RST65Service
nop
nop
ei
ret
RST7Service
nop
nop
ei
ret
RST75Service
nop
nop
mvi a,10h
sim
ei
ret
StartProg
di
ei
loop
call subr
jmp loop
subr
di
ei
in 123
in 0
in 1
in 2
in 3
in 038h
out 123
out 0
out 1
out 2
out 3
out 1Ah
lhld lhldop
shld shldop
lxi h,5aa5h
xthl
xthl
lxi h,089abh ;
rim
mvi a,08h
sim
rim
mov a,m
inx h
mov b,m
inx h
mov c,m
inx h
mov d,m
inx h
mov e,m
xchg
ACI Data8 ; CE56
ADC A ; 8F
ADC B ; 88
ADC C ; 89
ADC D ; 8A
ADC E ; 8B
ADC H ; 8C
ADC L ; 8D
xchg
ADC M ; 8E
ADD A ; 87
ADD B ; 80
ADD C ; 81
ADD D ; 82
ADD E ; 83
ADD H ; 84
ADD L ; 85
ADD M ; 86
ADI Data8 ; C656
ANA A ; A7
ANA B ; A0
ANA C ; A1
ANA D ; A2
ANA E ; A3
ANA H ; A4
ANA L ; A5
ANA M ; A6
ANI Data8 ; E656
CMA ; 2F
CMC ; 3F
CMP A ; BF
CMP B ; B8
CMP C ; B9
CMP D ; BA
CMP E ; BB
CMP H ; BC
CMP L ; BD
CMP M ; BE
DAA ; 27
DAD B ; 09
DAD D ; 19
DAD H ; 29
DAD SP ; 39
DCR A ; 3D
DCR B ; 05
DCR C ; 0D
DCR D ; 15
DCR E ; 1D
DCR H ; 25
DCR L ; 2D
DCX B ; 0B
DCX D ; 1B
DCX H ; 2B
DCX SP ; 3B
DI ; F3
EI ; FB
IN Data8 ; DB56
OUT Data8 ; D356
INR A ; 3C
INR B ; 04
INR C ; 0C
INR D ; 14
INR E ; 1C
INR H ; 24
INR L ; 2C
INX B ; 03
INX D ; 13
INX H ; 23
INX SP ; 33
LDA Data16 ; 3A3412
LDAX B ; 0A
LDAX D ; 1A
LHLD Data16 ; 2A3412
LXI B,Data16 ; 013412
LXI D,Data16 ; 113412
LXI H,Data16 ; 213412
MOV A,A ; 7F
MOV A,B ; 78
MOV A,C ; 79
MOV A,D ; 7A
MOV A,E ; 7B
MOV A,H ; 7C
MOV A,L ; 7D
MOV A,M ; 7E
MOV B,A ; 47
MOV B,B ; 40
MOV B,C ; 41
MOV B,D ; 42
MOV B,E ; 43
MOV B,H ; 44
MOV B,L ; 45
MOV B,M ; 46
MOV C,A ; 4F
MOV C,B ; 48
MOV C,C ; 49
MOV C,D ; 4A
MOV C,E ; 4B
MOV C,H ; 4C
MOV C,L ; 4D
MOV C,M ; 4E
MOV D,A ; 57
MOV D,B ; 50
MOV D,C ; 51
MOV D,D ; 52
MOV D,E ; 53
MOV D,H ; 54
MOV D,L ; 55
MOV D,M ; 56
MOV E,A ; 5F
MOV E,B ; 58
MOV E,C ; 59
MOV E,D ; 5A
MOV E,E ; 5B
MOV E,H ; 5C
MOV E,L ; 5D
MOV E,M ; 5E
MOV H,A ; 67
MOV H,B ; 60
MOV H,C ; 61
MOV H,D ; 62
MOV H,E ; 63
MOV H,H ; 64
MOV H,L ; 65
MOV H,M ; 66
MOV L,A ; 6F
MOV L,B ; 68
MOV L,C ; 69
MOV L,D ; 6A
MOV L,E ; 6B
MOV L,H ; 6C
MOV L,L ; 6D
MOV L,M ; 6E
MOV M,A ; 77
MOV M,B ; 70
MOV M,C ; 71
MOV M,D ; 72
MOV M,E ; 73
MOV M,H ; 74
MOV M,L ; 75
MVI A,Data8 ; 3E56
MVI B,Data8 ; 0656
MVI C,Data8 ; 0E56
MVI D,Data8 ; 1656
MVI E,Data8 ; 1E56
MVI H,Data8 ; 2656
MVI L,Data8 ; 2E56
MVI M,Data8 ; 3656
NOP ; 00
ORA A ; B7
ORA B ; B0
ORA C ; B1
ORA D ; B2
ORA E ; B3
ORA H ; B4
ORA L ; B5
ORA M ; B6
ORI Data8 ; F656
PUSH B ; C5
PUSH D ; D5
PUSH H ; E5
PUSH PSW ; F5
POP PSW ; F1
POP H ; C1
POP D ; D1
POP B ; E1
RAL ; 17
RAR ; 1F
RC ; D8
RLC ; 07
RM ; F8
RNC ; D0
RNZ ; C0
RP ; F0
RPE ; E8
RPO ; E0
RRC ; 0F
RST 0 ; C7
RST 1 ; CF
RST 2 ; D7
RST 3 ; DF
RST 4 ; E7
RST 5 ; EF
RST 6 ; F7
RST 7 ; FF
RZ ; C8
SBB A ; 9F
SBB B ; 98
SBB C ; 99
SBB D ; 9A
SBB E ; 9B
SBB H ; 9C
SBB L ; 9D
SBB M ; 9E
SBI Data8 ; DE56
SHLD Data16 ; 223412
SPHL ; F9
STA Data16 ; 323412
STAX B ; 02
STAX D ; 12
STC ; 37
SUB A ; 97
SUB B ; 90
SUB C ; 91
SUB D ; 92
SUB E ; 93
SUB H ; 94
SUB L ; 95
SUB M ; 96
SUI Data8 ; D656
XCHG ; EB
XRA A ; AF
XRA B ; A8
XRA C ; A9
XRA D ; AA
XRA E ; AB
XRA H ; AC
XRA L ; AD
XRA M ; AE
XRI Data8 ; EE56
XTHL ; E3
RIM ; 20
SIM ; 30
RET ; C9
lhldop .defw 1234h
.org 08000h
Data16 .word
shldop .word
.end
Po otwarciu pliku projektu istnieje możliwość jego modyfikacji lub załadowania kodu programu binarnego.
Oczywiście zmienia się zestaw dostępnych operacji. Jeżeli projekt nie jest modyfikowany można załadować program binarny klikając na „Ładuj hex” (jego nazwa jest już wpisana z plik projektu). Jeżeli w trakcie symulacji zostaną dostrzeżone własne błędy, to można zmodyfikować program źródłowy (ten dla intela), skompilować i ponownie kliknąć na „Ładuj hex” (nie ma konieczności zamykania programu emulatora lub ponownego otwierania projektu). Po załadowaniu kodu, program jest deasemblowany i jest postać jest pokazana w okienku.
W tym przykładzie wszystkie skoki i wywołania są „jawne”, więc nie ma „potencjalnych” martwych kodów. Po kliknięciu na „Krok” lub „Uruchom” program staruje i nie ma już możliwości „grzebania” w konfiguracji projektu. By wrócić do tej możliwości program należy zatrzymać klikając na „Zatrzymaj” (to nic, że program „stoi”, gdyż został puszczony krokowy, ale jest w kontekście <uruchomiony>, więc będzie wymagał zatrzymania, by stały się dostępne pewne jego funkcje). Załadowanie wskaźnika stosu powoduje, że zostaje wyświetlony stos – zawartość pamięci wskazana przez rejestr SP. Stos jest pokazany oczywiście „od tyłu” i widać tu dosyć przypadkowe wartości. Funkcją programu jest wypełnienie wszystkich pamięci RAM losową zawartością po każdym kliknięciu na „Reset”. Załadowanie kodu programu (Ładuj hex) również jest połączone z automatycznym resetem.
Wykonanie instrukcji EI DI (odblokowanie przerwań), sygnalizuje możliwość przyjęcia klasycznych (w sensie procka i8080) przerwań sprzętowych.
Kliknięcie na przerwanie niemaskowalne (TRAP) powoduje skod do jego obsługi, która zatrzymuje program w ciasnej pętli (skok do samego siebie).
Fajnie jest wiedzieć, co i gdzie zaszło? Co to wiadomo: TRAP, ale gdzie? Po kliknięciu prawym klawiszem z powstałego menu wybieramy „Kolejka wywołań”.
Wyświetlona jest istniejąca kolejka wywołań: normalnych wywołań oraz obsługi przerwań.
Pokazany tekst można sobie zapisać do pliku, co może być pomocne przy analizie programu. Ponieważ program został zatrzymany w obsłudze przerwań, to pozostaje jedynie przycisk „Reset” i wszystko wraca na początek.
Załadowanie czegokolwiek z pamięci do jakiegokolwiek rejestru pokazuje docelowe lub źródłowe miejsce w pamięci w okienku danych. To wyświetlenie jest takim krokiem w „przyszłość”, stan pokazanego obszaru danych jest jeszcze przed wykonaniem instrukcji. Poniżej LHLD z podanym adresem 1AB hex pokazuje, że do pary HL zostanie wpisane 1234 hex (starsza część jest na starszym adresie).
Przed kolejną instrukcją SHLD w okienku danych pokazana jest zawartość pamięci jeszcze przed wykonaniem instrukcji, która jest losowa (bo to pamięć RAM wypełniona losowo w wyniku akcji reset).
Ponieważ kolejna instrukcja ładuje do HL stałą i program próbuje pokazać, gdzie to wskazuje, to nie widać skutku operacji zapisu.
Możliwym wyjściem jest kliknięcie prawym klawiszem i z powstałego menu wybrać:
am był adres 8002 hex, więc taki zostaje wpisany.
Wcześniej było C994 hex, teraz tam jest 1234 hex.
By wrócić, wystarczy kliknąć na pole HL.
Identycznie kliknięcie na DE lub BC również pokazuje w okienku pamięć adresowaną przez odpowiednie pary rejestrów. Również programowe załadowanie czegokolwiek do tych par rejestrów daje w reakcji wyświetlenie danych zawartych w przestrzeni adresowej.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Ostatnio zmieniony czwartek 25 kwie 2024, 20:18 przez gaweł, łącznie zmieniany 1 raz.
Prawdziwe słowa nie są przyjemne. Przyjemne słowa nie są prawdziwe.
Lao Tse
Re: I8085 - emulator procesora
Modyfikacja stanów rejestrów
Po załadowaniu kodu programu do pamięci emulatora (po wcześniejszym otwarciu projektu), program można puścić na żywioł. Istotną funkcją emulatora jest „pilnowanie” by wszystko szło właściwie oraz zgłaszanie „nadużyć”.
Przykładowo, zaistniało naruszenie przestrzeni pamięci ROM, gdyż zapis czegokolwiek w ten obszar jest niedopuszczalny.
Wykonanie programu zostało zatrzymane z odpowiednim komunikatem. Problem wygenerowała instrukcja DCR M, której zadaniem jest dekrementacja bajtu pamięci o adresie wskazanym zawartością pary rejestrów HL. Wskazuje on na obszar pamięci ROM. Odczyt z tego obszaru jest możliwy, jednak zapis tam technicznie nie jest możliwy.
Podobna sytuacja wystąpiła nieco później. Przed instrukcją MVI M,…. została załadowana para rejestrów HL, ale w wyniku „własnej pomyłki” to nie jest właściwa wartość w tej parze rejestrów.
Możliwe jest dokonanie modyfikacji bez potrzeby edycji programu źródłowego i jego kompilacji (no chyba, że będzie to zachodzić wielokrotnie, to wtedy jest to bardziej uzasadnione). Można dokonać korekty każdego pokazanego niżej rejestru:
Operacja zmiany zawartości rejestrów jest możliwa w sytuacji zatrzymanego programu lub gdy program jest puszczany krokowo. Należy kliknąć na wybrany rejestr i wprowadzić szesnastkowo nową wartość. Zmiany par rejestrów są realizowane przez dwie zmiany zawartości pojedynczych rejestrów (starsza część jest z lewej strony, młodsza z prawej strony). Zmiana rejestru BC, DE, HL jednocześnie wyświetla zawartość pamięci danych wskazaną przez modyfikację rejestrów składowych. Również możliwa jest zmiana zawartości wskaźnika stosu, jednak tu trzeba zachować czujność, bo może to doprowadzić, że program się zgubi (po przykładowo wykonaniu instrukcji RET). Pewnym ograniczeniom podlega modyfikacja rejestru PC. Istnieją instrukcje jednobajtowe, dwubajtowe oraz składające się z trzech bajtów. Wymagane jest by trafić zawsze na pierwszy bajt instrukcji (po deasemblacji wiadomo, gdzie zaczyna się każda instrukcja). W tym miejscu program nie da sobie zrobić krzywdy.
Wpisanie przykładowo do PC wartości 13C wskazuje na drugi bajt instrukcji LXI (czyli operand tej instrukcji).
Po załadowaniu kodu programu do pamięci emulatora (po wcześniejszym otwarciu projektu), program można puścić na żywioł. Istotną funkcją emulatora jest „pilnowanie” by wszystko szło właściwie oraz zgłaszanie „nadużyć”.
Przykładowo, zaistniało naruszenie przestrzeni pamięci ROM, gdyż zapis czegokolwiek w ten obszar jest niedopuszczalny.
Wykonanie programu zostało zatrzymane z odpowiednim komunikatem. Problem wygenerowała instrukcja DCR M, której zadaniem jest dekrementacja bajtu pamięci o adresie wskazanym zawartością pary rejestrów HL. Wskazuje on na obszar pamięci ROM. Odczyt z tego obszaru jest możliwy, jednak zapis tam technicznie nie jest możliwy.
Podobna sytuacja wystąpiła nieco później. Przed instrukcją MVI M,…. została załadowana para rejestrów HL, ale w wyniku „własnej pomyłki” to nie jest właściwa wartość w tej parze rejestrów.
Możliwe jest dokonanie modyfikacji bez potrzeby edycji programu źródłowego i jego kompilacji (no chyba, że będzie to zachodzić wielokrotnie, to wtedy jest to bardziej uzasadnione). Można dokonać korekty każdego pokazanego niżej rejestru:
Operacja zmiany zawartości rejestrów jest możliwa w sytuacji zatrzymanego programu lub gdy program jest puszczany krokowo. Należy kliknąć na wybrany rejestr i wprowadzić szesnastkowo nową wartość. Zmiany par rejestrów są realizowane przez dwie zmiany zawartości pojedynczych rejestrów (starsza część jest z lewej strony, młodsza z prawej strony). Zmiana rejestru BC, DE, HL jednocześnie wyświetla zawartość pamięci danych wskazaną przez modyfikację rejestrów składowych. Również możliwa jest zmiana zawartości wskaźnika stosu, jednak tu trzeba zachować czujność, bo może to doprowadzić, że program się zgubi (po przykładowo wykonaniu instrukcji RET). Pewnym ograniczeniom podlega modyfikacja rejestru PC. Istnieją instrukcje jednobajtowe, dwubajtowe oraz składające się z trzech bajtów. Wymagane jest by trafić zawsze na pierwszy bajt instrukcji (po deasemblacji wiadomo, gdzie zaczyna się każda instrukcja). W tym miejscu program nie da sobie zrobić krzywdy.
Wpisanie przykładowo do PC wartości 13C wskazuje na drugi bajt instrukcji LXI (czyli operand tej instrukcji).
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: I8085 - emulator procesora
Break point’y w programie
W emulatorze nie może zabraknąć funkcji związanych z pułapkami zwanymi break pointy. By to uzyskać to należy mieć załadowany program (ten w intelu).
W okienku z programem „przewinąć się” do punktu, w którym wykonanie programu ma zostać wstrzymane i zrobić tam dwuklik. Miejsce to zostaje oznaczone gwiazdką. Ponowny dwuklik w tym miejscu zdejmuje z tej instrukcji pułapkę. Jeżeli wskazana instrukcja nie była oznaczona flagą pułapki, to zostanie ona ustawiona, jeżeli była oznaczona flagą pułapki, to zostaje zdjęta. Pułapek można w programie ustawić dowolną ilość. Efektem operacji pułapkowej jest przestawienie podświetlenia w okienku programu (co nie zmienia wartości zapisanej w rejestrze PC). By wrócić należy użyć prawego klawisza myszki i wybrać opcję „Skocz do miejsca wskazanego przez PC”. I wszystko wraca do normy.
Uruchomienie programu „na żywioł” (przycisk <Uruchom>) zatrzymuje wykonanie programu we wskazanym miejscu (program jest przed wykonaniem instrukcji). By przejść przez ten punkt należy kliknąć przycisk <Krok>.
Przy pracy krokowej wykonanie zawsze przechodzi przez pułapki bez zatrzymania wykonania.
By usunąć pułapki należy kliknąć prawym klawiszem myszki i wybrać <Usuń wszystkie pułapki>.
Jeżeli ktoś ma ochotę poeksperymentować z programem, to … zapraszam.
W emulatorze nie może zabraknąć funkcji związanych z pułapkami zwanymi break pointy. By to uzyskać to należy mieć załadowany program (ten w intelu).
W okienku z programem „przewinąć się” do punktu, w którym wykonanie programu ma zostać wstrzymane i zrobić tam dwuklik. Miejsce to zostaje oznaczone gwiazdką. Ponowny dwuklik w tym miejscu zdejmuje z tej instrukcji pułapkę. Jeżeli wskazana instrukcja nie była oznaczona flagą pułapki, to zostanie ona ustawiona, jeżeli była oznaczona flagą pułapki, to zostaje zdjęta. Pułapek można w programie ustawić dowolną ilość. Efektem operacji pułapkowej jest przestawienie podświetlenia w okienku programu (co nie zmienia wartości zapisanej w rejestrze PC). By wrócić należy użyć prawego klawisza myszki i wybrać opcję „Skocz do miejsca wskazanego przez PC”. I wszystko wraca do normy.
Uruchomienie programu „na żywioł” (przycisk <Uruchom>) zatrzymuje wykonanie programu we wskazanym miejscu (program jest przed wykonaniem instrukcji). By przejść przez ten punkt należy kliknąć przycisk <Krok>.
Przy pracy krokowej wykonanie zawsze przechodzi przez pułapki bez zatrzymania wykonania.
By usunąć pułapki należy kliknąć prawym klawiszem myszki i wybrać <Usuń wszystkie pułapki>.
Jeżeli ktoś ma ochotę poeksperymentować z programem, to … zapraszam.
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: I8085 - emulator procesora
Obsługa przerwań w emulatorze
Emulator procka realizuje obsługę przerwań opartą o prosty (ale skuteczny) kontroler i8214. Jego zadaniem (w kooperacji w parze z i8212) jest wypracowanie odpowiedniej instrukcji, która jest zgłaszana w chwili akceptacji przyjęcia przerwania przez procka. Schemat takiego rozwiązania jest następujący:
Akceptacja przez procka przerwania prowadzi do wystawienia na szynie danych jednej z możliwych instrukcji RST n (no może z wyjątkiem RST 0, bo to będzie tożsame z resetem).
I dokładnie taka filozofia działania jest zawarta w emulatorze. Kliknięcie na jeden z przycisków zgłoszenia przerwania generuje sygnał do kontrolera.
Jeżeli jest zezwolenie na obsługę przerwań, to ta obsługa sprowadza się do „zasymulowania” wykonania odpowiedniego wariantu instrukcji RST n (dokładnie jak na schemacie wyżej). Także przycisk RST1 generuje instrukcję RST 1, i tak dalej aż do przycisku RST7,który generuje instrukcję RST 7. Obsługa przerwań połówkowych jest zrealizowana trochę odmiennie: na stos wędruje bieżąca zawartość rejestru PC i następuje wpisanie do rejestru PC odpowiedniego adresu wynikającego z obsługiwanego przerwania. Każde przerwanie RST1 .. RST7 oraz połówkowe (z wyjątkiem RST 7.5) gasi „lampkę” sygnalizującą zgłoszenie przerwania na przycisku), RST 7.5 wymaga potwierdzenia (odpowiednie zaklęcie w instrukcji SIM). Za każdym razem również emulator sam z siebie blokuje przyjęcie kolejnych przerwań (robi DI).
Symulacja bardziej rozbudowanego układu obsługi przerwań i8259 nie jest zrealizowana.
Obsługa przerwania niemaskowalnego TRAP (w nomenklaturze Ziloga: NMI) przebiega podobnie do przerwań połówkowych. Na stos wędruje stan rejestru PC i następnie do jego wpisywany jest odpowiednia adres związany z obsługą tego przerwania.
Emulator procka realizuje obsługę przerwań opartą o prosty (ale skuteczny) kontroler i8214. Jego zadaniem (w kooperacji w parze z i8212) jest wypracowanie odpowiedniej instrukcji, która jest zgłaszana w chwili akceptacji przyjęcia przerwania przez procka. Schemat takiego rozwiązania jest następujący:
Akceptacja przez procka przerwania prowadzi do wystawienia na szynie danych jednej z możliwych instrukcji RST n (no może z wyjątkiem RST 0, bo to będzie tożsame z resetem).
I dokładnie taka filozofia działania jest zawarta w emulatorze. Kliknięcie na jeden z przycisków zgłoszenia przerwania generuje sygnał do kontrolera.
Jeżeli jest zezwolenie na obsługę przerwań, to ta obsługa sprowadza się do „zasymulowania” wykonania odpowiedniego wariantu instrukcji RST n (dokładnie jak na schemacie wyżej). Także przycisk RST1 generuje instrukcję RST 1, i tak dalej aż do przycisku RST7,który generuje instrukcję RST 7. Obsługa przerwań połówkowych jest zrealizowana trochę odmiennie: na stos wędruje bieżąca zawartość rejestru PC i następuje wpisanie do rejestru PC odpowiedniego adresu wynikającego z obsługiwanego przerwania. Każde przerwanie RST1 .. RST7 oraz połówkowe (z wyjątkiem RST 7.5) gasi „lampkę” sygnalizującą zgłoszenie przerwania na przycisku), RST 7.5 wymaga potwierdzenia (odpowiednie zaklęcie w instrukcji SIM). Za każdym razem również emulator sam z siebie blokuje przyjęcie kolejnych przerwań (robi DI).
Symulacja bardziej rozbudowanego układu obsługi przerwań i8259 nie jest zrealizowana.
Obsługa przerwania niemaskowalnego TRAP (w nomenklaturze Ziloga: NMI) przebiega podobnie do przerwań połówkowych. Na stos wędruje stan rejestru PC i następnie do jego wpisywany jest odpowiednia adres związany z obsługą tego przerwania.
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: I8085 - emulator procesora
Operacje na portach
Używając emulatora, wyszło mi, że warto go trochę poprawić. Otóż, operacje na portach są sygnalizowane komunikatem w okienku, gdzie należy kliknąć <OK>. Na dłuższą metę to trochę nużące, więc postanowiłem trochę udoskonalić swój program. Na formie doszedł CheckBox określający, czy program ma informować o dokonanej transmisji na port (jak dotychczas), czy nie informować o tym zdarzeniu.
Jeżeli „ptaszek” nie jest zaznaczony, to wszystko jedzie po cichu. Oczywiście istnieje możliwość sprawdzenia, co takiego poszło na porty. W tym celu należy kliknąć prawym klawiszem i wybrać właściwą pozycję:
W reakcji zostają wyświetlone wszystkie dokonane dotychczas operacje na portach, przykładowo:
gdzie jest podany adres portu i co latało na styku do portu. Literka „O” sygnalizuje operację wyjścia, literka „I” dotyczy operacji wejścia. Dalej po znaku ‘:’ jest transmitowana wartość w zapisie szesnastkowym. W przypadku, gdy dane są w zakresie znaków pisarskich (ISO-7), to w nawiasach kwadratowych jest pokazany znak. Istnieje możliwość zapisu tych danych do pliku.
Ulepszona wersja programu jest dostępna tutaj:
Używając emulatora, wyszło mi, że warto go trochę poprawić. Otóż, operacje na portach są sygnalizowane komunikatem w okienku, gdzie należy kliknąć <OK>. Na dłuższą metę to trochę nużące, więc postanowiłem trochę udoskonalić swój program. Na formie doszedł CheckBox określający, czy program ma informować o dokonanej transmisji na port (jak dotychczas), czy nie informować o tym zdarzeniu.
Jeżeli „ptaszek” nie jest zaznaczony, to wszystko jedzie po cichu. Oczywiście istnieje możliwość sprawdzenia, co takiego poszło na porty. W tym celu należy kliknąć prawym klawiszem i wybrać właściwą pozycję:
W reakcji zostają wyświetlone wszystkie dokonane dotychczas operacje na portach, przykładowo:
gdzie jest podany adres portu i co latało na styku do portu. Literka „O” sygnalizuje operację wyjścia, literka „I” dotyczy operacji wejścia. Dalej po znaku ‘:’ jest transmitowana wartość w zapisie szesnastkowym. W przypadku, gdy dane są w zakresie znaków pisarskich (ISO-7), to w nawiasach kwadratowych jest pokazany znak. Istnieje możliwość zapisu tych danych do pliku.
Ulepszona wersja programu jest dostępna tutaj:
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: I8085 - emulator procesora
Na amerykańskim forum "Vintage Computer Federation" odnalazłem dyskusję o nieudokumentowanych instrukcjach 8085 i domniemanych przyczynach nieujawniania ich przez Intela. Prawdopodobnie instrukcje zostały w 8085 zaimplementowane przez inżynierów w celu ułatwienia budowy języków wyższego rzędu (do czego się świetnie nadają - nadal uważam, że są lepszym pomysłem niż zastosowane przez Ziloga rejestry indeksowe), ale były one w konflikcie do nowo powstającego 8086, który nie posiadał podobnych instrukcji co powodowałoby problemy z automatycznym przenoszeniem kodu 8085 do 8086. Po premierze 8086 w powszechnym użyciu była translacja 8080->8086, by zapewnić sobie z marszu bibliotekę oprogramowania na nową architekturę. W załączniku inny, niż dokumentacja Tundra, który opisuje te nowe i zarazem tajne instrukcje.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Re: I8085 - emulator procesora
Wskaźnik przepełnienia
w operacjach dodawania
Kwestia wskaźnika nadmiaru w operacjach w kodzie U2 okazała się troszkę złożona. Postanowiłem sprawdzić wynalezioną w necie formułę i w tym celu napisałem drobny program w C na PC-ta. Ponieważ program jest „jednorazowego użytku” nie dbałem o zbytnią finezję.
Początkowo robiłem wydruk każdej operacji, ale wyszło tego takie mnóstwo, że postanowiłem drukować do pliku jedynie te przypadki, które generują nadmiar w operacjach dodawania.
Pomimo tego, wyszło również całkiem sporo (fragment):
Jak popatrzeć na to wszystko, to czasami wyniki rzeczywiście są dziwaczne.
Formuła na wskaźnik V to:
Sprawdziłem odpowiednio dużo przypadków wydrukowanych przez program. Sprawdziło się. Przykładowo: 7 dec + 127 dec = 134 dec, ale 134 dec = 86 hex.
Dla 8-bitów w U2 to będzie -122 dec → wynik rachunków jest poprawny (poprawny w sensie operacji na bitach, ale zostaje ustawiona flaga nadmiaru V, więc sumarycznie jest do ….).
Niestety dla operacji odejmowania się nie sprawdza, ale mam już podejrzenia, jak powinna ona wyglądać.
w operacjach dodawania
Kwestia wskaźnika nadmiaru w operacjach w kodzie U2 okazała się troszkę złożona. Postanowiłem sprawdzić wynalezioną w necie formułę i w tym celu napisałem drobny program w C na PC-ta. Ponieważ program jest „jednorazowego użytku” nie dbałem o zbytnią finezję.
Kod: Zaznacz cały
#include <stdio.h>
#include <stdlib.h>
static FILE * OutFile ;
static unsigned char Conv ( unsigned short Arg )
{
signed short ArgSig ;
char Str [ 10 ] ;
ArgSig = Arg & 0xFF ;
if ( Arg & 0x80 )
{
ArgSig |= 0xFF00 ;
} /* if */ ;
if ( Arg & 0x80 )
Str [ 0 ] = '1' ;
else
Str [ 0 ] = '0' ;
if ( Arg & 0x40 )
Str [ 1 ] = '1' ;
else
Str [ 1 ] = '0' ;
if ( Arg & 0x20 )
Str [ 2 ] = '1' ;
else
Str [ 2 ] = '0' ;
if ( Arg & 0x10 )
Str [ 3 ] = '1' ;
else
Str [ 3 ] = '0' ;
if ( Arg & 0x08 )
Str [ 4 ] = '1' ;
else
Str [ 4 ] = '0' ;
if ( Arg & 0x04 )
Str [ 5 ] = '1' ;
else
Str [ 5 ] = '0' ;
if ( Arg & 0x02 )
Str [ 6 ] = '1' ;
else
Str [ 6 ] = '0' ;
if ( Arg & 0x01 )
Str [ 7 ] = '1' ;
else
Str [ 7 ] = '0' ;
Str [ 8 ] = 0 ;
fprintf ( OutFile , "%d [%s]" , ArgSig , Str ) ;
}
static unsigned char not ( unsigned char Arg )
{
if ( Arg )
return ( 0 ) ;
else
return ( 1 ) ;
}
int main ( int argc , char * argv [ ] )
{
unsigned short Arg1 ;
unsigned short Arg2 ;
unsigned short Result ;
unsigned char Arg1Flag ;
unsigned char Arg2Flag ;
unsigned char ResultFlag ;
unsigned char VFlag ;
signed char Arg1Ch [ 2 ];
signed char Arg2Ch [ 2 ] ;
signed char ResultCh [ 2 ] ;
signed char VCh [ 2 ] ;
OutFile = fopen ( "vflag.txt" , "w" ) ;
fprintf ( OutFile , "* * * Sprawdzenie formuly na wskaznik przepelnienia w operacjach dodawania * * *\n\n" ) ;
Arg1Ch [ 1 ] = 0 ;
Arg2Ch [ 1 ] = 0 ;
ResultCh [ 1 ] = 0 ;
VCh [ 1 ] = 0 ;
for ( Arg1 = 0 ; Arg1 <= 0xFF ; Arg1++ )
{
for ( Arg2 = 0 ; Arg2 <= 0xFF ; Arg2++ )
{
Result = Arg1 + Arg2 ;
Arg1Ch [ 0 ] = '0' ;
Arg2Ch [ 0 ] = '0' ;
ResultCh [ 0 ] = '0' ;
VCh [ 0 ] = '0' ;
Arg1Flag = 0 ;
if ( Arg1 & 0x80 )
{
Arg1Flag = 1 ;
Arg1Ch [ 0 ] = '1' ;
} ;
Arg2Flag = 0 ;
if ( Arg2 & 0x80 )
{
Arg2Flag = 1 ;
Arg2Ch [ 0 ] = '1' ;
} ;
ResultFlag = 0 ;
if ( Result & 0x80 )
{
ResultFlag = 1 ;
ResultCh [ 0 ] = '1' ;
} ;
VFlag = ( Arg1Flag & Arg2Flag & not ( ResultFlag ) ) |
( not ( Arg1Flag ) & not ( Arg2Flag ) & ResultFlag ) ;
if ( VFlag )
{
VCh [ 0 ] = '1' ;
Conv ( Arg1 ) ;
fprintf ( OutFile , " + " ) ;
Conv ( Arg2 ) ;
fprintf ( OutFile , " = " ) ;
Conv ( Result ) ;
fprintf ( OutFile , " A1 Sign = %s A2 Sign = %s R Sign = %s V = %s \n" , Arg1Ch , Arg2Ch , ResultCh , VCh ) ;
} ;
} /* for */ ;
} /* for */ ;
fclose ( OutFile ) ;
return 0 ;
}
Początkowo robiłem wydruk każdej operacji, ale wyszło tego takie mnóstwo, że postanowiłem drukować do pliku jedynie te przypadki, które generują nadmiar w operacjach dodawania.
Pomimo tego, wyszło również całkiem sporo (fragment):
Kod: Zaznacz cały
* * * Sprawdzenie formuly na wskaznik przepelnienia w operacjach dodawania * * *
1 [00000001] + 127 [01111111] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
2 [00000010] + 126 [01111110] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
2 [00000010] + 127 [01111111] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
3 [00000011] + 125 [01111101] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
3 [00000011] + 126 [01111110] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
3 [00000011] + 127 [01111111] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
4 [00000100] + 124 [01111100] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
4 [00000100] + 125 [01111101] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
4 [00000100] + 126 [01111110] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
4 [00000100] + 127 [01111111] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
5 [00000101] + 123 [01111011] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
5 [00000101] + 124 [01111100] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
5 [00000101] + 125 [01111101] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
5 [00000101] + 126 [01111110] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
5 [00000101] + 127 [01111111] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
6 [00000110] + 122 [01111010] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
6 [00000110] + 123 [01111011] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
6 [00000110] + 124 [01111100] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
6 [00000110] + 125 [01111101] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
6 [00000110] + 126 [01111110] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
6 [00000110] + 127 [01111111] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
7 [00000111] + 121 [01111001] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
7 [00000111] + 122 [01111010] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
7 [00000111] + 123 [01111011] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
7 [00000111] + 124 [01111100] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
7 [00000111] + 125 [01111101] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
7 [00000111] + 126 [01111110] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
7 [00000111] + 127 [01111111] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
8 [00001000] + 120 [01111000] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
8 [00001000] + 121 [01111001] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
8 [00001000] + 122 [01111010] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
8 [00001000] + 123 [01111011] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
8 [00001000] + 124 [01111100] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
8 [00001000] + 125 [01111101] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
8 [00001000] + 126 [01111110] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
8 [00001000] + 127 [01111111] = -121 [10000111] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 119 [01110111] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 120 [01111000] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 121 [01111001] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 122 [01111010] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 123 [01111011] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 124 [01111100] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 125 [01111101] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 126 [01111110] = -121 [10000111] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
9 [00001001] + 127 [01111111] = -120 [10001000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 118 [01110110] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 119 [01110111] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 120 [01111000] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 121 [01111001] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 122 [01111010] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 123 [01111011] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 124 [01111100] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 125 [01111101] = -121 [10000111] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 126 [01111110] = -120 [10001000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
10 [00001010] + 127 [01111111] = -119 [10001001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 117 [01110101] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 118 [01110110] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 119 [01110111] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 120 [01111000] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 121 [01111001] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 122 [01111010] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 123 [01111011] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 124 [01111100] = -121 [10000111] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 125 [01111101] = -120 [10001000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 126 [01111110] = -119 [10001001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
11 [00001011] + 127 [01111111] = -118 [10001010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 116 [01110100] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 117 [01110101] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 118 [01110110] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 119 [01110111] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 120 [01111000] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 121 [01111001] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 122 [01111010] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 123 [01111011] = -121 [10000111] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 124 [01111100] = -120 [10001000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 125 [01111101] = -119 [10001001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 126 [01111110] = -118 [10001010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
12 [00001100] + 127 [01111111] = -117 [10001011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 115 [01110011] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 116 [01110100] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 117 [01110101] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 118 [01110110] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 119 [01110111] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 120 [01111000] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 121 [01111001] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 122 [01111010] = -121 [10000111] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 123 [01111011] = -120 [10001000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 124 [01111100] = -119 [10001001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 125 [01111101] = -118 [10001010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 126 [01111110] = -117 [10001011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
13 [00001101] + 127 [01111111] = -116 [10001100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 114 [01110010] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 115 [01110011] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 116 [01110100] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 117 [01110101] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 118 [01110110] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 119 [01110111] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 120 [01111000] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 121 [01111001] = -121 [10000111] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 122 [01111010] = -120 [10001000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 123 [01111011] = -119 [10001001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 124 [01111100] = -118 [10001010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 125 [01111101] = -117 [10001011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 126 [01111110] = -116 [10001100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
14 [00001110] + 127 [01111111] = -115 [10001101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 113 [01110001] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 114 [01110010] = -127 [10000001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 115 [01110011] = -126 [10000010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 116 [01110100] = -125 [10000011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 117 [01110101] = -124 [10000100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 118 [01110110] = -123 [10000101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 119 [01110111] = -122 [10000110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 120 [01111000] = -121 [10000111] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 121 [01111001] = -120 [10001000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 122 [01111010] = -119 [10001001] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 123 [01111011] = -118 [10001010] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 124 [01111100] = -117 [10001011] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 125 [01111101] = -116 [10001100] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 126 [01111110] = -115 [10001101] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
15 [00001111] + 127 [01111111] = -114 [10001110] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
16 [00010000] + 112 [01110000] = -128 [10000000] A1 Sign = 0 A2 Sign = 0 R Sign = 1 V = 1
Jak popatrzeć na to wszystko, to czasami wyniki rzeczywiście są dziwaczne.
Formuła na wskaźnik V to:
Sprawdziłem odpowiednio dużo przypadków wydrukowanych przez program. Sprawdziło się. Przykładowo: 7 dec + 127 dec = 134 dec, ale 134 dec = 86 hex.
Dla 8-bitów w U2 to będzie -122 dec → wynik rachunków jest poprawny (poprawny w sensie operacji na bitach, ale zostaje ustawiona flaga nadmiaru V, więc sumarycznie jest do ….).
Niestety dla operacji odejmowania się nie sprawdza, ale mam już podejrzenia, jak powinna ona wyglądać.
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: I8085 - emulator procesora
Wskaźnik V
Znalazłem potwierdzenie swoich eksperymentów i przypuszczeń. Stworzony program posiłkował się dokładnie taką formułą obliczania wskaźnika, jaka jest podana w dokumentacji do procka MC6800.
W przypadku dodawania:
W przypadku odejmowania:
No to już wszystko wiadomo.
Znalazłem potwierdzenie swoich eksperymentów i przypuszczeń. Stworzony program posiłkował się dokładnie taką formułą obliczania wskaźnika, jaka jest podana w dokumentacji do procka MC6800.
W przypadku dodawania:
W przypadku odejmowania:
No to już wszystko wiadomo.
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 12 gości