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

				----------------------
				ASEMBLER STRORY PART 2
				----------------------


Witam wszytkich jeszcze raz.
Teraz przejdziemy do sedna sprzwy w tej czesci poznamy podstawowe mnemoniki(komedy)
asemblera.Rozumiem ze wiesz dokladnie co to rejestr,port,flagi,stos itd..
umiesz tez skompilowac program (beda przyklady) i mniejwiecej wiesz co to przerwania.
OK

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!!!

To zaczynamy...

-------------------------------------
SPIS TRESCI

1.Instrukcja MOV
2.Instrukcje obslugi Stosu (PUSH i POP)
3.Deklaracja danych
4.Instrukcja JMP
5.Instrukcje CALL i RET
6.Instrukcje CMP i J**
7.Dzialania matematyczne
8.Petle

1. Instrukcja MOV

to jest chyba podstawowa instrukcja w ASM.

skladnia:	mov <gdzie>,<zrodlo>

Kopiuje jedna zawartosc do drugiej(mozna powiedziec przenosi),tzw ze <zrodla> do <gdzie>
a wiec
	
	MOV EDS, EAX    - przeniesienie pomiedzy dwoma rejestrami 32-bitowymi
	MOV CL, 39      - przeniesienie stalej do rejestru
	MOV ES:[BX],AX  - zmiana przypisania segmentu
	
Kilka uwag :

Nie mozna bezposrednio przeniesc danych pomiedzy komorkami
pamieci. Musimy dane najpier przeniesc dane do rejestru ogolnego
przeznaczenia a pozniej z rejestru do przeznaczenia w pamieci.
Przyklad, mamy dwie zmienne w pamieci np. TYLEK i ZADEK i aby
przenies wartosc z jednej do drugiej to

MOV AX,TYLEK
MOV ZADEK,AX

Nie mozna zaladowac bezposrednio stalej do rejestru segmentu,
musimy ja przenies przez rejestr ogolnego przeznaczenia.

MOV AX, ADRES_DS
MOV DS, AX

Podobnie nie mozemy przenies bezposrednio zawartosci jednego
rejestru segmentu do drugiego, podobnie musimy przez rejestr
ogolnego przeznaczenia.

MOV AX, ES
MOV DS, AX

Nie mozna uzyc rejestru CS jaki argumentu przeznaczenia w
instrukcji MOV

Pamietajmu ze przy tej instrukcji <zrodlo> pozostaje bez zmian.

2.Instrukcje obslugi Stosu (PUSH i POP)

Stos omwilimy ju wczeniej - ju wwczas sygnalizowaem istnienie dwch instrukcji,
ktre su do obsugi stosu - PUSH i POP. Push - powoduje wrzucenie wartoci lub 
zawartoci rejestru na stos a POP - pobranie wartoci ze stosu i wrzucenie jej do rejestru. 

Skadnia: 
PUSH REJ16 
PUSH WAR16 
POP REJ16 

"REJ16" i "WAR16" - oznaczaj odpowiednio rejestr i warto 16-bitow - tzn. nie mona
wrzuca ani pobiera ze stosu wartoci 8-bitowych np. AL, AH...; inaczej: 
instrukcje PUSH i POP operuj jedynie na sowach czyli danych 2-bajtowych. 

Instrukcja PUSHA i POPA powoduj wrzucenie na stos wszystkich rejestrw - nie trzeba wywoywa kilkakrotnie instrukcji PUSH i POP - wpywa to wic na skrucenie programu. 
Niestety - instrukcje te nie s dostpne we wszystkich wersjach procesora, czyli ich uywanie w programie wpywa na kompatybilno. 

Skadnia: 
PUSHA 
POPA 

Ostatni ju par instrukcji jest PUSHF i POPF, ktrych dziaanie jest identyczne 
do PUSHA i POPA, lecz ogranicza si wycznie do flag - push flags... 

Skadnia: 
PUSHF 
POPF 

3.Instrukcja INT

Jak ju o tym pisaem omawiajc istot przerwa, INT jest instrukcj uruchamiajc 
przerwanie programowe. 

Skadnia:
	INT numer_przerwania 

Numer_przerwania to liczba z zakresu 0-255, musi by podana konkretna warto; 
nie mona uywa rejestrw np. 
				INT AH 
spowoduje komunikat o bdzie. 

Majc dostp do listy funkcji choby nawet podstawowych przerwa - int 21H, int 16h, 
int 10H - otrzymujesz spor gam gotowych procedur, ktre bdziesz mg wykorzysta 
w swoich programach bez potrzeby ich (procedur) doczania do kodu programu. 

Polega to na tym, e odpowiednie ustawienie rejestrw (gwnie ax, bx...) i wywoanie
danego przerwania powoduje wykonanie okrelonej procedury lub funkcji - jeli jest to
funkcja, to po powrocie z danego przerwania odpowiednie rejestry bd miay 
odpowiednie wartoci - np: 

Przerwanie 21H funkcja 2CH - pobierz czas 

	AH = 2CH 

		Przerwanie zwraca: 
		CH = godzina (0-23) 
		CL = minuta (0-59) 
		DH = sekunda (0-59) 
		DL = setne sekundy (0-99) 

Co oznacza ten zapis? 
Znaczy to tyle, e aby otrzyma czas korzystajc z usugi przerwania 21H, naley: 
1. Ustawi rejestr AH na warto 2CH (MOV AH,2CH) 
2. Wywoa przerwanie 21H (INT 21H). 
I ju - rejestry CH, CL, DH i DL zawiera bd aktualny czas. 

Innym przykadem - do czsto uywanym - jest funkcja 4CH przerwania 21H. 

Przerwanie 21H funkcja 4CH - zakocz program i zwr kod errorlevel 

AH=4CH 
AL = kod wyjcia (errorlevel dla plikw .bat) 

Nie zwraca nic. 

Tutaj postpujemy analogicznie jak w poprzednim przypadku - ustawiamy rejestry 
AH i AL a nastpnie wywoujemy przerwanie. 
Prosta demonstracja funkcji int 21H/4CH 
-------------
.model tiny
.code
org 100h
start:
;Poczatek programu
mov ah,4ch;Numer funkcji w AH
mov al,01h ;Wartosc zwracana w errorlevel po opuszczeniu programu
int 21h;Przerwanie dos
;Jedna z czesciej uzywanych funkcji - opuszczenie programu i zwrocenie
;do systemu numeru bledu.
;
;W pascalu jej odpowiednikiem jest halt(nrbledu).
end start
-------------


Znajc choby te dwie funkcje - mona si pokusi o napisanie prostego programu,
ktry mona bdzie uywa w plikach wsadowych (.bat) - program, ktry po 
uruchomieniu w errorlevel zwrci aktualn godzin. 
Na pewno ju sam potrafisz napisa taki program, jeli jednak nie, to tutaj 
masz przygotowany ten programik oraz prosty 
plik wsadowy, ktry pozwoli przetestowa dziaanie programu. 

plik czaserl.asm-----------

.model tiny
.code
org 100h
start:
MOV AH,2CH
INT 21H
MOV AL,CH
MOV AH,4CH
INT 21H
end start


koniec pliku------------

skompiluj ten programik (do czaserl.com)
i napisz jeszcze jeden czas.bat

plik czas.bat-----------

@echo off
rem pora dnia - demo uzycia programu czaserl
czaserl
if errorlevel 21 goto noc
if errorlevel 19 goto wieczor
if errorlevel 13 goto popoludnie
if errorlevel 12 goto poludnie
if errorlevel 6 goto poranek
:noc
echo Jest noc
goto koniec

:wieczor
echo Jest wieczor
goto koniec

:popoludnie
echo Jest popoludnie
goto koniec

:poranek
echo Jest poranek
:koniec

koniec-----------------

teraz uruchom czas.bat

Ostatni spraw, o ktrej warto wiedzie jest oczywista moliwo uruchomienia dowolnego
przerwania - bez parametrw.Jak wiesz, przerwanie 05H jest przerwaniem drukowania 
ekranu - uruchamianym po naciniciu . 
Co by si jednak stao, gdyby uruchomi to przerwanie przy uyciu instrukcji INT? 
Sprubj!!

Uwaga. Jeli zamierzasz napisa jakikolwiek program sam, to pamitaj 
- po pierwsze o strukturze programu, po drugie - nigdy nie zapomnij uy funkcji 
  wyjcia z programu. 

3.Deklaracja danych.

Sama deklaracja danych jest bardzo prosta - podobnie jak w pascalu moemy
nada zadeklarowanej danej nazw; nie wyrnia si tu jednak typw danych
tak zoonych jak w pascalu - istniej generalnie tylko 3: byte (bajt), 
word (sowo - 2 bajty) i double word (podwjne sowo - 4 bajty). 

Istnieje te moliwo deklaracji acucha znakw - tekstu, co przyda si 
nam za chwil, lub obszaru dowolnej dugoci wypenionego jak okrelon
wartoci - tego sposobu uywa si np. do zadeklarowania "bufora", ktry 
bdzie modyfikowany w trakcie dziaania programu. 

Przyklad deklaracji zmnmiennych:

------------------
		.model tiny
		.code
		org 100h
		start:
		mov ax,4c00h
		int 21h
		;wyjscie.asm

		dane1 db 0
		;1 bajt
		dane2 dw 0
		;2 bajty - 1 slowo (word)
		dane3 dd 0
		;4 bajty - double word (podwojne slowo)

		;przyklady deklaracji lancuchow
		dane4 db 'napis 1 - przyklad deklaracji lancucha...'


		dane5 db 124 dup('x')
		;taki zapis powoduje wyprodukowanie w kodzie po kompilacji obszaru 124
		;bajtow, wypelnionych jakas wartoscia.
		;Dotyczy takze dw i dd

		end start
-------------------

Skoro ju umiemy deklarowa dane acuchowe, moemy ponownie otworzy spis funkcji
przerwania 21H i sprbowa naszych si piszc program bazujcy na funkcji 09H tego 
przerwania. 

Przerwanie 21H, funkcja 09H - wywietlenie napisu: 
AH = 09H DS:DX = wskanik pierwszego znaku napisu, 
Przerwanie nie zwraca nic. 
Napis musi by zakoczony znakiem '$'. 

Prawie wszystko jasne, jedyn zagadk stanowi swko "wskanik" w opisie tej funkcji. 
Wbrew pozorom jest to proste - DS musi by ustawione na segment pamici, w ktrym 
znajduje si nasz napis a DX na przesunicie tego napisu w segmencie. 

Kolejn cech programw .com, ktra przychodzi nam tu z pomoc jest fakt, e w 
tych programach CS = DS - kod programu jest zapisany w tym samym segmencie co dane
programu i ju przy adowaniu pliku .com do pamici CS jest ustawiane na t sam 
warto co DS. 
Pozostaje wic problem fatalnego przesunicia - tutaj z kolei przyda si funkcja 
wewntrzna Turbo Assemblera - OFFSET. Funkcja ta zwraca przesunicie danej, ktrej
nazw podamy w nawiasach, tak, e najpierw jest obliczane przesunicie tej danej 
po kompilacji i ta warto jest podstawiana w miejscu, gdzie wywoano funkcj - np: 
MOV DX, OFFSET(NAPIS) spowoduje, e podczas kompilacji zostanie obliczone 
przesunicie danej napis i wyliczona warto zostanie podstawiona za 
offset - przy dekompilacji lub debugowaniu programu w miejscu naszej instrukcji byaby: 
MOV DX,121H 
Oczywicie przy zaoeniu, e akurat 121H to przesunicie zmiennej napis. 
Kto mgby stwierdzi, e zamiast offset(napis) moglimy z gry wpisa
121H - miaby racj tzn. program prawdopodobnie by zadziaa, ale po co 
trudzi si skomplikowanymi wyliczeniami, skoro po pierwsze - kompilator zrobi 
to szybciej i dokadniej a po drugie jeli zmienimy co w programie, to caa 
matematyka na nic - wszystko trzebaby zrobi od nowa. 

Do tych teoretycznych rozwaa - przystpmy do napisania programu... 

--------------------
	.model tiny
	.code
	org 100h
	start:
	;Poczatek programu
	mov ah,09h
	mov dx,offset napis
	;DX=Przesuniecie napisu w segmencie cs
	int 21h
	;Wykonaj

	mov ax,4c00h
	;Wyjscie - zob. wyjscie.asm
	int 21h
	napis db 'Napis, ktory zostanie wypisany ',13,10,'$'
	;Napis _musi_ byc zakonczony znakiem $
	;13,10 to kod CR i LF - przejscie do nowej linii
	end start
------------------
compilacja tasm *.asm
	   tlink *.obj /t
przypominam ze tekst po ';' jest pomijany przy compilacji
------------------

Eksperymentujcie - zmieniajc napis (moe on by na prawd dugi), ale trzeba 
pamita, e musi koczy si znaczkiem $. 

4.Instrukcja JMP

Instrukcja jmp jest pprosta - zarwno w skadni jak i dziaaniu - powoduje 
bezwarunkowy przeskok do innej czci programu - analogicznie jak "goto" w 
pascalu czy basicu. 

skadnia: 
		JMP <etykieta> 


Etykieta - to podobnie jak w pascalu - cig znakw zakoczony dwukropkiem - 
identyfikujcy miejsce w programie np.: "Start:", "Petla:" itp. 

Instrukcji jmp uywa si w zasadzie w poczeniu z instrukcjami skoku warunkowego, 
ale ma oczywicie rwnie inne powane zastosowania:). 
Czasem mona si spotka z instrukcjami "JMP FAR" czy "JMP SHORT" - s to odmiany 
jmp nie rnice si skadni - rnica polega na tym, e "FAR" (daleki) 
odnosi si do skokw duszych ni +-128 bajtw a "SHORT" (krtki) - dotyczy 
skokw nie wikszych ni +-128 bajtw. 
Sygnalizuj to jednak wycznie dla "dopenienia" informacji o skokach - 
te szczegy dla nas - pocztkujcych programistw - nie maj adnego 
istotnego znaczenia. 

Przyklad:
--------------------
	.model tiny
	.code
	org 100h
	start:
       
	jmp etyk1
	;skok do etykiety "etyk1"
	mov ax,5238h
	mov bx,4321h
	mov cx,100h
	mov ax,4c00h
	int 21h
	;ta czesc kodu nie zostanie wykonana
	mov dx,0100h
	
	etyk1:
	jmp etyk2
	mov ax,4c00h
	
	etyk2:
	jmp etyk4
	mov ah,09h
	;znowu "jalowy" kod
	int 21h
	
	etyk3:
	mov ax,0c0c0h
	jmp wystarczy
	mov dx,0d0d0h
	
	etyk4:
	mov ax,4c00h
	jmp etyk3
	;kto powiedzial, ze nie mozna "skakac" wstecz?
	mov ah,09h
	
	wystarczy:
	mov ax,4c00h
	int 21h

	end start

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

Chyba ten przyklad dokladnie ilustroje problematyke skokow bezwarunkowych w ASM.

5.Instrukcje CALL i RET

Jak wskazuje na to temat instrukcje CALL (woaj) i RET (return - powrt) su 
do tworzenia podprocedur:) - czci programu, ktre bd uywane czciej ni raz - 
tak jak procedury np. w pascalu. 

Poniewa wierz w moc przykadw - znowu nie bd si zbyt dugo rozwodzi nad 
tematem... A wic do rzeczy: 


Skadnia: 
		CALL <etykieta> 
		RET


CALL zapamituje na stosie adres nastpnej instrukcji programu a nastpnie 
przeskakuje do etykiety "etykieta" tak, jak to robia instrukcja JMP. 
Po napotkaniu instrukcji RET procesor pobiera ze stosu adres zapamitany tam 
przez CALL i przeskakuje pod ten wanie adres - czyli "wraca" do programu 
nadrzdnego. 

Schemat uycia instrukcji CALL i RET wyglda wic nastpujco: 

Nazwa_procedury: ; etykieta okrelajca nazw procedury 
;Kod podprocedury 
;... 
;... 
;... 
RET ; Powrt do programu nadrzdnego. 


Gdzie w programie natomiast - naley uy nastpujcego wywoania: 

CALL nazwa_procedury 

To tak dla wszystkich lubicych schematy i teori. 
Dla zwolennikw twardej i niekiedy brutalnej praktyki - niepraktyczny
(jeli chodzi o uycie) programik demonstracyjny procedur i podprocedur. 

--------------------------
	.model tiny
	.code
	org 100h
	start:
	;Poczatek programu
	jmp begin
	;przeskakujemy do etykiety begin, 
	;tutaj zapiszemy procedury, ktore uzyjemy pozniej
	napis: ;procedure napis;
	;Parametry do procedury - dx=ofset napisu
	mov ah,09h
	int 21h
	;Zob. napis.asm
	ret
	;Powrot do procesu nadrzednego
	
	wyjscie: ;Procedure wyjscie;
	mov ax,4c00h
	int 21h
	ret

	;Umiescmy tu tez nasze dane:
	halo db 'Czesc uzytkowniku ',13,10,'$'
	nap1 db 'Napis pierwszy',13,10,'$'
	nap2 db 'Napis drugi',13,10,'$'
	
	;procedury wypisujace napisy

	witaj:
	mov dx,offset(halo)
	call napis
	ret
	
	napis1:
	mov dx,offset(nap1)
	call napis
	ret

	napis2:
	mov dx,offset(nap2)
	call napis
	ret
	dozob db 'Do zobaczenia ',13,10,'$'

	begin:
	;Poczatek wlasciwy
	call witaj
	call napis1
	call napis2
	call napis1
	;znowu napis 1
	;Oczywiscie procedury napis mozna uzyc w "programie glownym":
	mov dx,offset(dozob)
	call napis
	call wyjscie

	end start
-------------------------

6.Instrukcja CMP i J**

Rzecz, ktr za chwil omwi jest prawie tak samo a moe nawet bardziej wana
i przydatna jak omawiane ju przerwania. Dotychczas ani razu nie mwilimy o 
instrukcjach warunkowych (if .. then) ani o sposobie porwnywania dwch wartoci. 

Do porwnania dwch wartoci suy instrukcja CMP (compare - porwnaj), ktrej 
skadnia jest nastpujca: 

				CMP A, B 

A i B to dwie dowolne wartoci, ktre porwnujemy. Wykonanie instrukcji CMP 
powoduje ustawienie odpowiednich flag procesora (OF, SF, ZF), a to wanie na
tej podstawie s wykonywane instrukcje skoku, o ktrych za chwil - tematu 
ktre flagi s kiedy ustawiane i dlaczego tak a nie inaczej - nie chciabym
na razie zgbia bo moe to tylko zamiesza i nie wnie nic do sprawy... 

Na etapie pocztkowym nauki assemblera wystarczy wiedzie, e jeli chcemy 
wykona skok warunkowy ("If a>4 then" itp.) to najpierw wykonujemy 
instrukcj CMP A,4 a nastpnie jedn z poniszych... 

Skadnia instrukcji J**: 
				J** <etykieta>

"Etykieta" to oczywicie (tak jak w przypadku JMP, CALL) nazwa etykiety, 
do ktrej program przeskoczy jeli... No wanie. 
Przydatniejszych instrukcji J** jest kilka, ale s one nazwane wg pewnych 
regu, ktrych znajomo moe zaoszczdzi sporo wkuwania wic w efekcie "nie 
taki diabe straszny". Pierwsz liter tych instrukcji stanowi 
zawsze J (jump if - skok jeli), pniej moe wystpi N (not - nie) 
a na kocu A (above - ponad), lub E (equal - rwne), lub B (below - poniej). 
Wemy na przykad rwno - "J"+"E" czyli JE. W ten sposb moemy te 
zapisa nie-rwno piszc JNE... i tak dalej. 

Jednej rzeczy naley si jednak nauczy - jak ju miae okazj zauway z 
tym assemblerem to tak nie zawsze i nie do koca "po ludzku" bywa, wic 
jeli mielibymy instrukcje: 
				CMP A,B 
				JA et_wieksze 

to kto mgby zapyta, czy skok nastpi jeli A > B, czy jeli B > A? 
Kto inny sprawdziby to dowiadczalnie, ale ja - z gry wyjaniam. 
Tu akurat jest normalnie tzn. w powyszym przykadzie instrukcja JA 
wykona skok jeli A > B - piszc dla wyobrani - A above B. 

Myl, e to w miar bezbolenie wyjaniem - Jak zapisa >=? 
W assemblerze istnieje instrukcja JAE (Above or Equal), ktrej oczywicie 
mona uywa (istnieje te JBE (below or equal)) - nie s to jednak 
instrukcje "pierwszej potrzeby" zwaszcza, gdy kto nie chce si zbyt 
wiele uczy (a kto chce?:))), bo tak "na chopski rozum" sprawa jest prosta: 
Wiksze lub rwne znaczy tyle samo co "nie mniejsze" a wic - 
JNB... I mamy to samo przy uyciu naszego pierwotnego szablonu bez adnych JAE.... 

Przegldajc zestaw instrukcji przerwania 21H mona natrafi 
(w opisie np. otwierania pliku) na zapis, e funkcja zwraca: 
	CF=0 - wykonano bez bdw, 
	CF = 1 - wystpi bd (nr bdu jest w AX). 

W praktyce wic chodzi o to, eby sprawdzi czy dana flaga jest czy nie jest 
aktywna... a pisaem wczeniej, e wanie J** bazuje na flagach czym si nie
naley przejmowa.
 Jeli wic porwnujemy dwie wartoci, to istotnie nie ma to znaczenia, ale jeli 
interesuje nas stan jakiej konkretnej flagi, to istnieje kilka uytecznych 
instrukcji J** przeznaczonych wanie do tego. S to: 

JC - skok gdy CF = 1; 
JO - skok, gdy OF = 1; 
JP - skok, gdy PF =1; 
JS - skok, gdy SF = 1; 
JZ - skok, gdy ZF = 1. 

Rwnie tutaj stosuje si niemiertelna zasada not, czyli mona stosowa zapis 
np. JNC, ktry oznacza, e CF nie jest ustawiona - CF = 0; tyczy si to oczywicie
pozostaych flag take (JNO, JNP, JNS i JNZ). 

Wielokrotnie pisaem powyej, e jest wiele... e si nie ma co przejmowa... 
i wogle tak, e spokojnie monaby mi zarzuci herezj i nierzetelno. 
Przewidujc moliwo takiej sytuacji a jednoczenie chcc unikn zawiego i 
pokrtnego tumaczenia, przygotowaem (dla zapalecw cho i "leniwym" 
lektura nie zaszkodzi) peny (mam nadziej) zestaw instrukcji J**, ktry jednak 
(zastrzegam i ostrzegam) pochodzi z ksiki - wikszoci tych instrukcji wogle 
nie uywaem i nie zamierzam:)). 

J - jump if - skok jeli 
N - not - nie 
A - above - powyej 
G - greater - wiksze 
E - equal - rwne 
Z - zero flag - ZF 
B - below - poniej 
L - less - mniej 
O - Overflow flag - OF 
P - parity flag - PF 
S - sign flag - SF 

Podane zestawienia dla A i B obrazujce matematycznie kiedy warunek jest 
speniony - s przygotowane przy zaoeniu, e wykonujemy instrukcj 
CMP A, B 
- nie odwrotnie (dla CMP B,A wszystkie warunki bd odwrcone). 

JA (JNBE) 
A > B (CF = 0 lub ZF = 0) 

JAE (JNB) 
A >= B (CF = 0) 

JB (JNAE) 
A < B (CF = 1) 

JBE (JNA) 
A <= B (CF = 1 LUB ZF = 1) 

JE (JZ) 
A = B (ZF = 1) 

JNE (JNZ) 
A <> B (ZF = 0) 

JG (JNLE) 
A > B (ZF = 0 lub OF = SF) 

JGE (JNL) 
A >= B (SF = OF) 

JL (JNGE) 
A < B (SF <> OF) 

JLE (JNG) 
A <= B (ZF = 1 lub SF <> OF) 

JC 
(CF = 1) 

JNC 
(CF = 0) 

JO 
(OF = 1) 

JNO 
(OF = 0) 

JP (JPE) 
(PF = 1) 

JNP 
(PF = 0) 

JS 
(SF = 1) 

JNS 
(SF = 0) 

Tutaj musze zaznaczy, e sporzdzajc niniejsze zestawienie opieraem si na
rnych rdach - nie mam wogle dowiadczenia z wikszoci tych rzadziej 
uywanych - moe si wic okaza, e informacje te nie s do koca cise.

7.Dzialania matematyczne.

Po tym wszystkim, co ju dotychczas zrobilimy, to, czym zajmiemy si teraz 
jest proste jak ... si za chwil przekonasz. 
Nie zwlekajc wic ni chwili przystpmy do rzeczy. 

INC i DEC 
S to instrukcje analogiczne jak w Pascalu, z maym wszake wyjtkiem, 
ale o tym za moment - powoduj zwikszenie lub zmniejszenie jakiej wartoci. 

Skadnia: 
		INC A 
		DEC A 

No wic caa rnica polega na tym, e - jak wida - nie ma tu drugiego parametru,
ktry okrelaby o ile ma by zwikszona lub zmniejszona dana warto. Parametru 
tego nie ma, gdy zawsze jest ona zmniejszana/zwikszana o 1 - sownie jeden. 
Rozwiewajc wic resztki wtpliwoci wszystkich, ktrzy takie wtpliwoci jeszcze 
zachowali powiem, e INC zwiksza a DEC zmniejsza dan warto... 
Przykadowo, jeli w AX mamy warto 03H, to wykonanie instrukcji 
		INC AX 
zwikszy AX o 1 - AX bdzie si rwna 04H. Jeli wic w tym stanie rzeczy 
wykonamy instrukcj 
		DEC AX 
to warto AX zostanie zmniejszona o 1 - z wartoci 04H na 03H. 

Dodawanie i odejmowanie 

Do tych operacji mona oczywicie uywa DEC i INC, ale - oczywicie - byoby 
prawie nie do pomylenia, e Assembler nie udostpnia adnej instrukcji 
umoliwiajcej wykonanie powyszych dziaa "za jednym zamachem" tzn. bez 
koniecznoci zmieniania wartoci o 1. Instrukcje, ktre umoliwiaj wykonanie 
dodawania lub odejmowania to ADD (dodaj) i SUB (substract - odejmij). 

Skadnia: 
		ADD A, B 
		SUB A, B 

Wykonanie powyszych instrukcji powoduje dodanie (lub odjcie w przypadku SUB) 
wartoci A i B i wrzucenie wyniku do A - np.: Jeli AX=5 i wykonamy 
		ADD AX, 08H 
to procesor najpierw doda 5+8 a nastpnie wrzuci wynik do aX - po wykonaniu 
powyszego polecenia AX bdzie rwne 13 (dziesitnie) czyli 0DH. Analogicznie - 
wykonanie w tym stanie rzeczy instrukcji 
		SUB AX,3 
spowoduje odjcie trjki od aktualnej wartoci AX i wrzucenie wyniku 
do AX (13 - 3 =10) - AX=10D czyli 0AH. 

Mnoenie 

Tutaj sprawa nie jest ju tak prosta jak w przypadku dodawania i odejmowania, d
latego te mnoenie i dzielenie zostan omwione oddzielnie. 
Do mnoenia suy w Assemblerze instrukcja MUL (multiply - mn). 

Skadnia: 
		MUL A 

Niewtpliwie wymaga to pewnych wyjanie - wyjaniam wic: MUL powoduje 
pomnoenie wartoci A razy zawarto rejestru AX, lecz sprawa wyglda nieco 
inaczej, gdy A jest wartoci typu word (sowo - 2 bajty) lub byte (bajt).
Gdy wic A jest to 1 bajt, wwczas wykonywane jest mnoenie a*AL (przypomn,
e AL jest to modszy bajt rejestru AX) i wynik mnoenia zostaje wrzucany do AX.
Zamy, e AL=2 a BL=3 - wwczas wykonanie instrukcji 
		MUL BL 
powoduje wymnoenie 2*3 i wrzucenie wyniku do AX - AX=6. 

Jeli jednak A jest wartoci dwubajtow, to A jest mnoone razy AX a wynik 
zostaje wrzucany do rejestrw DX:AX tzn. DX zawiera 2 starsze a AX modsze 
bajty - np:. Jeli AX = 0FFFFH (65535) i BX=0FFFFH (65535 rwnie), to wykonanie 
MUL BX wymnoy BX*AX a wynik (w tym przypadku czterobajtowy 0FFFFFFFFH
czyli 4294836225D) znajdzie si w DX (2 bajty) i AX (rwnie 2 bajty). 

Dzielenie 

Instrukcj dzielc jest w Assemblerze DIV (divide - dziel). 

Skadnia: 
		DIV A 

Tutaj znowu - jak w przypadku mnoenia - ma znaczenie czy A jest bajtem 
(np. BH, BL), czy sowem (NP. BX). 

Jeli A jest bajtem, AX jest dzielony przez A; iloraz zostaje wrzucony do AL,
reszta do AH. Jeli wic AL zawiera 10D (0AH), BH=3, to po DIV BH 
AL=3, AH=1 - bo oczywicie 10/3 =3 i reszty 1. 

Gdy A jest sowem (2 bajty), DX:AX zostaje podzielony przez A; po dzieleniu 
AX zawiera iloraz a DX reszt z dzielenia - np.: 
Jeli - posugujc si analogicznym przykadem co przy mnoeniu - 
ustawimy DX=0FFFFH, AX=0FFFFH (dzielna =0FFFFFFFFH) i BX=0FFFFH (dzielnik), to 
DIV BX ustawi AX=0FFFFH (iloraz) BX=0000H (reszta). 

No - do tego sporo:)) - przydaby si jaki ilustrujcy wszystko przykadzik,
ale - obawiam si, e wszyscy, ktrzy na to licz - zawiod si; nie mam adnego 
sensownego pomysu a bezsensowne przykady umieszczaem na bieco przy omawianiu 
kadego dziaania. 

8.Instrukcja TEST 

Instrukcja TEST wykonuje operacje AND na dwoch argumentach i w oparciu o ten 
wynik ustawiane sa odpowiednie flagi.

Nalezalo by wiec przeanalizowac czym jest operacja mnozenia
logicznego AND. Dziala on na argumentach rozmiaru bajt lub slowo
(ale nie na ich zwyklej postaci a postaci binarnej, bo dziala
dokladnie na bitach tych liczb).

Z matematyki wiemy ze 
			0 AND 0 = 0 
			0 AND 1 = 0
			1 AND 0 = 0 
			1 AND 1 = 1

a wiec operacja daje wynik jeden wtedy i tylko wtedy gdy
oba bity rowne sa jeden.

Wezmy teraz TEST EAX, EAX. Zalozmy ze 
		EAX=0 czyli 00000000 AND 00000000 = 00000000
czyli na kazdej pozycji bedzie 0 i wtedy ustawiana jest flaga zerowa Z.
Natomiast przy kazdej innej wartosci np.
		 00000011 AND 00000011 da nam 00000011 
i wtedy jezeli gdziekolwiek na dowolnej pozycji wystapia w obu argumentach 1 to
flaga Z nie jest ustawiana.

Daje nam to mozliwosc sprawdzenia czy np. EAX jest 0 czy jakas inna
wartoscia, gdzy tylko porownanie dwoch TYCH SAMYCH liczb o wartosci
0 da nam 0 i ustawi flage. Operacja AND na kazdych dwoch TAKICH
SAMYCH roznych od zera nie ustawi flagi zerowej bo zawsze gdzies
bedzie 1 w bitach.

Dlatego tez w programach czesto spotykane instrukcje TEST EAX,EAX a
pozniej JZ adres lub JNZ adres.

9.Petle

" LOOP, LOOPE, LOOPZ, LOOPNE, LOOPNZ, JCXZ "


Jak pisaem poprzednio, przy naszych obecnych umiejtnociach spokojnie 
mona zrobi ptl "for .. to ..."

--------------
.model tiny
.code
org 100h
start:
jmp pocz
;Dane i procedury
crlf db 13,10,'$'
;Skorzystamy z procedur, ktore napisalismy wczesniej
;w celu wypisania wartosci CX na ekran
pznak:
push ax
push bx
mov ah,0eh
mov bx,0
int 10h
pop bx
pop ax
ret

piszCX:
;OK, do naszych celow przerobimy tak, aby wypisywac na ekran mlodszy
;bajt rejestru CX
push ax
push bx
mov ax,cx
mov bh,10
div bh
add al,'0'
call pznak
mov al,ah
add al,'0'
call pznak
pop bx
pop ax
ret

pocz:
;petla typu for cx=3 to 10
mov cx,3
ptl:
call piszcx
;pokaz aktualna wartosc cx na ekranie
;wykonaj inne dzialania "w petli"
;na przyklad - przejdz do nowej linii
mov ah,09h
mov dx,offset(crlf)
int 21h
;no i co? Trzaby sprawdzic czy juz koniec, lub zwiekszyc cx
cmp cx,10
je koniecptl
;koniec petli
inc cx
;zwiekszamy tymczasem cx
jmp ptl
;przeskakujemy na poczatek petli
koniecptl:
;koniec petli - koniec programu?
mov ax,4c00h
int 21h


end start
-----------------------------
Oczywicie - ptla dziaa co mona bez trudu stwierdzi - poprawnie, 
lecz to jest pretekstem do wprowadzenia wanie instrukcji LOOP. 

Skadnia: 
		LOOP <ETYKIETA>


Tu warto od razu wyjani, e loop - z angielskiego oczywicie - znaczy "ptla". 
No ale co waciwie robi LOOP? Mwic krtko - zaledwie dwie rzeczy:
Po pierwsze - zmniejsza warto CX o jeden (DEC CX), po drugie - jeli CX 
jest wiksze 0 powoduje bezwarunkowy przeskok do "ETYKIETA". 
Jeli chcielibymy powiedzie to jzykiem procesora - LOOP ETYKIETA jest 
skrutem poniszych komend: 
		DEC CX 
		JCXZ ETYKIETA 

JCXZ? No wanie - o tym nie mwilimy... JCXZ jest instrukcj skoku warunkowego 
- Jump if CX equal to Zero - skok jeli CX=0... nie mwilimy o tym wczeniej, 
gdy na dobr spraw bez tego te monaby si obej - wykonanie instrukcji: 
CMP CX,0 JE ETYKIETA robi to samo co JCXZ ETYKIETA... 
Mam nadziej, e wybaczycie t drobn dygresj - wracamy do LOOp. 
Nie trzeba tu filozofa by stwierdzi, e LOOP umoliwia tylko budow ptli 
typu "downto" czy - jak w basicu - "step -1" - a po ludzku ptli, w ktrej 
licznik maleje a nie ronie. 
Oczywicie jest to prawda, ale prawd jest te, e nie warto si mczy 
wykonywaniem powyej pokazanej ptli, gdy mona to rozwiza LOOPem. 
Poniewa postraszyem w nagwku p tuzinem instrukcji, najwyszy czas zakoczy
ten przydugi opis LOOP - za podsumowanie musi wystarczy przykadowy programik. 
----------------------
.model tiny
.code
org 100h
start:
jmp pocz
;Skorzystamy z procedur z poprzedniej petli - zob. ptldemo.asm
;Dane i procedury
crlf db 13,10,'$'
;Skorzystamy z procedur, ktore napisalismy wczesniej
;w celu wypisania wartosci CX na ekran
;Jesli nie znasz wczesniejszego programu, obejrzyj go - dataczas.asm
pznak:
push ax
push bx
mov ah,0eh
mov bx,0
int 10h
pop bx
pop ax
ret

piszCX:
;OK, do naszych celow przerobimy tak, aby wypisywac na ekran mlodszy
;bajt rejestru CX
push ax
push bx
mov ax,cx
mov bh,10
div bh
add al,'0'
call pznak
mov al,ah
add al,'0'
call pznak
pop bx
pop ax
ret

pocz:
;petla typu 
;for cx=10 downto 1
;lub w basicu
;for cx=10 to 1 step -1
mov cx,10
ptl:
call piszcx
;pokaz aktualna wartosc cx na ekranie
;wykonaj inne dzialania "w petli"
;na przyklad - przejdz do nowej linii
mov ah,09h
mov dx,offset(crlf)
int 21h
loop ptl
;zrobi za nas cale porownanie i zmniejszanie
;i sama zakonczy sie powtarzac, gdy CX osiagnie 0
;koniec petli - koniec programu?
mov ax,4c00h
int 21h
end start
------------------------------

LOOPE/LOPZ, LOOPNE/LOOPNZ 

Instrukcje LOOP?? maj - jak nie trudno si domyle - co wsplnego z 
instrukcj LOOP. Tym czym jest choby uycie. 

Skadnia: 
	LOOPE ETYKIETA LOOPZ ETYKIETA LOOPNE ETYKIETA LOOPNZ ETYKIETA 

Nie trudno si te domyle, e LOOP?? dotycz w jaki sposb instrukcji 
skoku warunkowego... 
Koczc wic domysy wyjaniam, e dziaanie instrukcji LOOP** jest nastpujce: 

1. Zmniejszy CX o jeden (DEC CX - tak jak przy LOOP) 
2. Jeli CX>0 wykona skok warunkowy do "ETYKIETA" w zalenoci od 
typu instrukcji: LOOPE - JE, LOOPNE - JNE, LOOPZ - JZ, LOOPNZ - JNZ. 
3. Jeli CX=0, lub nie speniono warunku skoku warunkowego, zakoczy ptl. 

A po jakie licho jest to wszystko a tak dokadnie zamotane? - jedn z przyczyn 
jest oczywicie - wyjcie na przeciw programicie... teraz ma on moliwo 
wykonania dziaania w ptli, ktre nie tylko bdzie uzalenione od wartoci CX, 
ale nawet moe on przeprowadzi porwn anie dwch innych wartoci (np. CMP AX,BX) 
i rwnie na tej podstawie wykona ptl lub jej nie wykona... np. procedurka 
upewniajca si - zadajca uytkownikowi wane pytanie, ktre musi on potwierdzi
3 razy np. "czy formatowa dysk" - mogaby wyglda tak jak to przedstawia 
niniejszy program. 
------------------------
.model tiny
.code
org 100h
start:
jmp pocz
;Tu - juz tradycyjnie - dane
text1 db 'Wazne pytanie, potwierdz odpowiedz "t" 3-krotnie',13,10
db 'Uwaga: Wpisuj "t" nie "T" OK? '
crlf db 13,10,'$'
pytanie db 'Czy chcesz zobaczyc co mam Ci do powiedzenia (t/n)? $'
dopowiedz db 'Po mojemu umiesz juz calkiem dobrze Assembler!!!$'
niepowiem db 'Nie to nie!!!$'
pocz:
mov ah,09h
mov dx,offset(text1)
int 21h
mov cx,3
ptlp:
;petla pytania
mov ah,09h
mov dx,offset(pytanie)
int 21h
;wypisanie lancucha

;wczytanie znaku
mov ah,01h
int 21h
;zwraca: AL=znak; automatycznie wypisuje znak na ekran
;gdy al=0 instrukcja musi byc wykonana ponownie (tak jak readkey w TP)
;by wczytac klawisz "podwojnego znaczenia".
cmp al,'t'
;tymczasem wypisujemy enter - przejscie do nowej linii
;cos jak "writeln;" w pascalu
mov ah,09h
mov dx,offset(crlf)
int 21h
loope ptlp
;skok do ptlp jesli cx>0 i jesli prawdziwy jest warunek E (equal -
;rowne) z ostatniego porownania (czyli cmp al,'t').
mov ah,09h
jne npowiem
;skok bezwarunkowy po ostatnim CMP AL,'t'
;Wczytany znak byl rozny od t, (JNE) wiec "nie powiem"
mov ah,09h
mov dx,offset(dopowiedz)
int 21h
;teraz moge powiedziec
;skoro powiedzialem, skacze na koniec
jmp koniec
npowiem:
mov ah,09h
mov dx,offset(niepowiem)
int 21h

koniec:
mov dx,offset(crlf)
;przejscie do nowej linii
;poprzez wypisanie entera na ekranie
int 21h
;nie ustawiamy ah na 09h bo i tak juz jest ustawione
mov ax,4c00h
int 21h
end start
------------------------------
Mam nadziej, e po jego analizie nie bdziesz mie ju adnych wtpliwoci,
ale oczywicie - gdyby jednak mia mie - czekam na pytania. 
====================================================================================

UFFF....dobra koniec czesci II
mam nadzije ze juz troche lapiesz w ASM i umiesz napisac prosty programik.
