     ||||| ||     ||     |
    ||  || ||     |
   ||   || ||     ||||\ ||
  |||||||| ||     |   |  |
 ||     || ||     |   |  |
||      || \||||| \|||/  || 03.2000  priv: albi26@poczta.onet.pl
				     Web:  www.republika.pl/zamczysko
******************************************************************************

				----------------------
				ASEMBLER STRORY PART 3
				----------------------

ALO ALO...
teraz przejdziemy do bardziej skomplikowanych rzeczy jak przesuniecia i
operacje logiczne, jest to niezedne do programowania w ASM.
Mam nadzieje ze czytales 1 i 2 czesc i masz trochwe wiecej wiedzy na temat
ASM niz przed tym kursem. Zwiasku z tym zrozumiesz ponizsze instrukcje
bez wiekszego problemu.
To chyba bedzie ostatnia czesc ASEMBLER STORY, bo juz nie mam pomyslu na
dalsze czesci...chociasz chodzi mi po glowie asembler pod WIN32 i pisanie
TSRow (programow rezydentnych) ale musze zebrac materialy.
Zachecam tez wszystkich zaiteresowanych do zdobycia ksiazki
"JAK PISAC WIRUSY" autora ANDRZEJ DUDEK, bardzo wam sie przyda.
Dobra chyba skonczymy na tymi... a teraz do nauki.
No moze jeszcze jedna rzecz napiszcie do mnie e-mail (krytyka mile widziana)
ale moze byc cokolwiek, byle bym wiedzial ze ktos TO czytal.
Mozna mnie tez zlapac na #crackpl (mam modem za ktory musze bulic z wlasnej
kasy to nie zawsze jest taka mozliwosc ale mozna sprobowac).

JESZCE RAZ PRZYPOMNE NIE SA TO WYLACZNIE MOJE TEKSTY JEST TO ZBIOR INNYCH TEKSTOW
ZEBRANE PRZE ZEMNIE I ODPOWIEDNIO ZREDAGOWANE DZIEKI TEMU MASZ WSZYSTKO JAK NA TACY
A JAK CI SIE TO NIEPODOBA TO MOZESZ ORGINALOW POSZUKAC W NECIE I WCALE NIE MUSISZ 
CZYTAC TEGO TEKSTU POPROSTU NIE WIDZIALEM SENSU PISANIE TEKSTU OD PODSTAW PRZECIESZ
		KTOS JUZ TO NAPISAL I ZROBIL TO BARDZO DOBRZE!!!

-------------------------------------------------------

SPIS TRESCI

1.Przesuniecia i obroty
2.Instrukje NOT/AND/OR/XOR (operacje logiczne)
3.Spis podstawowych instrukcji
4.Male wprowadzenie do Win32

-------------------------------------------------------

1.Przesuniecia i obroty 

skladnia:

	SHL <rejestr lub zmienna,liczba>  przesuniecie logiczne w lewo
	SAL <rejestr lub zmienna,liczba>  przesuniecie arytmetyczne w lewo

          ____________________________________________________
 ---     |                                                    |
| C | <--| 7  <-- 6  <-- 5  <-- 4  <-- 3  <-- 2  <-- 1 <-- 0  |<--0
 ---     |____________________________________________________|

mov al,15h   ;00010101b
moc cl,2
shl al,cl
wynik:AL=54h ;01010100b

skladnia:

	SHR <rejestr lub zmienna,liczba>  przesuniecie logiczne w prawo

	  ____________________________________________________
         |                                                    |    ---
    0 -->| 7  --> 6  --> 5  --> 4  --> 3  --> 2  --> 1 --> 0  |-->| C |
         |____________________________________________________|    ---

mov al,15h   ;00010101b
mov cl,3
shr  al,cl
wynik:AL=02h  00000010b
Znacznik C ustawiony..

skladnia:

	SAR <rejestr lub zmienna,liczba>  przesuniecie arytmetyczne w prawo

	  ____________________________________________________
         |                                                    |    ---
         | 7  --> 6  --> 5  --> 4  --> 3  --> 2  --> 1 --> 0  |-->| C |
         |_|__|_______________________________________________|    ---
           |__|

mov al,0A3h      ;10100011b
mov cl,4
sar al,cl
AL=0FAh  ;1111010b
Znacznik C wyzerowany

skladnia:
	
	ROL <rejestr lub zmienna,liczba>    obrot w lewo

          ____________________________________________________
 ---     |                                                    |
| C | <--| 7  <-- 6  <-- 5  <-- 4  <-- 3  <-- 2  <-- 1 <-- 0  |<--|
 ---   | |____________________________________________________|   |
       |__________________________________________________________|

mov al,15h   ;00010101b
rol al,1
Wynik:AL=2Ah   ;00101010b

skladnia:
	RCL <rejestr lub zmienna,liczba>    obrot w lewo z przeniesieniem

              ____________________________________________________
     ---     |                                                    |
 - -| C | <--| 7  <-- 6  <-- 5  <-- 4  <-- 3  <-- 2  <-- 1 <-- 0  |<--|
 |   ---     |____________________________________________________|   |
 |____________________________________________________________________|

mov al,15h   ;00010101b
mov cl,3
rcl al,cl
Wynik:AL=A8h   ;10101000b
Znacznik C wyzerowany

skladnia:
	
	ROR <rejestr lub zmienna,liczba>    obrot w prawo

          ____________________________________________________
         |                                                    |      ---
    |--->| 7  --> 6  --> 5  --> 4  --> 3  --> 2  --> 1 --> 0  |--|--| C |
    |    |____________________________________________________|  | > ---
    |____________________________________________________________|

Zakladajac ze wskaznik C jest wyzeroway

mov al,21h    ;00100001b
ror al,1
Wynik:Al=90h  ;10010000b

Znacznyik C ustawiony

skladnia:

	RCR <rejestr lub zmienna,liczba>    obrot w prawo z przeniesieniem

          ____________________________________________________
         |                                                    |   ---
    |--->| 7  --> 6  --> 5  --> 4  --> 3  --> 2  --> 1 --> 0  |--| C |--
    |    |____________________________________________________|   ---  |
    |__________________________________________________________________|

Przy zalozeniu ze znacznik C jet ustawiony
mov al,0cdh   ;11001101b
mov cl,2
rcr al,cl
Wynik:AL=F3h  11110011b
Znacznik C wyzerowany

--UWAGA:-------------------------------------------------------------------
Jesli np.chodzi o zwiekszenie wydajnosci programow(predkosc) mozna stosowac
przesuniecia w prawo lub lewo zamiast mnozenia lub dzielenia.Jednak mnozyc
i dzielic w ten sposob jednynie przez potege dwojki.(przyklad)

mov al,32   ;0010000b
mov cl,4
shr al,cl
Wynik:AL=2 ;00000010b czyli 32/16

mov al,4  ;00000100b
moc cl,3  ;2^3=8
shl al,cl
Wynik AL=32  ;4*8
---------------------------------------------------------------------------

2.Instrukcja NOT/AND/OR/XOR (instrukcje logiczne)

skladnia:
                        NOT <rejestr lub zmienna>

Jest to negacja logiczna.Dzialanie polega na zamianie kazdego bitu argumentu na
przeciwny.

mov ax,14B5h;   ;0001010010110101b
not ax
Wynik:AX=0EB4Ah (1110101101001010b)

skladnia:
            AND <rejestr lub zmienna,rejestr,zmienna lub wartosc>
           TEST <rejestr lub zmienna,rejestr,zmienna lub wartosc>
            OR  <rejestr lub zmienna,rejestr,zmienna lub wartosc>
           XOR  <rejestr lub zmienna,rejestr,zmienna lub wartosc>

opis dzialania:

             AND            OR              XOR 
        -----------------------------------------------
       | A    B    W   | A    B    W   | A    B    W   |
       |-----------------------------------------------|
       | 0    1    0   | 0    1    1   | 0    1    1   |
       | 1    0    0   | 1    0    1   | 1    0    1   |
       | 1    1    1   | 1    1    1   | 1    1    0   |
        -----------------------------------------------

przyklady:

mov   al,2ch   ;00101100b
mov   bl,65h   ;01100101b
and   al,bl

Wynik:AL=24h   ;00100100b

mov   al,59h   ;01011001b
mov   bl,9bh   ;10011011b
or    al,bl

Wynik:AL=DBh  ;11011011b

mov   al,57h  ;01010111b
mov   bl,0C2h ;11000010b
xor   al,bl

Wynik:AL=95h   ;10010101b


3.Spis podstawowych instrukcji.

Tak prawde mowiac nie wiem juz o czym pisac. Podstawy asemblera juz przedstawilem
i czytajac 1 i 2 czesc juz chyba umiesz napisac maly programik.
A wiec na koniec przypomnienie wszystkich insrukcji ASM z malym opisem,
polecam wydrukowanie sobie tego opisu, przydaje sie poczatkujacym:

Oto podstawowe mnemonniki:

MOV a,b   - przenies zawartosc b do a
            Przy czym "a" moze byc rejestrem, wtedy "b" moze byc takze rejestrem
            lub adresem komorki pamieci,np:
            mov ah,byte ptr ds:[100]   - przenies setny bajt z segmentu danych
                                         do rejesru ah
            W innym przypadku to "a" moze byc adresem,a "b" rejestrem
            Nalezy pamietac,ze nie mozna przenosic do siebie zawartosci reje-
            strow segmentowych,np intsrukcja:
            mov cs,ds   - w procesie kompilacji bedzie bledem
            Totez by np. przenies zawartosc rejestru ds do cs trzeba wpierw
            przenies zawartosc ds do innego rejestru ogolnego przeznaczenia i
            dopiero jego zawartosc do cs,np.
            mov ax,cs    ;ax:=cs
            mov ds,ax    ;ds:=ax
            ;    - oznacza komentarz czyli tekst programisty nie brany pod
                   uwage przez kompilator
PUSH a     - odlozenie na wierzcholek stosu "a", gdzie "a" jest rejestrem
             16 bitowym,lub konkretna wartoscia.Zwiekszenie SP o jeden,np.
             push ax    - zapisz na wierzcholek stosu zawartosc ax
POP a      - zdjecie ze stosu "a", rozkaz zdejmuje 16 bitow ze stosu,zmniejsze-
             nie SP o jeden,np.
             pop cx  - zdjecie slowa ze stosu i jego zapis do cx
ADD a,b    - dodanie do "a" wartosci "b" np.
             add ax,cx     - ax:=ax+cx
             Uwaga operacja moze byc przeprowadzona na rejestrach o tej
             samej dlugosci jak i inne np. przenoszenia!!
SUB a,b    - odjecie od "a" wartosci "b" np.
             sub ax,cx     - ax:=ax-cx
INC a      - zwiekszenie "a" o jeden
DEC a      - zmniejszenie "a" o jeden
MUL a      - mnozenie. Jesli "a" jest 8 bitowe to:
             ax:="a"*al
             czyli wtedy bedzie to iloczym "a" i rejestru al zapisany do ax
             Jesli "a" jest rejestrem 16 bitowym to:
             dx:ax:="a"*ax
             czyli w parze rejestrow dx,ax zostanie umieszczony wynik iloczynu
             ax przez "a",gdzie dx to starsza czesc wyniku ,ax  to mniej
DIV a      - dzielenie.Jesli "a" jest 8 bitowe to:
             ax:=ax / a
             wtedy al - iloraz,ah - reszta
             Jesli "a" jest 16 bitowe to
             dx:ax:=dx:ax / a
             wtedu dx - iloraz(czesc calk. wyniku),ax - reszta
ROL a,b    - przesuniecie zawartosci "a" o 1 bit w lewo gdy "b" to 1,np.
             rol al,1
             Lub jesli "b" to CL wowczas o jego zawartosc
ROR a,b    - przesuniecie zawartosci "a" o 1 bit w prawo gdy "b" to 1,np.
             rol al,1
             Lub jesli "b" to CL wowczas o jego zawartosc
NOT a      - negacja logiczna zawartosci "a",zmiana kazdego bitu "a" na
             przeciwny
NEG a      - negacja logiczna ostatniego bitu "a" - bit znaku
AND a,b    - iloczyn logiczny "a" i "b",wynik w "a",np.
             and ax,bx
             gdy ax = 1100010b, a bx = 1011000b
             to ax = 10000000
             Iloczyn logiczny polega na tym, ze gdy wykonujemy go na dwoch
             bitach to wynikiem jest jeden gdy oby dwa bity sa jedynkami
TEST a,b   - to samo co and ale wynik nie jest nigdzie umieszczany a jedynie
             modyfikowane sa znaczniki
OR a,b     - suma logiczna "a" i "b",wynik w "a".Gdy wykonujemy or na dwoch
             bitach to w wyniku jeden gdy jeden z bitow jest jedynka
XOR a,b    - roznica arytmetyczna "a" i "b",wynik w "a".Gdy wykonujemy xor
             na dwoch bitach to w wyniku zero gdy oby dwa bity to jedynki
JMP a      - skok pod adres "a",gdzie "a" moze byc nazwa etykiety(nazwa:)
JE/JZ   a  - skok pod "a" gdy Z=1
JNE/JNZ a  - skok pod "a" gdy Z=0
JS      a  - skok pod "a" gdy S=1
JNS     a  - skok pod "a" gdy S=0
JC      a  - skok pod "a" gdy C=1
JNC     a  - skok pod "a" gdy C=0
JO      a  - skok pod "a" gdy O=1
JNO     a  - skok pod "a" gdy O=0
LOOP a     - skok pod adres "a" jesli cx jest inne od zera,jesli zostal
             wykonany skok to cx jest zmniejszane o 1.Rozkaz sluzy do
             tworzenia petli
CALL a     - skok pod adres "a" z mozliwoscia powrotu rozkazem ret.Rozkaz
             sluzy to wywolywania procedur.Rozkaz odklada na stosie odpowiednie
             dane dla powrotu totez trzeba zadbac by nie zostaly zniszczone bo
             zastosowanie rozkazu ret mozne doprowadzic do zawieszenie kompute-
             ra
             "a" moze byc tez konkretnym adresem np. segment danych i offset - 
             czyli numer bajtu w tym segmencie do ktorego skaczemy,np.
             call cs:[bx]   - skocz pod bajt o numerze bx w segmencie cs
RET        - powrot z procedury(zdjecie ze stosu odpowiednich wartosci)
INT a      - wywolanie przerwania o numerze "a",np.
             int 10h
NOP        - brak czynnosci
IN AL,DX   - przeslanie bajtu z portu o numerze w DX do AL
IN AX,DX   - przeslanie slowa z portu o numerze w DX do AX
IN AL,a    - przeslanie bajtu z portu o numerze w "a" do AL
IN AX,a    - przeslanie slowa z portu o numerze w "a" do AX
OUT DX,AL  - przeslanie slowa z AL do portu o numerze w DX
OUT DX,AX  - przeslanie slowa z AX do portu o numerze w DX
OUT a,AL   - przeslanie slowa z AL do portu o numerze w "a"(0-255)
OUT a,AX   - przeslanie slowa z AX do portu o numerze w "a"(0-255)
CLC        - C=0
STC        - C=1
CLD        - D=1(znacznik kierunku)
STD        - D=1
CLI        - I=0
STI        - I=1
MOVSB      - przekopiowanie bajtu spod DS:[SI] do bajtu ES:[DI] i zwiekszenie
             lub zmniejszenie SI i DI w zaleznosci od znacznika D
CMP a,b    - adjecie "b" od "a" bez umieszczania nigdzie wyniku,ale ustawienie
             znacznikow w zaleznosci od wyniku

4.Male wprowadzenie do Win32

A coz to takiego jest. No wiec jest to pisanie w ASM pod Windowsa 9*.
Czy jest to mozliwe, OCZYWISCIE i sam sie przekonasz daje duze mozliwosci
dla programistow.
Pamietasz jak wykorzystywalismy przerwania w DOSie do wykonywanie jakis
czynnosci (np: do wyswietlenia napisu na ekranie).
Przy pisaniu pod WIN32 NIE MOZEMY KOZYSTAC Z PRZERWAN, ale za to mamy
do dyspozycji funcje API (funcje systemowe WIN32), to one wlacnie sa
odpowiedzialne za wyswietlenie okna, zamkniecia okna, wyswietleniu
napisu, obslugi przycisku itd.
My mamy mozliwosc kozystania z nich i tutaj przydalo by sie posiadanie
rozpiski API (proponuje na http:/www.crackpltools.prv.pl ), wszystkie mi 
znane rozpiski sa po angielsku , ALE NAPRAWDE JEST TO PROSTE, wystarczy ze
poznasz kilka a bedziesz umial zrozumiec skladnie wszystkich.

Pamietasz w jaki sposob kozystalo sie z przerwan DOSa wystarczyla
instrukcjia INT i wpisanie danych do rejestrow. Pod WIN32 wyglada
to troche inacze chociasz sens naszego dzialania jest podobny
insrukcje dajemy na stos a wywolanie funkcji nasepuje po CALL
Musimy tez pamietac ze trzeba na poczatku zadeklarowac chec 
uzycia funkcji API
A WIEC:

parametry dla funkcji API skladowane sa na stosie (za pomaca PUSH)
wyglada to mniej wiecej tak:

		extrn <funkja API> ;deklaracja uzycia funkcji API
		....
		PUSH <parametr4>
		PUSH <parametr3>
		PUSH <parametr2>
		PUSH <parametr1>
		CALL <funcja API> ;wywolanie fukcji API

oczywiscie jezeli chodzi o parametry dla funcji to nie zawsze sa 4
moze bys 1 lub wcale, to zalezy od rodzaju fukcji.
Zauwazyles tesz ze parametry sa podawane na stos w odwrotnej kolejnosci,
chyba wiesz dlaczego, jak nie to przeczytaj jeszcze raz rozdzial o STOSIE.

Ogolna skladnie juz poznales, ale najlepiej wszystko zilustruje przyklad:

Zajmiemy sie funcja : MessageBox
jest odpowiedzialna za wyswietlenie okna z komuniktem i klawiszem OK

Najpierw w rozpisce API musimy odnalesc opis:

int MessageBox( 

HWND hWnd, 		// handle of owner window 
LPCTSTR lpText, 	// address of text in message box 
LPCTSTR lpCaption, 	// address of title of message box 
UINT uType 		// style of message box 

i cosz tu mamy (moze troche tumaczenia)

HWND - Jako, ze nie mamy okna ktore wywolaloby nasze okno (okno macierzyste?),
  ustawimy "hWnd" na zero.
lpText - bedzie offsetem do miejsca, gdzie nasz tekst jest przechowywany.
lpCaption - offset do tytulu okna (ang. Caption)
uType - rowniez ustawimy jako "0" also, co oznacza "normalny" MessageBox ze
  slicznym przyciskiem OK (typ: MB_OK)

A wiec wystarczy wstawic na stos w odwrotnej kolejnosci powyzszy parametry
i wywolac funkcje MessageBox.
Sprobujmy:

--------------napis.asm-----
;przykladowy programik pochodzi
;z "_masta_'s Tutorial on Win95 ASM Coding Part 0"
;tlumaczenie tego turialu mozna spotkac w necie
;tlumaczyl sachy

.386P
Locals
jumps

.Model Flat ,StdCall
mb_ok     equ 0               ;MB_OK przypisujemy wartosc "0"
hWnd      equ 0
lpText    equ offset text     ;wskaznik do tekstu
lpCaption equ offset caption  ;wskaznik do tytulu MessageBox'a


; deklaracja wszystkich urzytych funkcji API

extrn     ExitProcess     : PROC     ;procedura zakonczenia procesu
extrn     MessageBoxA     : PROC     ;procedura wyswietlenia MessageBox'a

; tutaj zaczynaja sie nasze dane

.Data
text     db "CZESC",13,10 ; pierwsza linia tekstu (+ znaki nowej linii)
         db "_masta_;sachy i ALbi pozdrawiaja kazdego, kto czyta tego tuta!",0
                                ; druga linia, zakonczona zerem (ASCIIZ :)

caption  db "Hello!",0 ; Tytul okienka, zakonczonu zerem (ACSIIZ jak w C)


; tutaj zaczyna sie nasz kod :)

.Code
Main:
                                ; pozdrowmy swiat :))

        push mb_ok              ;wartosc uType - na stos
        push lpCaption          ;wskaznik do tytulu okna - na stos
        push lpText             ;wskaznik do naszego tekstu - ma stos
        push hWnd               ;'uchwyt' okna nadrzednego - na stos
        call MessageBoxA        ;wywolanie "MessageBoxA"
        CALL ExitProcess        ;zakonczenie programu

End Main                        ;koniec kodu, Main jest punktem rozpoczecia
                                ;programu
-------------------------------------------------
kompilacja:
tasm32 /mx /m3 /z /q napis
tlink32 -x /Tpe /aa /c napis,napis,, import32.lib
--------------------------------------------------

Jak widzisz nie jest to takie trudne, sa male roznice w podejsciu do 
temtu w programowaniu, ale za to mamy bardzo duze mozliwosci.
Proponuje zapoznac sie z rozpiska API lub przesledzic kod jakiegos
malego programiku pod WIN32.

=========================================================================
NO KONIEC

jeszcze raz podziekowania dla:

	grupy CRACKPL - wiekszosc wiedzy czerpalem z tego zrodla
	dla ludzi z #crackpl - za cierpliwosc w odpowiadaniu na pytania
	Piotr Sokolowski - spis mnemonikow ASM
	sachy - Win32 /jego osobiste tumaczenie turu _masta_/

	kilku gosciom z klatki ktorzy przeczytali ten tekst
	(a bylo to trudne zadanie aby ich do tego zmusic)
	a nie mieli pojecia co to asembler (oni tylko gierki)
	a teraz umieja cos nieco napisac w ASM
