opt faq


___ ___ ___ ___
/ / /__/ /--- /-- / /
/ / ___ ________--/ ---/_____ / /
/ /----// // ___ \/ / ___ / /__/
/ ---/ // // / / // / _____/_ ___
/__/ / //__//__/ /__//__//_________//__/
/ /
/__/ hinte@box43.gnet.pl

;--------------------------------------------------------------------------------;
; ;
; ÜÛßßßßßßßßÛßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÛÜ ;
; Û ÜÛÛßßÛÛÜ ÜÛÛßßÛÛÜ ßßßßßßßß ÜÛÛßßÛÛÛ ÜÛÛßßÛÛÜ Û ;
; Û Û²Û Û²Û Û²Û Û²Û ÜÛÛßßÛÛÜ Û²Û ÛÛ Û²Û ÛÛ Û ;
; Û Û²ÛÛÛÛ²Û Û²ÛÛÛÛ²Û Û²Û Û²Û Û²Û Û²Û ed!Û ;
; Û Û²Û Û²Û Û²Û Û²Û ßÛÛÜÜÛÛß Û²Û ÜÜÜ Û²Û ßÛÛÛ Û ;
; Û ßÛß ßÛß ßÛß ßÛß ÜÜÜÜÜÜÜÜ ßÛÛÜÜÛÛÛ ßÛÛÜÜÛÛß Û ;
; ÛÜÜÜÜÜÜÜÜÛÜÜÜÜÜ Û ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ ;
; þ aDVANCED aRT ÜßÜßÜ Ü ÜÜÜÜÜ oF cRACKiNG gROUP þ ;
; ;
;--------------------------------------------------------------------------------;

- p r e s e n t s -

.model
__________________________________________________________________________________

Optimalization Faq & Errors High Levels Languages
__________________________________________________________________________________

.data
________________________________

TRESC TEGO TUTKA
________________________________

0. co to jest optymalizacja?

1. po co stosowac?

a) optymalizacja w asm/asm32
b) czy zawsze stosowac?
c) zalety asm

2. bledy jezykow wyzszego poziomu

3. greatzz
.code
start:
ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo
0. co to jets optymalizacja?
ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo

piszac wlasne programy w asm/asm32 nasuwa sie mysl: czy nie mozna
jakos prosciej tego napisac?? wiele procek mozna uproscic, czyli
zoptymalizowac, nie tylko pod wzgledem zajmowanego miejsca, lecz
takze pod wzgledem szybkosci wykonywania. a wiec wnioskujemy, ze
operacje polegajace na zmniejszeniu kodu-src
naszego programu, w celu szybszego jego
dzialania, nazywamy optymalizacja.

ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo
1. po co stosowac?
ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo

hmm, praktycznie odpowiedz na ten punkt jest w punkcie "b", no
ale tutaj pojdzie teoria :). optymalizacje stosujemy dla naszych
potrzeb zwiazanych z usprawnieniem dzialania danej aplikacji, pod
wzgledem objetosci kodu i szybkosci dzialania. jak wiecie juz z
poprzedniego punktu, szybkossc dzialania nie zawsze pokrywa sie z
najmniejsza iloscia kodu. niektore kompilatory jezykow wyzszego
poziomu maja w opcjach kompilacji: *minimum size i *maximum speed
takim kompilatorem moze byc VC++ 6.0 jak ktos chce to moze sobie
to sprawdzic ;) moze sie zdazyc tak ze program ktory zajmuje na
dysku wiecej, moze chodzic szybciej niz program o mniejszej obje-
tosci. zwiazane jest to z wykonywaniem instrukcji asm
mianowicie: ogolnie mowi sie ze jak procek ma 700 MHz to kazda
linijka kodu jest wykonywana z predkoscia 1/700'000'000 sekundy -
otoz nie! kazda instrukcja ma swoj czas wykonania, i wcale nie
jest tak, ze jak zajmuje mniej kodu to szybciej sie wykonuje, np.
wezmy instrukcje "push eax" wykonuje sie ona wolniej niz linijka
"mov eax,12345678h" - zostalo to udowodnione w punkcie "a". mozna
to wytlumaczyc tak: = +
tak wiec mamy 2 instrukcje w jednej. instrukcje "elementarne" wy-
konuja sie o wiele szybciej. czyli po krotce wiemy jak to jest,
w prawdzie ten opis odbiega troche od rzeczywistosci, ale mysle
ze kazdy lapnie o co chodzi :). no to teraz czas na troche kodu
src i nieco opisow.

ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo
a) optymalizacja w asm/asm32
ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo

zaczynamy - czesc tego co jest tutaj opisane na pewno kazdy juz
zna, ale postaram sie to zebrac w jedna calosc i dorzucic czegos
nowego.

-----------------------------------------------------------------
- zerowanie rejestrow -
-----------------------------------------------------------------
najprostszym zerowaniem rejestru jest:

and r32, 0 ; 3 bajty
mov r32, 0 ; 5 bajtow

ale chwila - w kodzie asm zajmuje to 5 bajtow, mozna zrobic tak:

xor r32, r32 ; 2 bajty
sub r32, r32 ; 2 bajty

zerowanie rejestru EDX mozna zrobic jednym bajtem:

cdq

ale uwaga, jesli w EAX jesl liczba wieksza niz 7fffffffh to cdq
zwroci w EDX: -1, na poczatku proga mozna to smialo stosowac bo w
EAX mamy EntryPoint programy, przewaznie mniejszy od tej liczby

dla przykladu jeszcze cos:

xor ax,ax ; 3 bajty
xor al,al ; 2 bajty
xor ah,ah ; 2 bajty

na wyzeworanie rejestru AH jest jeszcze jeden sposob a mianowicie
funkcja "CBW", w prawdzie ona realizuje rownanie: ax = al, czyli
zawsze zeruje rejestr AH, funkcja zajmuje 1 bajt.

-----------------------------------------------------------------
- porownywanie z zerem -
-----------------------------------------------------------------

normalnie to wtglada tak:

cmp r32, 0 ; 3 bajty

mozemy napisac to tak:

test r32, r32 ; 2 bajty
or r32, r32 ; 2 bajty

albo tak:

inc r32
dec r32

-----------------------------------------------------------------
- push -
-----------------------------------------------------------------

wwalanie na stos tej samej wartosci, np.:

push 0
push 0
push 0
push 0
push 0

kazde po 2 bajty, a mozna napisac tak:

xor eax, eax
push eax
push eax
push eax
push eax
push eax

i zaoszczedzamy 3 bajty

przy wiekszych ilosciach mozna tez inaczej:

push 7 ; 2 bajty
pop ecx ; 1 bajt
xor eax,eax ; 2 bajty
@wwal:
push eax ; 1 bajt
loop @wwal ; 2 bajty

calosc zajmuje 8 bajtow, a przy 7 push'ach to by bylo 14 bajtow

-----------------------------------------------------------------
- wpisywanie malych wartosci -
-----------------------------------------------------------------

zalozmy ze chemy zrobi tak:

mov eax, 7 ; 5 bajtow

mozna zrobic to jednak prosciej:

push 7 ; 2 bajty
pop eax ; 1 bajt

ale co z liczbami z zakresu 80h - FFh ??, tutaj kompilator zmieni
push na 5 najtow - niestety, wszystko opiera sie o to, ze liczby
talie sa uznawane za liczby ujemne: od 0-7fh plus, a od 80h-FFh
minus. mozna to zapisac jedynie jako 4 bajty:

xor eax,eax
mov al,80h

dla "jedynki" mozna tak:

xor eax,eax ; 2 bajty
inc eax ; 1 bajt

-----------------------------------------------------------------
- pozostale instrukcje -
-----------------------------------------------------------------

jak spawdzic czy w rejestrze jest -1? otoz najprosciej chyba tak:

inc r32
jz @jest
dec r32

tak jest prosciej, poniewaz cmp r32,-1 zajmuej 3 bajty, mozna
to wykorzystac przy createfilea - jak niema pliku zwraca -1 w EAX

zamiana wartosci rejestrow - pzydatna jest instrukcja xchg, ale:

xchg eax,edx ; 1 bajt
xchg edx,esi ; 2 bajty

widac roznie to bywa, instukcje w asm sa tak dobrane aby najmniej
bajtow zajmowaly instrukcje operujace EAX, wynika to nawet z na-
zwy tego rejestru - Akumulator, oto przyklad:

add eax, 5000h ; 5 bajtow
add esi, 5000h ; 6 bajtow

pobieranie wartosci spod ESI mozna zrobic tak:

mov eax, [esi] ; 2 bajty

ale mozna i tak:

lodsd ; 1 bajt = mov eax,[esi] ; add esi,4

niedogodne jest, ze dziala tylko na eax.. no coz takie jest zycie

zerowanie obaszaru pamieci:

mov esi, offset _pamiec
xor eax,eax
push 20h
pop ecx
_lop:
rep stosd ; stosw albo stosb
loop _lop


-----------------------------------------------------------------
- masowe wywolanie API -
-----------------------------------------------------------------

chyba nikt nie bedzie wywolywal 9 tych samych API po kolei, tylko
lepiej byloby to zrobic w petli, CheckBox'ami albo zapisywanie opcji swojego programu do rejestru>
mozna to rozpatrzyc jeszcze tak, ze niektore funkcje maja troche
tych parametrow i niektore z nich pozostaja bez zmiany. dam tutaj
wyzej wspomnainy przyklad z checkbox'ami:

push 20h ; 32 checkboxy
pop ecx
xor ebx,ebx
push IDI_CHBOX01 -1 ; np= 10, nastepny, 11,12, itd ...
pop edx
@lop:
push ecx
inc edx ; numer checkboxa
shl ebx,1

push edx
invoke IsDlgButtonChecked,hWnd, edx ; normalnie ok 10 bajtow
pop edx

or ebx,eax
pop ecx
loop @lop

mamy z tego ok 19 bajtow + wywalanie API, a gdybysmy to zrobili
pojedynczo to troche by to nam zajelo ;). w EBX jest liczba w bi-
tach, zaznaczonych checkboxow. tak samo mozna robic z rejestrem.


-----------------------------------------------------------------
- zastawnienia wynikow wykonywania sie roznych instrukcji -
-----------------------------------------------------------------
bajty | instrukcja | jednostki
-----------------------------------------------------------------
0578563412 | ADD EAX,12345678 | 1,45
030508304000 | ADD EAX,[00403000] | 1,49
03C3 | ADD EAX,EBX | 1,46
0FC8 | BSWAP EAX | 1,44
99 | CDQ | 1,50
3D78563412 | CMP EAX,12345678 | 1,51
3B0508304000 | CMP EAX,[00403000] | 1,45
3BC3 | CMP EAX,EBX | 1,45
FF0D08304000 | DEC [00403000] | 5,14
48 | DEC EAX | 1,48
2D78563412 | SUB EAX,12345678 | 1,47
2BC3 | SUB EAX,EBX | 1,50
FF0508304000 | INC [00403000] | 4,93
40 | INC EAX | 1,45
0F7EC0 | MOVD EAX,MM0 | 2,48
0F6EC0 | MOVD MM0,EAX | 2,44
A108304000 | MOV EAX,[00403000] | 1,53
B878563412 | MOV EAX,12345678 | 1,49
8BC3 | MOV EAX,EBX | 1,45
8BC6 | MOV EAX,ESI | 1,51
8BFE | MOV EDI,ESI | 1,46
85C0 | TEST EAX,EAX | 1,44
91 | XCHG EAX,ECX | 2,31
-----------------------------------------------------------------
- srednia wartosc na jedna komende -
-----------------------------------------------------------------
6878563412 | PUSH 12345678 | ----
58 | POP EAX | 1,78
6A20 | PUSH 20 | ----
58 | POP EAX | 1,98
FF3508304000 | PUSH [00403000] | ----
58 | POP EAX | 2,41
50 | PUSH EAX | ----
8F0508304000 | POP [00403000] | 2,40
50 | PUSH EAX | ----
58 | POP EAX | 1,94
-----------------------------------------------------------------

ten system jest wyliczony dla okreslonej wartosci, nie znaczy to
ze nap jesi CDQ = 1,50 to dwie komendy CDQ = 3,00 to NIE jest tak
liczone. im mniejsza jednostka tym szybciej sie wykonuej funkcja.
to tylko taki maly obraz czasu wykonywania sie kilku funkcji CPU
i dlateg warto czasem stosowac mov, zamiast push/pop :)

ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo
b) czy zawsze stosowac?
ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo

odpowiedz jest niejednoznaczna. chodzi przedewszystkim o program,
zalezy do czego ma on sluzyc. jesli jest to powiedzmy 'crackme',
to kazdy bedzie sie zastanawial jak najlepiej ukryc jego procke
sprawdzajaca poprawnosc seriala, i w 70% ludzie stosuja junki -
czyli maly kodzik najczesckeij inicjowany jako makro, ktoy ma za
zadanie utrudnic nam sledzenie kodu pod debuggerem. nikt w tedy
nie bedzie sie zastanawial nad optymalizacja, jedyna taka osoba
ktora stosuje optymalizacje i junki to imagi^cp ;)

ok, to taki prosty przyklad, wezmiy np. loadera - wiadomo loader
zmiania bajty w spakowanej aplikacji, i musi to zrobic po rozpa-
kowaniu progsa, ale przed wykonaniem sie programu. z loaderami, a
raczej z ich pisaniem jest duzy klopot, bo - na kazdym procesorze
loader bedzie chodzil inaczej - szybciej albo wolniej, to zalelzy
od taktowania porcesora, uruchomionych apliakcji itp. czasem wiec
loader niezdazy spatchowac bajtow - calkiem ciekawym rozmiazaniem
w tej kwesti jest "DzA patcher" ale tym kiedy indziej sie napisze
czyli przy pisaniu loaderow decyduje szybkosc dzialania programu
niz zajmowane jego miejsce - nawet kosztem sporej ilosci bajtow
.

jako kolejny przyklad mozna wziac jakas normalna aplikacje, wezmy
patchGenerator - przecietnie nikt nie wnika w zmniejszanie ilosci
bajtow kodu, tylko skupia sie na samym kodzie wykonywalnym, zeby
to dobrze dzialalo :) po napisaniu proga mozna wprowadzac korekty
ale przy sporej ilosci kodu src bedzie tego od groma :)

czyli w ostatecznym wyniku: optymalizacje stosujemy wedle potrzeb

ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo
c) zalety asm
ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo

w asm/asm32 mamy praktycznie problem z glowy bo procka ktora mamy
napisac zawsze zajmuje malo miejsca, mamy jesze plus, ze
mozemy ja dowolnie modyfikowac czego w jezykach wyzszzego poziomu
niema. niedogodnoscia jest ze napisana procka zajmuje wiecej niz
bysmy ja napisali w asm! to jest faqt i duzy minus dla HighLevel
jezykow. faqtem jest takze to, ze w HL pisze sie o wiele prosciej
i szybciej niz w asm. jednak w asm mamy w/w plus ktorego niemaja
inne jezyki - mamy bezposredni dostep do kodu i w pelni panujemy
nad kodem programu - tego niema np w delphi. porownajcie sobie -

sam form w delhpi - ok. 300KB
sam form w asm32 - 2048 bajtow

po odpowiedniej kompialcji, laczeniu sekcji itp ... roznica jest
kolosalna!!! wynikaja tu 3 plusy: w pelni konrolowany kod w asm,
maly rozmiar pliku wykonywalnego, optymalizujemy jak chcemy i co
chcemy :). przyznam jednak, ze jak niewiem jak cos zrobic a asm,
a wiem jak to zrobic w delphi, to pisze to w delphi - int 3 - i
jade w SI, potem tylko screendump, troche optymalizacji i kod ok

powracajac do potymalizacji, wezmy sobie funkcje API: "lstrlen" -
funkcja liczaca dlugosc stringu. moze ktos sledzil ja w SI? jesli
nie to polecam. a przeciez mozna ja prosciej napisac:

mov edi,offset _string ; 5 bajtow \
or ecx,-1 ; 3 bajty \
repenz scasb ; 2 bajty } 13 bajtow
not ecx ; 2 bajty /
dec ecx ; 1 bajt /

i ile mniej niz "call lstrlen" ?? pozatym pozbywamy sie 1 importu
i zyskujemy na szybkosci dzialania. niektore procki mozna pisac
samemu. jeszcze jeden przykald - jak by tu pobrac offset startu
kernela? najprosciejby bylo tak:

push offset _kernel32
call GetModuleHandleA

ale to daje nam lacznie jakies 19 bajtow . moze
sporobojemy to napisac inaczej?? czemu nie:

pop eax
push eax

@Kernel:
dec eax
xor ax,ax
cmp word ptr [eax], 'ZM' ; mona tez: cmp byte ptr [eax], 'M'
jnz @Kernel ; ale daje 'ZM' dla zabezpieczenia

znaleznienie kernela bez wywoalania API, zajmuje tylko 12 bajtow!
faqt, jest troche niedogodne bo mozna tylko skorzystac z tego na
starcie programu , ale zawsze mniej
bajtow i nietrzeba korzystac z importu :)

ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo
2. bledy jezykow wyzszego poziomu
ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo

tutaj pewnie wele osob sie zawiedzie, z powodu nazwy tematu, nie
chodzi tutaj o "bledy" w znaczeniu errory - tylko o bledy w kom-
pilacj programu. nie, nie, jakis program dziala, i dziala dobrze,
ale chodzi mi o bledy przy optymalizacji tutku :>. lamiac programy, wiele razy natknolem sie na taki kod,
ze jak serial jest ok, to eax=0, jesli jest zly to eax=1. to jest
chyba standard ;). no ale spojrzymy na to od strony kodu:

B800000000 MOV EAX,0
B801000000 MOV EAX,1

niby takie niewinne instrukcje a ile bajtow nam zzeraja :(. mozna
zawsze eax wyzerowac sub'em albo xor'em. a zeby miec jedynke, to
wystarczy to jeszcze inc'nac - i tak mamy 3 bajty zamiast 5-ciu.

nastepne dziwne bug'i ktore udalo mi sie zauwarzyc w programch:

8918 MOV [EAX],EBX
899800000000 MOV [EAX+00000000],EBX

ta sama komenda, a zawiera o 4 bajty wiecej kodu! i co to ma byc?
to napewno nie jest objaw optymalizacji jezykow wysokiego poziomu
to samo wyrazenie spotkalem na EBP - zreszta ten rejestr jest tak
przystosowany do pracy z liczbami --> ebp+34 itd.. zreszta jak
napiszemy "mov [ebp],ebx" to i tak kompilator zrobi to po swojemu

895D00 MOV [EBP+00],EBX

zycie i assembler sa dziwne ;). to chyba wszystkie bledy jakie
udalo mi sie do tej poey zauwrzyc. fakt, malo tego jest alwe cos

mozna by to jeszcze wspomniec o visualnym gownie, (MSVB) ale to
jest juz inna sprawa, on wogole marnuje miejsce przy pobieraniu
textu - pobiera go word'ami, czyli wymaga na niego 2 razy wiecej
miejsca niz string zajmuje, a porownywanie stringow najczesciej
odbywa sie poprzez: "rep cmpsw". ale o VB niema co pisac, chociaz
na podstawie tego jezyka zaczyna powstawc c# (c sharp) - chyba od
nazwy programistow, ktorych szarpnelo, ze chca laczyc C i VB, a
jeszcze zeby bylo smieszneiej, spotkazlem sie ostatnio z calkiem
nowym kompilatorem assemblera, ktory mniej wiecej dzial na tej
samej zasadzie - bodajrze nasywa sie "IL Asm". oni wszyscy chyba
upadli na glowe, niech zrobia jeden dobry jezyk, a nie 20 roznych
i kazdy po takie ilosci bledow, ze az sie wiezyc niechce...

no to by bylo chyba na tyle. jesli tu dotrwales to gratulacje, ze
chcialo Ci sie czytac ten nudny faq.. moze jednak cos z niego za-
pamietasz i zaczniesz uzywac w praktyce ...


ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo
3. greatzz
ooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOoooooOooooo

to: bart^cp, smola^cp, PiT^R, imagi^cp, coxoc, Chendler, Liquid,
oraz reszte ludzi o ktorych niewspomnialem a chcialem ;)

end start


Wyszukiwarka

Podobne podstrony:
FAQ Komendy Broń (Nazwy używane w komendach) do OFP
faq general
faq
Jaguar Bluetooth FAQ
FAQ
FAQ Ger
FAQ
Eldritch Errata and FAQ
FAQ
faq 4
faq page3
BCB FAQ
QDLTool FAQ 20110211
faq
opt czarnybór

więcej podobnych podstron