home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #7
/
amigamamagazinepolishissue1998.iso
/
magazyn_amiga
/
0896
/
048_asembler
< prev
next >
Wrap
Text File
|
1998-03-26
|
10KB
|
394 lines
--------------Proszë zîoûyê dwuszpaltowo-------------------
PROGRAM SZYFRUJÂCY DANE
<a>Bartek Pampuch
<txt>Miesiâc temu napisaliômy program stanowiâcy "wstëp" do
programu szyfrujâcego dane. Program ten pytaî uûytkownika o nazwë
pliku oraz hasîo, a nastëpnie kopiowaî podany plik do pamiëci i
zapisywaî go pod nazwâ "ram:plik". Hasîo natomiast zapisywane
byîo w pliku "ram:haslo". Na koniec uruchamiany byî gîówny
program kodujâcy "df0:code" (dzisiaj go napiszemy). Bëdzie on
wykonywaî nastëpujâce czynnoôci:
1) Wczytanie pliku ram:plik do pewnego bufora (u nas: DATA)
2) Wczytanie pliku ram:haslo do pewnego bufora (u nas: HASLO)
3) Kodowanie bufora DATA hasîem z bufora HASLO
4) Zapisanie bufora DATA do pliku ram:plik
Zanim przyjrzysz sië kodowi úródîowemu, musisz poznaê zasadë
dziaîania kilku nowych rozkazów.
Pierwszy to "TST.x REJESTR_DANYCH/(ADRESOWY)", gdzie x to B, W
lub L. Rozkaz ten sprawdza, czy podany rejestr danych (lub dana
znajdujâca sië pod okreôlonym adresem) jest pusty, czy coô
zawiera. Jeûeli jest pusty (czyli jego zawartoôê to 0), to
ustawiany jest znacznik Z (za chwilë wytîumaczë, jak të wiadomoôê
wykorzystaê). W przeciwnym wypadku (jeôli coô zawiera), znacznik
Z jest zerowany.
Moûemy z tego skorzystaê, uûywajâc innego rozkazu: "BEQ
Etykieta", który jest tak zwanym rozkazem warunkowym. Sprawdza
on, czy znacznik Z jest ustawiony. Jeûeli tak, to zostanie
wykonany skok w miejsce programu, okreôlone przez Etykietë. W
innym wypadku wykonywana jest instrukcja, znajdujâca sië
bezpoôrednio za rozkazem BEQ:
<l>
lea $80000,a0
tst.l d0
beq D0Pusty
D0Peîny:
tst.l (a0)
beq DanaPodA0Pelna
jmp DanaPodA0Pusta
D0Pusty:
tst.l (a0)
beq DanaPodA0Pelna
DanaPodA0Pusta:
...
DanaPodA0Pelna:
...
<txt>Powyûszy schemat obrazuje sposób dziaîania rozkazów TST
oraz BEQ.
Przeciwieïstwem rozkazu BEQ jest rozkaz BNE. W wypadku tego
rozkazu skok do Etykiety wykonywany jest, gdy znacznik Z jest
wyzerowany.
<l>
tst.l d0
bne D0Pelny
D0Pusty:
...
D0Pelny:
...
<txt>Istnieje jeszcze kilka innych rozkazów warunkowych, ale
powiemy o nich, kiedy bëdâ nam potrzebne.
Teraz natomiast zapoznam cië z nowym systemem liczbowym, zwanym
systemem dwójkowym. W systemie tym, do zapisania liczb uûywa sië
jedynie dwóch cyfr: jedynki oraz zera. W liczbach zapisanych w
tym systemie cyfra najbardziej na prawo jest cyfrâ jednoôci,
kolejna (na lewo) to cyfra dwójek, kolejna (na lewo) to cyfra
czwórek, kolejna -- ósemek itd. (Dla porównania: w systemie
dziesiëtnym cyfry w liczbie oznaczajâ kolejno: jednoôci,
dziesiâtki, setki tysiëcy itd.)
Aby zaznaczyê, ûe liczba zapisana jest systemem dwójkowym, naleûy
przed niâ postawiê znaczek "%".
A oto kilka przykîadów (przeliczeï):
%01110011 = 0 * 128 + 1 * 64 + 1 * 32 + 1 * 16 + 0 * 8 + 0
* 4 + 1 * 2 + 1 * 1 = 64 + 32 + 16 + 2 + 1 = 115
%1010 = 1 * 8 + 0 * 4 + 1 * 2 + 0 * 1 = 8 + 2 = 10
%111 = 7 ; %1 = 1 ; %10 = 2 ; %100 = 4
Jeûeli mniej wiëcej rozumiesz ten nowy system liczbowy, moûemy
przejôê do omówienia rozkazu: "EOR". Wykonuje on operacjë
logicznâ EXCLUSIVE OR. Prostszymi sîowami: EOR jest rodzajem
pewnego dziaîania (tak jak dodawanie czy odejmowanie), ale jego
argumentami sâ jedynki lub zera. Wynikiem EOR jest takûe jedynka
lub zero (w zaleûnoôci od argumentów).
<l>
1 EOR 1 = 0
0 EOR 0 = 0
1 EOR 0 = 1
0 EOR 1 = 1
<txt>
Jak widaê, EOR zwraca jedynkë, gdy ma dwa róûne argumenty. Dwa
identyczne argumenty zwracajâ zero.
Jeûeli wykonamy dziaîanie:
<l>
A EOR B = C
<txt>
(A -- moûe byê naszym plikiem, B -- hasîem, natomiast C to
zaszyfrowany plik), to dziaîanie funkcji EOR, której argumentami
sâ C oraz B, zwróci nam A:
<l>
C EOR B = A
<txt>
Oto inny przykîad tego typu:
<l>
%10101100 - A
EOR %11110000 - B
--------------
%01011100 - C
%01011100 - C
EOR %11110000 - B
--------------
%10101100 - A
<txt>Teraz moûemy wreszcie przystâpiê do napisania naszego
programu:
<l>
INCDIR DF0:
INCLUDE moj_dos.i
; Tu znajduje sië procedura otwierajâca bibliotekë dos.library
; Po otwarciu biblioteki jej adres przesyîany jest do rejestru A6
move.l d0,a6
jsr _LVOOutput(a6)
move.l d0,OutputBase
; Póúniej OutputBase musi byê wykorzystane w celu wypisania czegokolwiek
; w oknie CLI/SHELL
; Otwierany jest plik ram:plik (w trybie OLDFILE)
; Jego zawartoôê wczytywana jest (rozkazem _LVORead) do bufora DATA
; Testowana jest wielkoôê pliku (iloôê odczytanych danych) i jeôli
; jest ona róûna od zera - zapisywana jest pod FSize
tst.l d0
beq.s FileError
move.l d0,FSize
; Zamykany jest otwarty plik ram:plik (Polecenie _LVOClose)
; Otwierany jest plik ram:haslo
; Jego zawartoôê wczytywana jest do bufora HASLO
; Testowana jest wielkoôê pliku (jeôli wiëksza od zero - zapisywana jest
; pod HSize
; Zamykany jest otwarty plik ram:haslo
MainProg:
lea DATA,a0
lea HASLO,a1
move.l HSize,d7
move.l FSize,d6
sub.l #1,d7
Loop1:
eor.b (a1)+,(a0)+
sub.l #1,d6
tst.l d6
beq LoopEnd
dbra d7,Loop1
lea HASLO,a1
move.l HSize,d7
jmp Loop1
LoopEnd:
; Teraz otwierany jest plik ram:plik (w trybie NEWFILE)
; do tego pliku zapisywana jest zawartoôê bufora DATA
; zamykany jest plik ram:plik
; zamykana jest biblioteka dos.library
; program koïczy swoje dziaîanie
rts
FileError:
; wyôwietlenie komunikatu o bîëdzie (np. za pomocâ polecenia _LVOWrite)
; zamkniëcie biblioteki dos.library
; wyjôcie z programu
; Oto niektóre ze zmiennych niezbëdnych do poprawnego dziaîania programu:
OutputBase: ds.l 1
FSize: ds.l 1
HSize: ds.l 1
SECTION BSS,BSS_P
DATA: ds.b 50000
HASLO: ds.b 100
<txt>Gîówny program jest bardzo krótki i ogranicza sië zaledwie
do kilku instrukcji. Po zainicjowaniu rejestrów adresowych (A0
zawiera adres, pod którym znajduje sië wczytany plik, natomiast
A1 wskazuje na bufor, do którego wczytane jest hasîo) nastëpuje
przesîanie do rejestrów danych odpowiednich danych. Rejestr D7
zawiera liczbë bëdâcâ dîugoôciâ podanego hasîa (minus jeden, gdyû
jak pamiëtamy, rozkaz dbra wykonuje pëtle o jeden raz wiëcej niû
podane jest w rejestrze), natomiast D6 to dîugoôê wczytanego
pliku (minus jeden). Rozpoczyna sië gîówna pëtla szyfrujâca
(Loop1). Szyfrowany jest bajt po bajcie tyle razy, ile liter ma
nasze hasîo. Bowiem ponowne uûycie rozkazu:
<l>
eor.b (a1)+,(a0)+
<txt>szyfrowaîoby plik przypadkowymi danymi (i nie daîoby sië go
póúniej odkodowaê), gdyû A1 nie wskazywaîby na nasze hasîo.
Musimy wiëc regularnie odnawiaê zawartoôê tego rejestru. Robi to
funkcja "lea HASLO,a1" wywoîywana zawsze, gdy pëtla wykonana
zostanie tyle razy, ile liter jest w haôle. Nie moûemy teû
zapomnieê o wielkoôci szyfrowanego pliku. Dlatego teû po
zakodowaniu kaûdej litery odejmujemy od wielkoôci pliku jeden i
sprawdzamy, czy wartoôê ta osiâgnëîa juû zero. Jeûeli tak,
nastëpuje skok i pëtla koïczy swoje dziaîanie.
Wydaje mi sië, ûe niezrozumiaîa moûe byê dla niektórych linia:
<l>
SECTION BSS,BSS_P
<txt>Na razie wytîumaczë tylko, co ta linia robi, ale nie
powiem, dlaczego tak sië dzieje (o tym kiedy indziej).
Otóû linia ta (gdyû nie moûna jej nazwaê rozkazem) sprawia, ûe
pamiëê dla wszystkich danych, znajdujâcych sië pod niâ
(najczëôciej sâ to bufory), bëdzie przydzielana dopiero podczas
uruchamiania programu. Gdybyômy të linië pominëli, nasz program
(zasemblowany) zajmowaîby na dyskietce ponad 50 KB (nagrane
zostaîyby bufory DATA i HASLO). A w ten sposób nagrana zostanie
tylko informacja o tych buforach i ich wielkoôciach.
Nasz program wykorzystuje funkcjë EOR i dziëki temu nie musimy
pisaê drugiego programu odkodowujâcego zaszyfrowane dane.
Albowiem df0:code dziaîa w obie strony (wynika to z definicji
funkcji EOR).
Niestety, "code" ma jednâ zasadniczâ wadë: nie potrafi kodowaê
plików wiëkszych niû 50 000. Oczywiôcie moûna zwiëkszyê bufor
DATA na 800 KB czy nawet wiëcej, ale do tego potrzebowalibyômy
duûej iloôci pamiëci. Na szczëôcie jest rozwiâzanie tej
sytuacji. Istnieje pewna procedura (biblioteki dos.library),
umoûliwiajâca wczytywanie danego pliku "porcjami".
Nazwa: _LVOSeek (-66)
Funkcja: Przesuwa miejsce uchwytu pliku. Umoûliwia to wczytywanie
danego pliku do pamiëci partiami. Rozkaz _LVORead wczytuje
zawartoôê pliku od jego poczâtku. Za pomocâ _LVOSeek moûemy
zmieniê miejsce, od którego _LVORead bëdzie wczytywaîo dane.
Dziëki temu moûemy wczytaê pierwsze 10 KB pliku, przesunâê uchwyt
pliku o 10 KB dalej, ponownie wczytaê 10 KB, znów przesunâê
uchwyt itd.
Wejôcie: D1 -- uchwyt pliku (otrzymany za pomocâ polecenia _LVOOpen)
D2 -- Liczba okreôlajâca nowâ pozycjë uchwytu
D3 -- tryb, czyli sposób, w jaki powyûsza liczba ma byê traktowana
Dopuszczalne sâ nastëpujâce tryby: OFFSET_BEGINNING -- liczba
oznacza odlegîoôê wzglëdem poczâtku pliku (np. liczba 1234 ustawi
uchwyt pliku na 1234 bajt tego pliku); OFFSET_CURRENT -- liczba w
rejestrze D2 oznacza przesuniëcie pozycji wzglëdem pozycji
aktualnej (np. liczba 1234 ustawi uchwyt pliku o 1234 bajty dalej
od aktualnego ustawienia uchwytu); OFFSET_END -- liczba oznacza
odlegîoôê wzglëdem koïca pliku (np. 1234 ustawi uchwyt pliku na
1234 bajt od koïca).
UWAGA! W trybie OFFSET_CURRENT dopuszczalne sâ takûe liczby
ujemne (np. -1234 przesunie uchwyt pliku o 1234 bajty wstecz).
Poniewaû omówiliômy juû gîówne polecenia biblioteki dos, na
nastëpnej lekcji zajmiemy sië bibliotekâ INTUITION. Nauczymy sië
otwieraê wîasne okna, ekrany i gadûety. Jeûeli wystarczy nam
czasu, stworzymy naszâ pierwszâ aplikacjë opartâ na interfejsie
graficznym. Na kolejnych lekcjach bëdziemy sië uczyli tworzyê
wîasne MENU, rysunki itd. Juû niedîugo bëdziemy pisali programy
wykorzystujâce polecenia wielu bibliotek. Nasz kurs zakoïczymy
stworzeniem wîasnej biblioteki.
-- No, no, ciekawe, ale jeszcze ciekawsze: "TRZY DORZYJEM TEY
POCJEHY, ABY KONJEC TFEGO KÓRSÓ TRAFIÎ POD STÛEHY?"
-- Ômiej sië ômiej, ale zobaczysz, ûe teraz bëdziemy sië uczyli
coraz szybciej.
-- Obyô miaî racjë! A tymczasem do nastëpnego MA.
-- Do nastëpnego.