Zgrywus
-- Sebastian Pawlak, PCKurier 26/1995.
Niektórzy pewnie pamiętają z pism poświęconych ośmiobitowym komputerom
zamieszczane tam programy. Były to niekiedy wielostronnicowe szeregi
cyfr w systemie heksadecymalnych, które po zmodyfikowaniu specjalnym
programem tworzyły np. grę czy program użytkowy. System szesnastkowego
zapisu programu jest bardzo wygodny, gdyż pozwala niewielkim nakładem
sił wpisać wielokrotnie wiekszy program. Na przykład zamieszczony na
wydruku 1 program w asemblerze zajmuje 497 bajtów, a w zapisie
heksadecymalnym 211.
Zasady asemblacji są następujące:
Tasm Wersja.asm Tlink /t Wersja.obj
Ten sam program w zapisie szesnastkowym maszynowej wersji programu z wydruku 1 ma postać.
eb,1a,90,b4,09,cd,21,c3,57,65,72,73,6a,61,20 44,4f,53,20,24,2e,24,20,24,20,0d,0a,24,ba,08 01,e8,e1,ff,b4,30,cd,21,04,30,80,c4,30,a2,16 01,88,26,18,01,ba,16,01,e8,cb,ff,ba,14,01,e8 c5,ff,ba,18,01,e8,bf,ff,b4,4c,cd,21
Jak działa Zgrywus? Dwa programy przedstawione na wydrukach 2 i 3 to: char2hex, przetwarzający pliki na pliki z rozszerzeniem.Com w zapisie heksadecymalnym i hex2char, odwracający sytuację.
Obowiązują nastepujące zasady postępowania:
Program, np. w Assemblerze, przetwarzamy na maszynowy (czyli kompilujemy).
Otrzymany plik com lub exe wstawiamy jako parametr, Char2hex.exe plik.com plik.hex.
Otrzymany plik "plik.hex" drukujemy w naszej gazecie.
Użytkownik, który kupił czasopismo, przepisuje program do pliku.
Następnie uruchamia program Hex2char.exe, w taki sposób: Hex2char.exe plik.hex plik.com, co powoduje zapisanie do pliku "plik.com" przekształconego już programu.
Czytelnik zauważy jeszcze na ekranie sumę kontrolną pliku z gazety i tę, która została obliczona w jego wersji pliku. Jeśli sumy różnią się, to znaczy, że użytkownik popełnił błąd w przepisywaniu.
Przewidując pytania, jakie mogą mieć czytelnicy, z góry udzielę na nie odpowiedzi.
Przecież można jeszcze bardziej zmniejszyć program, publikując wydruk pliku w formacie.com?
Można tak zrobić, ale wpisywanie programu w bajtach jest dosyć uciążliwe, dlatego stosuje sie wydruki szesnastkowe mniejsze niż program w danym języku, ale łatwiejsze do wpisania niż kod maszynowy.
Przecież publikowanie programów źródłowych nie jest stosowane dla zabawy, ale w celu nauczenia kogoś zasady działania opublikowanego programu?
Tak właśnie jest. W przypadku programów w języku wysokiego poziomu poddaję się (można je tylko uruchamiać), ale jeśli program jest w Assemblerze, to od czego są debuggery? Co prawda program napisany w Pascalu też można oglądać pod debuggerem, ale wtedy bęzie to już kod w asemblerze, a nie program pascalowy.
Wydruk 1 Main SEGMENT Assume Cs:Main,Ds:Main Org 100h Begin: jmp Start Write PROC Near mov ah,9h int 21h RET Write ENDP Tekst DB 'Wersja DOS ','$' Kropa DB '.','$' Wer_g DB ' ','$' Wer_p DB ' ',13,10,'$' Start: mov dx,Offset Tekst call Write mov ah,30h int 21h add al,48 add ah,48 mov Wer_g,al mov Wer_p,ah mov dx,Offset Wer_g call Write mov dx,Offset Kropa call Write mov dx,Offset Wer_p call Write mov ah,4ch int 21h Main ENDS END Begin Wydruk 2 - char2hex { Char2Hex wer.1.0 Sebastian Pawlak 1994r.} Program _char2hex_; Uses dos,crt; Var Odczyt,Zapis :text; Bajt :char; Pozycja_w_pliku:word; Opis_pliku :searchrec; Kontrola :longint; {Suma kontrolna pliku} Const Szer=15; {ilość liczb w kolumnie} Function Char2hex (Znak:char) :string; {dec na hex} Var L :array [0..1] of byte; Hex :string [2]; Petla :byte; Begin Hex:='--'; L [0]:=ord (Znak) div 16*16; L [1]:=ord (Znak)-L [0]; L [0]:=L [0] div 16; For Petla:=0 to 1 do Begin Hex [Petla+1]:=chr(L [Petla]+48); If L [Petla]>9 then Hex [Petla+1]:=chr(L [Petla]+97-10); End; Char2hex:=Hex; End; Begin If paramcount<2 then writeln ('Skladnia: Char2Hex.exe zrodlo.chr cel.hex') Else Begin findfirst (paramstr (1),Archive,Opis_pliku); If Opis_pliku.Name='' then Begin write ('Brak pliku.'); halt; End; assign (Odczyt,paramstr (1)); assign (Zapis ,paramstr (2)); reset (Odczyt); rewrite (Zapis); writeln (Zapis,'Char2Hex wer.1.0 Sebastian Pawlak'); Pozycja_w_pliku:=0; Kontrola:=0; Repeat read (Odczyt,Bajt); Pozycja_w_pliku:=Pozycja_w_pliku+1; Kontrola:=Kontrola+ord (Bajt)*Pozycja_w_pliku; If ((Pozycja_w_pliku div Szer=Pozycja_w_pliku/Szer)or (Pozycja_w_pliku=Opis_pliku.Size)) then writeln (Zapis,char2hex (Bajt)) Else write (Zapis,char2hex (Bajt),','); gotoxy (1,wherey); write(round(Pozycja_w_pliku/Opis_pliku.Size*100),'%'); Until Pozycja_w_pliku=Opis_pliku.Size; writeln (Zapis,'*',Kontrola); close (Odczyt); close (Zapis); End; End. Wykres 3 - hex2char { Hex2char wer.1.0 Sebastian Pawlak 1994r.} Program _Hex2char_; Uses dos,crt; Var Odczyt,Zapis :text; Hex :string [3]; Opis_pliku :searchrec; Czolowka,Wiersz :string; Petla,Dec :byte; Pozycja_w_wierszu :byte; Pozycja_w_danych :word; Kod :integer; Kontrola :longint; Begin If paramcount<2 then writeln ('Skladnia: Hex2Char.exe zrodlo.hex cel.chr') Else Begin findfirst (paramstr (1),Archive,Opis_pliku); If Opis_pliku.Name='' then Begin write ('Brak pliku.'); halt; End; assign (Odczyt,paramstr (1)); assign (Zapis ,paramstr (2)); reset (Odczyt); rewrite (Zapis); readln (Odczyt,Czolowka); Writeln ('Czolowka: ',Czolowka); Hex:='$--'; Kontrola:=0; Pozycja_w_danych:=0; Repeat readln (Odczyt,Wiersz); If Wiersz [1]'*' then {koniec danych, poczatek sumy} Begin For Pozycja_w_wierszu:=0 to length (Wiersz) div 3 do Begin For Petla:=1 to 2 do Hex [Petla+1]:=Wiersz [Petla+Pozycja_w_wierszu*3]; val (Hex,Dec,Kod); write (Zapis,chr (Dec)); Pozycja_w_danych:=Pozycja_w_danych+1; Kontrola:=Kontrola+Dec*Pozycja_w_danych; End; write ('.'); End; Until Wiersz [1]='*'; writeln; writeln ('Suma kontrolna stara: ',Wiersz,' nowa: *', Kontrola); close (Odczyt); close (Zapis); End; End.