Delphi faq tom3_offline.doc

(350 KB) Pobierz
TP w 32-bitowym opakowaniu

1

 

DELPHI

 

Część 3.ASM i Pascal

 

 

 

Delphi Offline 4Programmers : Zadania i wypracowania, oraz zbiory lekcyjne delphi

wersje faq napisane przez wielu programistów znajdują się w tej ogromnej książce, składającej się z wielu stron o bardzo wnikliwie napisanej treści.

 

 

Autorzy : minn,. Adam Boduch,iinni.

Podziękowania dla wszystkich autorów faq, bo to oni stworzyli tą książkę.

 

 

Książka ta nie jest , nie była i nie będzie wydana na rynku, jedynie może się ukazać w wersji pirackiej na stronach i z innych żródeł, jest ona prawnie nieprawna i prawnie łamie chyba wszystkie prawa dotyczące praw prawa prawowitego właściciela i autora oraz plagiat jak cholera . Uehhhhh, ;) prawo w Polsce jest pOkRęCoNe,

 

 

 

 

                                                                                                                                                                        IRCc2003

 

 

 

 

Ps : w rzyciu jeszcze niewidziałem tak wielkiej kopii danych tak wielu autorów i to zklepana całkiem bez ich zgody ! czy to może tak być? Nie, Dla tego proszę wnikliwie nie doszukiwać się autorów tej oto wielkiej 2 tomowej księgi, i potraktować to jako wielkie uznanie, iż wasze Faq mogło się ukazać wraz z najlepszymi, nik nie będzie pokszywdzony, dane nie są zmienione, brakuje tylko podpisów autorów, z powodu takiego, że, naprawdę ich nie znałem: Dlaczego ją napisałem ? bo wasze nauki poprostu się marnowały !

Dlaczego by tego nie zapakować w jedno. Nigdy nie myślałem o tym że ta książka będzie wirowała po internecie, nawet teraz, jak ją piszę , niewiem o tym, co dzieje się w czasie gdy ty ją czytasz. Jeżeli jednak coś się dzieje i z nie mojego powodu dostałą się ona w wasze oblicze, bądż zbyt wielu autorów tych faq się z czymś tutaj zawartym nie zgadza, proszę zmieniać treść DOWOLI ! NIC TUTAJ NIE MUSI ZOSTAC W TAKIEJ FORMIE W JAKIEJ JEST wszystko to dotyczy każdej mojej książki, która w jakiś sposób kogoś lub wielu WAS crackerów i hakerów i Hakerów uraziła. Wiele danych pochodzi ze strony :

4programmers.net i to Właśnie A.B powinien mieć o to największy żal, no ale cóż zrobię.

PA.

 

 

 

 

TP w 32-bitowym opakowaniu

Czyli jak zmusić 16-bitowy kompilator tp do 32-bitowych operacji. Pozornie rzecz niemożliwa, a jednak...
Część tematu jest już zaprezentowana w artykule pt.: efektywne programowanie w turbo pascalu, więc się będę nieco powtarzać. Ponadto zakładam, że znasz podstawy asemblera, bo to dzięki niemu będziemy czarować w 32 bitach. (Będziemy używać tylko asemblera wbudowanego w kompilator, więc jeśli używasz asemblera zewnętrznego, to nie ma sensu żebyś czytał dalej ten artykuł.)

Co nam daje działanie na 32 bitach? Przede wszystkim operacje takie są szybsze w porównaniu do ich 16-bitowych odpowiedników, ponadto wyniki naszych działań nie są ograniczone rozmiarem 16-bitowego rejestru a rozmiarem rejestru 32-bitowego, czyli że bez nadmiernego kombinowania możemy sobie działać na wielokrotnie większych liczbach - przy zachowaniu tej samej, a nawet wyższej szybkości.
Same plusy :)

Ale jest i minus: jak? Jak zmusić kompilator tp do przełknięcia czegoś, do czego nie był przewidziany? Popatrzmy na wbudowany asembler: nie zna takich rejestrów, jak EAX,EBX itp, nie zna FS ani GS, w ogóle zero zrozumienia dla naszych 32-bitowych aspiracji. Ale zna on coś takiego, jak DB, DW i DD. I to nas urządza. :)

Jak się buduje 32-bitową instrukcję? Jeśli by za pośrednictwem debuggera (np.: Turbo Debugger) pownikać w kod jakiegoś 32-bitowego programu, to zobaczymy śmiesznie prostą prawidłowość: każda taka operacja jest poprzedzona bajtem o wartości 66h (102d). Tak! To jest naprawdę aż takie proste! Więc zaczynamy rzeźbienie...

Na pierwszy ogień najczęściej używana operacja - zerowanie rejestru.

asm

  mov ax,0              {można tak}

 

  xor ax,ax             {można też tak; tak jest lepiej, bo operacje

                         wykonywane na samych rejestrach, bez odwołania

                         do pamięci, są szybsze}

 

  db $66; mov ax,0      {tu już mamy 32 bity: mov eax,0}

 

  db $66; xor ax,ax     {i druga wersja 32-bitowa: xor eax,eax

                         ta wersja jest najlepsza i najszybsza}

end;

W ten sam sposób możemy sobie dzielić, mnożyć, dodawać, odejmować, przesuwać bity, wrzucać na stos i z niego zdejmować - teoretycznie cokolwiek!
W praktyce pojawia się kilka problemów, ale o tym za chwilę.

Może kilka przykładów:

asm

  {szybkie c=a*b, gdzie a i b są typu word, wynik

  jest też typu word, czyli w zasadzie nic nowego}

  mov ax,a

  mov bx,b

db 66;  mul bx

  mov c,ax

end;

Teraz mnożenie word*word z wynikiem dword (tzn. longint). Strach patrzeć w debuggerze na to, co robi TP z c := longint(a)*longint(b)...

asm

  db $66; xor ax,ax;           {na wszelki wypadek eax = 0}

  mov ax,a                     {ax = a}

  mov bx,b                     {bx = b}

  db $66;  mul bx              {eax = eax * ebx}

 

  db $66;  mov word ptr c,ax   {c = eax}

end;

Powyższa instrukcja jest wykonywana o ponad 60% szybciej.
A może by tak zaryzykować 64 bity?... Mnożenie dword*dword z wynikiem qword (2*longint)!!! Wynik zrzucany do dwóch zmiennych - poniżej $FFFFFFFF do c, a to co wyżej - to do d.

asm

db $66; mov ax, word ptr a

db $66; mov bx, word ptr b

db $66; mul bx

db $66; mov word ptr c,ax

db $66; mov word ptr d,dx

end;

W analogiczny sposób można dzielić dword przez dword, otrzymując w wyniku też dwa dwordy (tzn. c = a div b; d = a mod b):

asm

db $66; mov ax, word ptr a

db $66; mov bx, word ptr b

db $66; div bx

db $66; mov word ptr c,ax

db $66; mov word ptr d,dx

end;

Jak szybko zwiększyć zmienną typu longint?

asm {tak TP interpretuje inc(a): dwie operacje dodawania}

  add    word ptr a,0001

  adc    word ptr a+2,0000

end;

 

asm {tak my zrobimy: jedna operacja inkrementacji}

  db $66;  inc word ptr a

end;

Nie trzeba dodawać, że inc jest dużo szybsze od add?
A dodawanie? Proszę bardzo:

asm {dodawanie stałych: niech stała będzie równa np. $0F0F1010}

  db $66;  add word ptr a,$1010; DW $0F0F;

end;

{przy dodawaniu stałej, której dolna część będzie mniejsza

od $100, pojawi się problem, bo kompilator się nabierze,

że to bajt; wtedy trzeba mocno czarować:}

asm

  db $66; mov ax,$0010; DW $000F;

  db $66; add word ptr a,ax

end; { co i tak generuje szybszy kod niż inc(a,$000F0010)}

Jeśli porównasz któryś z powyższych kodów z jego odpowiednikiem generowanym w wyniku zwykłego mnożenia, dzielenia itp., to zobaczysz jak wiele zyskujesz.

Możemy też dopalić najbardziej czasochłonną procedurę w TP: move (nota bene - ona jest 8-bitowa!!!). Napiszemy własną wersję, która będzie prawie cztery razy szybsza.
A w ogóle jak działa ta procedura? Szybki rzut oka:

procedure move(var src;var dest;count : word); assembler;

asm

  mov cx,count

  push ds

  lds si,src

  les di,dest

 

  cld

  rep movsb {!!!}

 

  pop ds

end;

Spójrz na linijkę z trzema wykrzyknikami: rep movsb. movsb to operacja przenoszenia bajtu ze stosu ds:si na stos es:di. Przenosimy po bajcie! (Jeśli nie wierzysz, to odpal program, który używa tej procedury, pod debuggerem i sam sprawdź.)
Przecież to jest bez sensu, bo kompilator bez żadnego rzeźbienia pozwala na napisanie procedury, która będzie przenosić po słowie, czyli w tym samym czasie skopiuje dwa razy więcej!
Ale po co się ograniczać do słowa? Poniższa procedura będzie zrzucać od razu cztery bajty, osiągając graniczną prędkość działania równą prędkości zegara pamięci...

procedure move32(var src;var dest;count : word); assembler;

asm

  mov ax,count

  db $66; xor dx,dx   {xor ecx,ecx}

  mov bx,4

  div bx              {ax = count div 4; dx = count mod 4}

 

  push ds

  mov cx,ax

  lds si,src

  les di,dest

 

  cld

  db $66; rep movsw      {rep movsd}

 

  cmp dx,0

  jz @@1

  db $66; mov cx,dx

  rep movsb

 

@@1:

  pop ds

end;

Chyba już łąpiesz, o co chodzi? Wtykasz db $66; wszędzie, gdzie się da, i już możesz być szczęśliwy. Uważaj na jedno: operacje na pamięci - zrzucanie i pobieranie ze stosu; pamiętaj, że operujesz naraz czterema bajtami, a nie dwoma czy jednym. Jeśli nie jesteś pewien, czy poprawnie zrobiłeś to, co chciałeś, a masz do dyspozycji Turbo Debuggera albo jakiś inny debugger, to nie wahaj się i sprawdzaj.
Jeżeli masz jeszcze jakieś pytania lub chcesz coś dodać - pisz do mnie.

 

FAQ CrackPL - Asm dla badaczy kodu – Wprowadzenie



Chyba nikogo nie musze uswiadamiac jak wazna jest znajomosc
assemblera dla badaczy kodu. Jezyk ten bedacy mnemonika kodu
maszynowego procesorow ulega zatraceniu w dzisiejszych czasach w
dobie pakietow typu Visual Microsoftu, Borlanada i innych.
Nowoczesni (czytaj. nowi -:)) programisci nie maja nawet pojecia
czym jest assebler i jak go ugrysc a przeciez kod asemblera jest
esencja programowania i dlatego kazdy badacz kodu musi go poznać.
Postanowilem przedstawic wam maly guide wprowadzajacy do asemblera
dla wszystkich poczatkujacych crackerów i pod ich kierunkiem
pisany. Jest to jedynie schematyczny przeglad podstawowych pojec i
instrukcji, który mam nadzieje rozwine w przyszlosci. W ZADNY
WYPADKU NIE JEST TO TUTOR programowania w asm, jedynie przedstawia
zagadnienia na ktore nalezy zwrocic uwage podczas analizy kodu. No
ale mam nadzieje :-) ze kazdy kto to przeczyta wezmie sie za asm'a
porzadnie i bedzie pisal w nim programy w razie potrzeby.

Wszelkie sugestie i pomysly kierowac na gcrkpl@friko6.onet.pl.

Co powinien wiedziec cracker o asm

InDeX

[PODSTAWOWE INFORMACJE]

1. Rejestry [REGISTERS]
1.a. [Specyfikacja architektury Intela - Rejestry]
2. [Flagi - Rejestr znacznikow]
2.a. [Flagi - Rejestr znacznikow - specyfikacja Intel 8086]
3. [Stos - STACK ]
4. [Call i Ret - wywolania funkcji i procedur]
5. [MOV - instrukcja przeniesienia]
6. [CMP i skoki warunkowe]
6.a. [Specyfikacja skokow warunkowy]

[CIEKAWOSTKI]
7. TEST EAX,EAX - co to znaczy ?
___________________________________________________________________
1. Rejestry [REGISTERS]

Rejestry sa podstawowym miejscem przechowywania danych. Sa to
16-bitowe komorki procesora. Jest 14 rejestrów i w tym 12 rejestrow
danych i adresowych, rejestr wskaznika instrukcji (IP) i rejestr
znacznikow. Rejestry danych i adresowych mozemy podzielic na kilka
grup i tak:

AX (akumulator) --------+
BX (bazowy) |----- Rejestry ogólnego
przenzaczenia
CX (licznik) |
DX (danych) --------+

SP (wskaznik stosu) --------+
BP (wskaznik bazy) |-----Rejestrywskaznikowe i
indeksowe
SI (index zrodla) |
DI (indeks przeznaczenia) --------+

CS (programu) --------+
DS (danych) |----- Rejstry segmentowe
SS (stosu) |
ES (dodatkowy) --------+

IP (wskaznik instrukcji)
I Rejestr Znacznikow

Jak oczywiscie kazdy sie zorientowal przy pracy w Win32 rejestry
okreslane sa jak EAX, EAX itd, oznacza to ze sa to odpowiedniki
powyzszych rejestrow, tyle, ze 32-bitowe.

Chwila wyjasnienia z tymi bitami. Wezmy rejestr AX, ktoryjest 16
bitowy i dzieli sie na dwa podrejestry 8 bitowe AH i AL. Jak wiemy
8 bitow tworzy bajt, ktory przyjumuje wartosc od 0 do 255, czyli
rejestr AH i AL moze miec najwieksza wartosc FFh. Logicznie myslac
-:) rejestr 16 bitowy moze przyjac maksymalna wartosc FFFFh itd.
(32 bit EAX mam max FFFFFFFFh ups-:)). Chyba kazdy lapie co daja 32
bitowe rejestry i jak zwiekszaja sie mozliwosci.

Warto zapoznac sie z charakterystykami rejestrow, gdzyz kazdy ma
swoje wlasne konkretne zastowsowanie. Przegladajac kod programu
mozemy zauazyc pewne prawidlowosci, np.

EIP - debugujac pod SoftIce 32bit widzimy, ze rejestr ten wskazuje
na aktualny kod instrukcji i mozemy go uzyc np do zalozenia pulapki
na danej lini czyli bpx EIP lub dokladniej CS:EIP.

CS - wskazuje segment kodu, czyli jak mamy jakac linie kodu o
adresie np. 14F:04033232 to mozemy ja zapisac jako CS:04033232
poniewaz w rejestrze CS jest zachowana wartosc 014F.

DS - podobnie jak powyzej, zawiera adres segmentu dany, jezeli w
okienku danych pod SoftIce mamy jakis adres np. 0145:03055555 to DS
wskazuje segment 0145.

ESI i EDI sa wskaznikami danych np. do porownan tekstow itp. Wezmy
np. instrukcje porownywania w bibliotekach VB - reps cmpsw dla,
ktorych w w ds:esi i es:edi zawarte sa adresy tekstow (np. numerow
seryjnych) do porwnania. To samo tyczy sie wielu instrukcji
przesylania i porownnywania danych, gdzie przeznaczenie i cel
zawarte sa w rejesteach SI i DI np:

LEA SI, ZRODLo ;Zaladowanie adresu zrodla
LEA DI, ES:PRzesznaczenie ;Zaladowanie adresu
przezanczenia

MOV CX,100 ;Zaladowanie licznika elementow
MOVS Przeznaczenie,Zrodlo ;Kopiowanie tekstu z jednego
miejsca w innne.

___________________________________________________________________
1.a. [Specyfikacja architektury Intela - Rejestry]

Rejestry ogolnego przeznaczenia Rejestrysegmentowe
AH/AL AX (EAX) Akumulator CS Programu
BH/BL BX (EBX) Bazowy DS Danych
CH/CL CX (ECX) Licznik SS Stosu
DH/DL DX (EDX) Danych ES Dodatkowy


(Exx) znaczy 386+ 32 bit rejestr

Rejestry wskaznikowe Rejestry stosu

SI (ESI) Indeks zrodla SP (ESP) Wskaznik stosu
DI (EDI) Indeks przeznaczenia BP (EBP) Wskaznik bazy
IP Wskaznik instrukcji

FLAGI Rejestr Znacznikow (zobacz FLAGI)

Specjalne rejestry (386+)
CR0 Control Register 0 DR0 Debug Register 0
CR2 Control Register 2 DR1 Debug Register 1
CR3 Control Register 3 DR2 Debug Register 2
DR3 Debug Register 3
TR4 Test Register 4 DR6 Debug Register 6
TR5 Test Register 5 DR7 Debug Register 7
TR6 Test Register 6
TR7 Test Register 7

Rejestry ogolnego przeznaczenia sa przeznaczzone do przechowywania
dowolnych danych i wykonywania roznych operacji (arytmetycznych,
logicznych itp) , pelnia takze funkcje specjalne odpowiadajace ich
nazwom.

AX (accumulator) - rejestr ten jest najczesciej uzywany przy
operacjach mnozenia i dzielenia, a takze w operacjach logicznych,
arytmetycznych i odkladania wynikow wielu operacji.
8 dolnych bitow tego rejstru okresla sie jako rejestr AL, a 8
gornych bitow jako AH

BX (basis) - rejestr bazowy moze byc uzywany jako dwa 8-bitowe
rejestry BH i BL, a np. jako 16-bit mozemy go uzyc do utworzenia
adresu pamieci, tworzac z rejestrem segmentowym pelny adres -
Segmennt:Offset - DS:BX

CX (count) - rejestr zliczajacy jest wykorzystywany oprocz
zliczania takze do przesylania danych. Moze byc takze uzywany jako
dwa rejestry 8-bitowe CH i CL.

DX (data) - rejestr danych wykorzystuje sie przy dzieleniu i
mnozeniu. Jest takze jedynym rejestrem, w korym mozna podac adres
portu w rozkazach wejscia-wyjscia.

Rejestry segmentowe sluza do adresowania pamieci operacyjnej.

CS (code segment) - rejestr wskazuje poczatek segmentu kodu
programu, tworzy pelny adres wraz z rejestrem IP - CS:IP. Rozkazy
programu, skoki, powroty pobierane sa w odniesieniu do tego
rejestru.

DS (data segment) - rejestr wskazujacy poczatek segmentu danych

SS (stack segment) - rejestr stosu wskazuje poczatek segmentu stosu

ES (extra segment) - rejestr dodatkowu wskazujacy dodatkowy segment
danych

Rejestry wskaznikow. Dostep do danych adresowany jest przez
polaczenie adresu z rejestru segmentu z przesunieciem pobieranym z
innego rejestru min. rejestru wskaznikowego.

SI (source index) - rejestr indeksowy zrodla, najczesciej stosowany
przy adresowaniu w innstrukcjach przetwarzajacych lancuchy znakow,
tworzy wowczas pelny adres DS:SI

DI (destination index) - rejestr indeksowy przeznaczenia, podobny
do SI uzywany w adresowaniu danych przy przetwarzaniu lancuchow
znakow, tworzy wowczas pelny adres ES:DI

SP (stack pointer) - wskaznik stosu tworzy wraz z SS - SS:SP adres
danej odeslanej na stos i jest wykorzystywany przy pobieraniu i
zapisywaniu danych na stos.

BP (base pointer) - wskaznik bazy uzywany jest podczas operacji
niestandardowych np. przy pobieraniu parametrow przekazywanych na
stos.

IP (instruction pointer) - wskaznik instrukcji wskazuje na
aktualnie wykonywana instrukcje i wraz z rejestrem segmentu kodu
tworzy pelny adres - CS:IP. IP wskazuje offset (przesuniecie)
wzgledem poczatku segmentu programu.

___________________________________________________________________
2. [Flagi - Rejestr znacznikow]

Falgi sa komorkami, ktore moga przyjmowac wartosc 0 lub 1 i sa
zawarte w rejestrze znacznikow. Odpowiednie ustawienie
poszczegolnych flag decyduje o wykonaniu innych instrukcji a
szczegolnie instrukci warunkowych. Najszybciej zrozumiec flagi
mozna na przykladzie :

CMP AX,BX - Porownaj rejestry AX z BX, jezeli rowne to flaga
zerowa Z ustawiona na 1
JZ 0401233 - Jezeli flaga Z ustawiona na 1 to wykonaj skok do
adrsu 0401233

Oczywiscie intrukcja CMP ustawia takze inne flagi z zaleznosci od
wyniku porownania i podobnie inne instrukcje warunkowych skokow
moga sprawdzac takze inne flagi. Szczegolowiej przedstawie to przy
omowieniu skokow warunkowych.

...

Zgłoś jeśli naruszono regulamin