forum speccy.pl
ZX Spectrum => PROGRAMOWANIE => Wątek zaczęty przez: Gelip w 2021.11.07, 10:21:24
-
Potrzebuję program, który zamienia wartość HEX 8-bit na BIN, odwraca bity i oblicza znowu HEX:
HEX -> BIN -> REVBIN -> HEX
40 - 01000000 - 00000010 - 2
C0 - 11000000 - 00000011 - 3
78 - 01111000 - 00011110 - 1e
Znalazłem jakieś programy i próbuję zlepić ale coś chyba pomieszałem i nie wiem jak teraz zamienić znowu bin na dec i na hex:
HEXtoDEC (https://spectrumcomputing.co.uk/entry/25800/ZX-Spectrum/Hex_to_Dec_Conversion)
DECtoBIN (https://spectrumcomputing.co.uk/forums/viewtopic.php?p=52452#p52452)
Wyszło mi coś takiego.
DEC mi w sumie nie potrzebne tylko hex i bin
-
A jakie masz wymagania jeśli chodzi o wydajność? To jednorazowa konwersja, czy coś, co jest liczone na bieżąco?
Bo jeśli to ma być zrobione prosto i działać szybko, to ja bym to stablicował jako nibble (4 bity):
0 -> 0
1 -> 8
2 -> 4
3 -> C
4 -> 2
...
E -> 7
F -> F
Nie zapominając o zamianie miejscami młodszego nibble ze starszym.
Unika się jakiejkolwiek konwersji z/na format binarny*, przesuwania bitów itp. Masz znaki HEX na wejściu i znaki HEX na wyjściu.
* - z wyjątkiem policzenia indeksu do tablicy.
-
Chodzi o jednorazowe przeliczenie:
- program pyta o wartość HEX 8-bit
- konwertuje na bin, odwraca i konwertuje na hex
- wszystko wyświetla ładnie na ekranie i goto początek
Nie ukrywam iż chciałem gotowca :P w przeciwnym razie będę musiał przysiąść do tego co mam bo już prawie uzyskałem rozwiąznie - trzeba by rozpisać na kartce blokowo co robią poszczególne części programu i gdzie mają być skoki goto.
Da się w BASIC'u bez zamiany na dec tylko od razy na bin?
-
To jakiś przykład dydaktyczny? Bo nie bardzo widzę w nim sens.
-
To jakiś przykład dydaktyczny? Bo nie bardzo widzę w nim sens.
Konwerter kodu IR w formacie 32-bit unsigned integer na kod NEC ADDR=xx, CMD=xx np.
mam kod przycisku 807F28D7 gdzie adres 80 NOT=7F polecenie 28 NOT=D7 i z tego ma wyjść:
80h = 10000000b -> rev 00000001 = 01h ADDR
28h = 00101000b -> rev 00010100 = 14h CMD
-
A jak to się wiąże ze spectrum?
-
Wejściowe i wyjściowe wartości do przeliczenia są 8-bitowe a poza tym w BASIC ZX coś tam potrafię w przeciwieństwie do C.
Z ciekawości - do ZX pewnie da się podłączyć nadajnik czy odbiornik IR np. przez RS-232 w ZX Interface 1 tylko pewnie jeszcze nikt nie próbował.
Chyba można wykorzystać ZX do różnych obliczeń nie związanych z samym komputerem - jeśli nie ten dział to proszę przenieść do odpowiedniego.
-
Pytałem, bo byłem ciekawy czy po prostu korzystasz z ZX jako kalkulatora, czy masz do niego podłączony odbiornik IR :)
-
Zła wiadomość - musisz najpierw załadować Beta Basic 3.0.
-
Pomocy - zrobiłem nowe wersje podprogramów tak aby liniie w BASIC się nie pokrywały - ostatecznie połaczę wszystko w jeden program. Program hdclear.z80 to konwerter hex > dec (ma też konwersję w odwrotną stronę od linii numer 11)
Drugi program decbinv2.z80 konwertuje dec to bin gdzie mam wartość bin w b$. Myślałem iż zrobię z tego VAL b$ jako liczbę i wykorzystam polecenie BIN aby zamienić na dec a tu d..pa :-\
Mam też drugą wersję dec na bin rev dbr.z80 - w tablicy DIM b() jest wartość bin przed odwróceniem a w tablicy DIM i() po odwróceniu.
Brakuje mi tylko przekształcenia na dec bo na hex to wykorzystam hdclear.z80 od linii 11
-
Serio? Pomocy? Przecież konwersja liczby binarnej do dziesiętnej to zadanie dla pierwszej klasy informatyki.
Da się to napisać przy porannej kawie.
Algorytm bezpośrednio wynika z konstrukcji liczby binarnej.
Mamy liczbę binarną B: B7B6B5B4B3B2B1B0
DEC=B7*27+B6*26+B5*25+B4*24+B3*23+B2*22+B1*21+B0*20
A w Basic
LET dec=2^7*b(1)+2^6*b(2)+2^5*b(3)+2^4*b(4)+2^3*b(5)+2^2*b(6)+2^1*b(7)+2^0*b(8)
Dla liczby binarnej w zmiennej łańcuchowej b$:
LET dec=2^7*VAL b$(1)+2^6*VAL b$(2)+2^5*VAL b$(3)+2^4*VAL b$(4)+2^3*VAL b$(5)+2^2*VAL b$(6)+2^1*VAL b$(7)+2^0*VAL b$(8)
Albo elegancko w pętli
LET dec=0
FOR a=1 TO 8
LET dec=dec+2^(8-a)*VAL b$(a)
NEXT a
Można to zrobić na pierwotnej nie-odwróconej liczbie binarnej wystarczy odwrócić ją "w biegu", czyli zmieniać indeks od końca do początku.
LET dec=0
FOR a=1 TO 8
LET dec=dec+2^(8-a)*VAL b$(9-a)
NEXT a
Tylko po co zamieniać na dziesiętną? Można od razu na HEX.
To już poważniejsza sprawa, zajmuje aż 10 minut.
10 LET h$=""
20 LET start=1: GO SUB 1000
30 LET start=5: GO SUB 1000
40 STOP: REM wynik w h$
1000 LET h=0
1010 FOR a=0 TO 3
1020 LET h=h+2^(3-a)*VAL b$(a+start)
1030 NEXT a
1040 IF h>9 THEN LET h=h+(CODE "A"-CODE "9"-1)
1050 LET h$=h$+CHR$ (h+CODE "0")
1060 RETURN
Pętla oblicza wartość dziesiętną połówki bajta, dwie następne linie tworzą hex.
Oczywiście zamiast CODE "coś-tam" można wpisać stałe - będzie szybciej.
Także w tym przypadku można działać na nie-odwórconej liczbie binarnej:
10 LET h$=""
20 LET start=5: GO SUB 1000
30 LET start=1: GO SUB 1000
40 STOP: REM wynik w h$
1000 LET h=0
1010 FOR a=0 TO 3
1020 LET h=h+2^(3-a)*VAL b$(3-a+start)
1030 NEXT a
1040 IF h>9 THEN LET h=h+(CODE "A"-CODE "9"-1)
1050 LET h$=h$+CHR$ (h+CODE "0")
1060 RETURN
-
Serio? Pomocy? Przecież konwersja liczby binarnej do dziesiętnej to zadanie dla pierwszej klasy informatyki.
Da się to napisać przy porannej kawie.
Wiem, wiem ale ostatnio jestem bardzo zmęczony i nic mi się nie chce. Mimo tego już rozwiązałem problem - wystarczy tylko połączyć wszystko w jeden program. Zrobiłem konwersję z bin na dec, odwrotność bin i znowu na dec tak jak w pliku decbinrevdec.z80
Ale oczywiście dzięki za Twój kod - sprawdzę tylko nie wiem kiedy.
-
Luzik. W takim razie - "happy to help" cytując całkiem świeży film SF :)
-
@Phonex
Sprawdziłem Twoje programy i ładnie konwertują BIN na HEX. A jak w odwrotną stronę czyli HEX na BIN?
-
Trudne: 25 minut ;)
Albo to przez to, że dziś dzień wolny...
100 REM liczba HEX w x$, tylko duże litery
110 LET n$=""
120 LET s=CODE x$(1): GO SUB 2000
130 LET s=CODE x$(2): GO SUB 2000
140 STOP: REM wynik w n$
2000 IF s>CODE "9" THEN LET s=s-(CODE "A"-CODE "9"-1)
2010 LET s=s-CODE "0"
2020 FOR a=3 TO 0 STEP -1
2030 LET s$="0"
2040 LET b=INT s/(2^a)
2050 IF b THEN LET s$="1": LET s=s-b*2^a
2060 LET n$=n$+s$
2070 NEXT a
2080 RETURN
-
@Phonex
Posklejałem Twoje programy w jeden - dodałem odwrócenie BIN w tablicy DIM i$() ale coś jest nie tak bo źle oblicza. Możesz rzucić okiem na program conv.z80 bo coś źle działa.
P.S. Twój program zamiany HEX na BIN jednak źle działa. Jak podam mu HEX FF to źle oblicza BIN i zamiast samych 11111111 wyświetla 10001000
-
Zrobiłem konwerter mynew.tap używając swoich początkowych plików. Program zamienia:
HEX -> DEC -> BIN -> REVBIN -> DEC -> HEX ale wyświetla wyniki tylko:
HEX -> BIN -> REVBIN -> HEX
Jeśli podamy Hex=0 to wychodzi z programu (polecenie STOP)
Power button: 20DF10EF (32-bit unsigned)
czyli 20 NOT 20=DF 10 NOT 10=EF
20 00100000 00000100 04
10 00010000 00001000 08
NEC ADDR=04, CMD=08
-
Nawias w złym miejscu w linii 2040 >:(
Tak ma być:
100 REM liczba HEX w x$, tylko duże litery
110 LET n$=""
120 LET s=CODE x$(1): GO SUB 2000
130 LET s=CODE x$(2): GO SUB 2000
140 STOP: REM wynik w n$
2000 IF s>CODE "9" THEN LET s=s-(CODE "A"-CODE "9"-1)
2010 LET s=s-CODE "0"
2020 FOR a=3 TO 0 STEP -1
2030 LET s$="0"
2040 LET b=INT (s/2^a)
2050 IF b THEN LET s$="1": LET s=s-b*2^a
2060 LET n$=n$+s$
2070 NEXT a
2080 RETURN
Poprawiłem w pliku.
Drugi zamieszczony programik BIN -> HEX sam odwraca łańcuch w trakcie - nie potrzeba osobnej procedury, tak jest szybciej i krócej. Też poprawiłem. Teraz już działa dobrze. Można jeszcze trochę przyspieszyć i skrócić wpisując wartości zamiast CODE "xx".
-
Pod jaką zmienną jest odwrócona wartość BIN bo chciałbym aby się wyświetlała jak w niepoprawionej wersji conv.z80 ?
-
Sorry, nie ma.
Nie ma odwracania, program po prostu przetwarza łańcuch od końca.
Wiem, że wygląda teraz niesymetrycznie, ale tak naprawdę chyba nie jest do niczego potrzebne? ;)
Rozumiem, że przydawało się do testów, ale jak już działa...
Ewentualnie można wydrukować łańcuch od tyłu :P
Przy okazji jak się przyglądałem, to wpadłem, że IF w linii 2050 nie jest do końca niezbędny. Odejmowanie od s sobie poradzi, tylko trzeba jakoś wybrać "0" czy "1". I wymyśliłem! Bezpośrednie indeksowanie łańcucha, które zawsze mnie rozbawia (w linii 2060) :D.
100 REM liczba HEX w x$, tylko duże litery
110 LET n$=""
120 LET s=CODE x$(1): GO SUB 2000
130 LET s=CODE x$(2): GO SUB 2000
140 STOP: REM wynik w n$
2000 IF s>CODE "9" THEN LET s=s-(CODE "A"-CODE "9"-1)
2010 LET s=s-CODE "0"
2020 FOR a=3 TO 0 STEP -1
2040 LET b=INT (s/2^a)
2050 LET s=s-b*2^a
2060 LET n$=n$+"01"(b+1)
2070 NEXT a
2080 RETURN
Jest krótsze.
Jak już miałem to w pamięci, to w ten sam sposób poprawiłem też BIN -> HEX:
10 LET h$=""
20 LET start=5: GO SUB 1000
30 LET start=1: GO SUB 1000
40 STOP: REM wynik w h$
1000 LET h=0
1010 FOR a=0 TO 3
1020 LET h=h+2^(3-a)*VAL b$(3-a+start)
1030 NEXT a
1050 LET h$=h$+"0123456789ABCDEF"(h+1)
1060 RETURN
I teraz jest szybsze!
I lepiej wygląda :D
I od razu widać co robi.
EDIT: poprawki w linii 1050. Zmiana załącznika
-
Coś źle działa
-
A no jasne! Zapomniałem o zerze w łańcuchu.
Przetestowałem za słabo, jak się okazuje.
Poprawiłem w poprzednim poście i zmieniłem załączony plik.
-
Na zakończenie można by jeszcze sprawdzić, jak długi byłby konwerter korzystający z pomysłu trojacka z postu #2.
Skoro już jest działający poprawnie odwracacz HEX, można wygenerować sobie wszystkie wyniki i stablicować je.
Oto kompletny konwerter.
Dzięki "xxxxxxx" w tablicy, da się to zrobić w dwóch liniach tylko!
REM wejście x$, wyjście h$
LET a$="084C2A6E19xxxxxxx5D3B7F"
LET h$=a$(CODE x$(2)-47): LET h$=h$+a$(CODE x$(1)-47)
Dziękuję za uwagę :D
-
Dzięki "xxxxxxx" w tablicy, da się to zrobić w dwóch liniach tylko!
Co mam wstawić za te xxxxxxx ?
-
Dokładnie to, co tam jest - iksy są po to, żeby przeskoczyć różnicę między kodem '9' i 'A' - '9' to 57, 'A' - 65 czyli między nimi masz 7 znaków, które się nigdy nie pojawią w wejściowym HEXie.
-
Faktycznie działa:
5 POKE 23658,8
10 INPUT "Hex ";x$
20 LET a$="084C2A6E19xxxxxxx5D3B7F"
30 LET h$=a$(CODE x$(2)-47): LET h$=h$+a$(CODE x$(1)-47)
40 PRINT x$;" -> ";h$
50 GO TO 10