--WYKLAD Z ASM BY Gynvael - 26.09.2005--: [21:04:32] lista zadan z asma pojawi sie dzisiaj kolo 24 na sieci [21:04:59] zasady beda obowiazywac na niej identyczne jak na liscie z zadankami z C [21:05:13] teraz tak [21:05:19] jako ze jest full nowej wiary [21:05:28] to przypomne z czego narazie korzystamy (tj jakich narzedzi) [21:05:39] jak narazie piszemy pod linuxa [21:05:48] wiec narzedzia sa linuxowe.. mianowicie: [21:05:56] assembler: nasm (netwide assembler) [21:06:01] debugger: gdb [21:06:13] disasembler+binary tool: objdump [21:06:15] linker: ld [21:06:40] wiekszosc z tych narzedzi zazwyczaj wystepuje w kazdej dystrybucji [21:06:41] ;> [21:06:43] czesc czesc ;> [21:07:00] teraz tak [21:07:17] jako ze o linuxie bede ciagnac jeszcze z 2-3 wyklady max [21:07:22] a pozniej o windowsie [21:07:32] to chcial bym polecic wyklady z WinAPI, ktore to beda potrzebne na pozniej [21:08:00] WinAPI dla delphi bedzie wykladac d0uble_j (wg mojego terminarza pierwszy wyklad w niedziele o 20) [21:08:17] a WinAPI dla C/C++ bedzie wykladac codeguy, przed moimi wykladami z asma w poniedzialki [21:08:20] od 19:30 do 21 [21:08:52] python bedzie, jestem na etapie negocjacji z potencjalnym wykladowca ;> [21:09:00] wiec jakies info powinno sie do srody pojawic o terminie [21:09:16] pelna lista wykladow ofc jest na naszej stronce [21:09:20] http://wyklady.vexillium.org/ [21:09:29] dobra [21:09:31] tyle ogloszen [21:09:36] lecimy [21:10:12] wiec [21:10:16] przypomnienei co bylo ostatnio [21:10:24] ostatnio bylo w sumie samo wprowadzenie [21:10:32] troche pobawilismy sie jakims nieistniejacym asmem [21:10:51] ktory z przykladu na przyklad coraz bardziej przypominal to czego sie uzywa [21:10:58] czyli asma pod procki x86 ;> [21:11:09] na koncu wykladu byl jeden przyklad - hello world [21:11:18] ok [21:11:20] co bedzie dzisiaj [21:11:35] AMD tez jest x86 (kompatybilne) ;> [21:12:11] dzisiaj bedziemy sie dalej bawic hello worldami [21:12:15] tak, amd64 tez [21:12:27] amd64 moze dzialac w trybie 32 i 64 bitowych [21:12:29] ;> [21:12:36] a amd 85 nie znam =^^= [21:12:37] dobra [21:12:42] wracajac do tematu ;> [21:12:49] najpierw hello world [21:12:56] potem convention calle [21:13:06] i w miedzy czasie pobawimy sie troche gdb [21:13:12] zeby zobaczyc co sie dzieje w programie [21:13:31] zaczne od paru linkow [21:13:40] http://nasm.sourceforge.net/doc/html/nasmdoc0.html to jest dokumentacja nasma [21:13:48] wersja offline jest tu: http://nasm.sourceforge.net/doc/nasmdoc.pdf [21:14:07] nasm jest slicznie opisany, a na koncu w dodatku znajduje sie spis mnemonikow z wyjasnieniem co do czego [21:14:10] warto zajrzec [21:15:15] ok, 3 sekundy tylko moje przykladziki wyladuja na serverze [21:15:39] male przypomnienei w takim razie [21:15:49] conieco o samej budowie programu w asmie pod linuxem [21:16:18] 1) kod dzielimy na ten wrzucany do sekcji .text (sekcja kodu), oraz na ten wrzucany do sekcji .data (sekcja danych) [21:16:35] o sekcjach bedzie pozniej ;> [21:16:56] 2) do odwolan do funkcji systemowych, uzywamy przerwania int 80h [21:17:07] w rejestrze eax wrzucamy numer funkcji ktora chcemy wyolac [21:17:08] *wywolac [21:17:29] przykladowo uzywalismy juz funkcji 1 - exit [21:17:34] i funkcji 4 - write [21:17:52] taka mala uwaga [21:17:59] na koncu procesu TRZEBA uzyc funkcji exit [21:18:19] powniewaz w innym wypadku dostaniemy segfaulta (czyli blad programu, po czym program zostanie zamkniety) [21:18:26] albo nie daj boze cos sie popsuje ;> [21:19:07] (pod winda btw mozna po prostu "ret" uzyc.. coz.. pod linem widac nie) [21:19:19] ok [21:19:20] http://gynvael.vexillium.org/wyklady/hello_1.asm [21:19:26] to jest przyklad z poprzedniego wykladu [21:19:41] kompiluje sie nastepujaco: [21:19:48] nasm -f elf hello_1.asm [21:19:57] ld hello_1.o -o hello_1 [21:20:00] a odpala ./hello_1 [21:20:05] (czemu tak? bylo ostatnio) [21:20:26] gynvael@localhost:wyklady> ./hello_1 [21:20:26] Hello World [21:20:52] teraz tak [21:21:02] w tym przykladzie widac ze zapisujemy cos najpierw do sekcji danych [21:21:07] potem do sekcji kodu [21:21:13] ladnie, uporzadkowanie [21:21:21] ale nie musimy tak robic [21:21:31] mozemy na przyklad najpierw cos wrzucic do sekcji kodu [21:21:33] potem do sekcji danych [21:21:37] potem znowu do sekcji kodu [21:21:38] etc [21:21:49] http://gynvael.vexillium.org/wyklady/hello_2.asm [21:22:21] co nam to daje ? zalozmy ze mamy duzy plik, duzo funkcji [21:22:30] kazda ma jakies wlasne dane (zmienne globalne, napisy, etc) [21:22:45] dzieki temu dane od kazdej funkcji mozemy trzymac w zrodle "przy niej" [21:22:59] nie musimy scisle na poczatku pliku ;> [21:23:11] jako ciekawostke dodam [21:23:37] ze przykladowo kompilator jezyka C - gcc - wlasnie tak robi ;> (gcc -S zeby go zmusic do wygenerowania kodu asma) [21:23:50] ok [21:23:56] zanim przejdziemy dalej z hello world [21:24:01] pobawmy sie troche gdb [21:24:05] pare slow o tym narzedziu [21:24:37] gdb jest konsolowym debuggerem, prawie na kazdy system operacyjny [21:24:40] (tak, na winde tez jest) [21:25:06] przeciwnicy zarzucaja mu mala czytelnosc i skomplikowanie (na konsoli nie mozna tak ladnie wyswietlic danych jak graficznie) [21:25:25] a zwolennicy zachwalaja jego mozliwosci (np mozliwosc pisania skryptow) [21:25:47] sciagnicjcie najpierw przyklad [21:26:15] http://gynvael.vexillium.org/wyklady/trace_me.asm [21:26:25] eh w8 [21:26:28] przykladu nie wrzucilem [21:26:35] annihilator: to bylo ostatnio ;> [21:27:39] http://gynvael.vexillium.org/wyklady/trace_me.asm [21:27:40] ok [21:27:42] mamy taki przyklad [21:27:45] najpierw pare slow o nim [21:27:57] caly kod jest w sekcji .text [21:28:06] tzn caly kod "dotyczy" sekcji .text ;> [21:28:11] czyli nie mamy zadnych globalnych danych [21:28:55] global _start <=- to jest prosba do assemblera zeby wyexportowal symbol start.. tzn chodzi o to zeby w pliku obiektowym ( .o ) bylo zaznaczone ze _start ma adres taki i taki [21:29:01] ld (linker) korzysta z tego [21:29:19] _start: nop xchg eax, eax mov eax, 1 mov ebx, 2 mov ecx, 3 mov edx, 4 [21:29:22] eh... [21:29:30] _start: [21:29:38] nastepnie jest _start:, czyli etykieta ;> [21:29:40] bylo o nich ostatnio [21:29:45] a potem leca mnemoniki [21:29:48] troche o nich [21:29:52] pierwszy jest nop [21:29:58] nop pochodzi od slowa "no operation" [21:30:04] czyli jak mozna wynioskowac, nie robi kompletnie nic [21:30:15] warto zapamietac jego opcode, 0x90 ;> [21:30:24] hackerom roznej masci bardzo sie przydaje ;> [21:30:26] ale o tym bedzie pozniej [21:30:37] nastepnie jest xchg eax, eax [21:30:54] xchg dziala w ten sposob, ze zamienia rejestry wartosciami ;> [21:30:57] tzn przykladowo [21:31:01] xchg a, b [21:31:06] zalozmy ze a = 10, b = 20 [21:31:09] po xchg a,b [21:31:12] a = 20, b = 10 [21:31:21] czyli a dostalo wartosc b, i b dostalo wartosc a [21:31:31] u nas jest [21:31:35] xchg eax, eax [21:31:50] czyli co ? proboje zamienic miejscami wartosci rejestru eax z ... samym soba ?;> [21:32:03] jak mozna sie domyslic to nie robi dokladnie nic [21:32:14] i to jest inna postac mnemonika "nop" [21:32:30] ;> [21:32:53] ant_c: na privie twierdzi ze to to samo co xor eax, eax [21:33:01] sprawdzimy to za chwile ;> [21:33:04] coz ;> [21:33:15] jak mowilem wczesniej, nop i xchg eax, eax to dokladnie to samo [21:33:19] czyli brak operacji [21:33:31] (zobaczycie za chwile, jak sie gdb bedziemy bawic, ze to serio jest DOKLADNIE to samo ;>) [21:33:43] nastepnie jest pare instrukcji mov, czyli nadanie wartosci [21:33:45] mov eax, 1 [21:33:48] mov ebx, 2 [21:33:49] etc [21:34:00] nadajemy kazdemu z tych 4 rejestrow jakas wartosc [21:34:04] potem jest pusha [21:34:31] pusha == push all, i po prostu wrzuca wszystkie rejestry (z podstawowych) na stos [21:34:51] co to stos ? ;> [21:34:54] o tym pozniej [21:35:05] narazie powiem ze pusha nalezy rozumiec jako [21:35:11] "zapamietaj wartosci wszystkich rejestrow" [21:35:26] ok [21:35:28] lecimy dalej [21:35:31] push eax [21:35:32] pop ebx [21:35:41] push eax zapamietuje wartosc eax na stosie (tj wrzuca ja na stos) [21:36:05] a pop ebx SCIAGA PIERWSZA RZECZ ZE STOSU (to co przed chwila wrzucilismy) i wrzuca ja do ebx [21:36:08] te dwie instrukcje [21:36:09] push eax [21:36:11] pop ebx [21:36:19] mozna rozumiec jako mov eax, ebx [21:36:38] bo w sumie robi to samo (po za paroma efektami ubocznymi ktore rzadko kogo interesuja) [21:36:45] dalej mamy znowu dwa nadania [21:36:47] mov eax, 5 [21:36:50] mov ebx, 7 [21:36:58] oraz xchg, czyli zamiana miejscami wartosci [21:37:18] dostalem pytanie co do pop [21:37:32] pop pobierajac wartosc ze stosu, usuwa to wartosc [21:37:39] stos wyobrazcie sobie jako stos na przyklad monet [21:37:52] push wklada cos na czubek stosu (np monete 2zlotowa) [21:38:00] a pop sciaga ja stamtad i przeklada gdzies indziej [21:38:22] ok [21:38:26] -=213107=- <@Gynvael> mov eax, 5 [21:38:26] -=213109=- <@Gynvael> mov ebx, 7 [21:38:26] -=213117=- <@Gynvael> oraz xchg, czyli zamiana miejscami wartosci [21:38:30] wracajac do tego watku [21:38:44] po tej operacji ebx = 5, a eax = 7 ;> [21:38:50] potem jest dodanie do ecx wartosci ebx [21:38:54] czyli add ecx, ebx [21:39:09] a potem jest odjecie od edx 1 ;> (sub edx, 1) [21:39:28] nastepnie jest popa, czyli pobranie zapamietanych wczesniej wartosci ze stosu (mowie o pusha) [21:39:42] a nastepnie cos co nie jest juz mnemonikiem, tylko dyrektywa nasma [21:39:44] times 10.. [21:39:58] to wrzuca rzecz ktora jest po tym 10 razy do pliku [21:40:02] czyli np [21:40:06] times 2 nop [21:40:16] zrobi to samo co jak my bysmy wrzucili do kodu [21:40:17] nop [21:40:17] nop [21:40:33] ;> [21:40:38] u nas jest times 10 nop [21:40:43] ;> [21:40:45] tak for fun [21:40:46] ok [21:40:47] kompilujemy [21:41:45] ;> [21:41:47] tak tak;> [21:41:49] asemblujemy [21:41:59] aczkolwiek czesc ludzi ktora znam mogla by sie klucic [21:42:11] ;> [21:42:29] nasm trace_me.asm -f elf [21:42:36] ld trace_me.o -o trace_me [21:42:46] aha, odrazu mowie, ten program przy normalnym odpaleniu sie wywala [21:42:46] ;> [21:43:05] ;> [21:43:08] to nie jest blad ;> [21:43:10] tak mialao byc;> [21:43:14] ok [21:43:19] linkujemy ;> [21:43:28] konsolidujemy nie lubie.. ze tez wszystko musza spolszczac --; [21:43:32] nvm [21:43:43] gdb ./trace_me [21:43:47] tak odpalamy debugger [21:43:58] powinien wyswietlic swoja wersje i zglosic sie znakiem zachety [21:44:07] (gdb) [21:44:08] takim ;> [21:44:10] teraz tak [21:44:17] najpierw ustawimy jedna rzecz [21:44:36] mianowicie gdb defaultowo pokazuje listing disassemblera w skladni at&t [21:44:40] a my mowimy o skladni intela [21:44:43] wiec trzeba wklepac [21:44:54] (gdb) set disassembly-flavor intel [21:44:54] (gdb) [21:45:08] teraz tak [21:45:25] wiemy ze symbol _start jest wyexprotowany [21:45:33] (pamietacie global _start z kodu ne ?) [21:45:37] wiec mozemy napisac [21:45:41] disas _start [21:46:01] to wyswietli listing disasemblera dla "funkcji" (w bardzo duzym cudzyslowie) _start [21:46:04] co to disasembler ? [21:46:10] jak mowilem na #1, asm ma dwie postacie [21:46:14] czytelne dla nas mnemoniki [21:46:20] i czytelne dla procka opcody [21:46:32] assembler tlumaczy mnemoniki na opcody [21:46:40] natomiast disassembler robi to w druga strone [21:46:46] tlumaczy opkody na mnemoniki [21:47:02] dzieki czemu z kszaczkow mozemy uzyskac cos co latwiej (czasem) zrozumiec [21:47:19] oczywiscie nie dostajemy wtedy perfekcyjnego kodu zrodlowego [21:47:25] bo tego nei da sie automagicznie odzyskac 1:1 [21:47:36] dostajemy opcody przetlumaczone na mnemoniki [21:47:37] nic mniej [21:47:39] nic wiecej [21:47:41] ok [21:47:43] disas _start [21:47:59] powinien pojawic wam sie listing tego typu: [21:48:05] Dump of assembler code for function _start: [21:48:06] 0x8048080 <_start>: nop [21:48:06] 0x8048081 <_start+1>: nop [21:48:06] 0x8048082 <_start+2>: mov %eax,0x1 [21:48:06] 0x8048087 <_start+7>: mov %ebx,0x2 [21:48:08] 0x804808c <_start+12>: mov %ecx,0x3 [21:48:10] etc [21:48:28] na koncu powinno byc 10 instrukcji nop ;> to efekt tego co robi times 10 nop [21:48:38] po prostu wrzuca w kod 10 instrukcji i tyle [21:48:42] teraz tak [21:48:44] pierwsza rzecz [21:48:47] w kodzie mielismy [21:48:49] _start: [21:48:52] aa w8 [21:48:53] po kolei [21:49:00] co tam wogole widac na tym listingu [21:49:05] po pierwsze adres w hexa [21:49:23] systemy liczbowe hexa i binarne wypada znac jesli w asmie sie pisze ;> [21:49:28] serio, ulatwia to baaaaardzo duzo rzeczy [21:50:01] 0x8048087 [21:50:02] np to [21:50:12] to jest adres miejsca w pamieci gdzie jest dany op-code [21:50:34] <_start+7>: [21:50:44] to jest natomiast najblizszy symbol (dla nas to _start) [21:51:07] oraz przesuniecie.. czyli ile bajtow od _start jest ta instrukcja [21:51:17] adresy moga u was byc rozne ;> jak ant_c zauwazyl [21:51:33] zaleza one od assemblera, linkera, i samego systemu [21:51:45] wiec adresem sie nie przejmojcie ;> [21:52:02] po symbolu+przesunieciu jest juz mnemonic [21:52:06] mov %ebx,0x2 [21:52:25] % przy nazwie oznacza ze to rejestr.. coz. gdb tak ma ;> [21:52:41] warto zauwazyc ze liczby wszelkie (stale) pisane za w hexa [21:52:47] jak mowilem, warto sie tego systemu nauczyc ;> [21:53:17] ok [21:53:21] popatrzmy na nasz kod [21:53:27] na dwie pierwsze instrukcje po _Start [21:53:40] aa btw niektorzy mi zglaszaja [21:53:46] ze gdb u nich nie daje % przy rejestrach [21:53:51] coz ;> widac zalezy od wersji ;> [21:54:09] na shellu na ktorym testuje mam dosc stara ;> moze w nowszysch juz nie daje;> [21:54:18] nvm, to tylko oznaczenie [21:54:18] ;> [21:54:31] ok [21:54:34] -=214746=- <@Gynvael> na dwie pierwsze instrukcje po _Start [21:54:37] nop [21:54:41] xchg eax, eax [21:54:44] mowilem ze to JEST TO SAMO [21:54:52] rzucmy okiem co disasm pokazal [21:55:00] Dump of assembler code for function _start: [21:55:00] 0x8048080 <_start>: nop [21:55:00] 0x8048081 <_start+1>: nop [21:55:00] 0x8048082 <_start+2>: mov %eax,0x1 [21:55:04] dwa nopy [21:55:08] ;> [21:55:11] czyli nie klamalem [21:55:37] dla ludzi ktoorzy nadal mi nie wierza [21:55:42] mozna rzucic okiem na opcody [21:55:44] wystarczy napisac [21:55:47] x/2b _start [21:55:50] (gdb) x/2b _start [21:55:50] 0x8048080 <_start>: 0x90 0x90 [21:55:59] 0x90, czyli nop ;> jak mowilem ;> [21:56:14] coz, tak na prawde okazuje sie ze pare instrukcji w asmie ma rozne nazwy [21:56:31] np wlasnie xchg eax, eax, badz np skoki (je, etc) o ktorych bedzie potem [21:57:00] ok [21:57:03] ale o wszystkim po kolei [21:57:27] ok [21:57:27] ;> [21:57:29] mimo to [21:57:37] na privie mi zarzucaja ;> ze po prostu nasm tak robi [21:57:42] a nie ze jest tak na prawde [21:57:55] dalej w kodzie mamy innego xchg [21:57:59] 0x80480a3 <_start+35>: xchg %ebx,%eax [21:57:59] 0x80480a4 <_start+36>: add %ecx,%ebx [21:58:09] jak widac adresy roznia sie o 1, czyli sam opcode ma jeden bajt [21:58:19] za pomoca instruckji mozna sprawdzic opcode tego xchg [21:58:25] (gdb) x/b _start+35 [21:58:25] 0x80480a3 <_start+35>: 0x93 [21:58:36] przypominam ze xchg %eax, %eax to 0x90 [21:58:41] jak widac opcode jest bardzo podobny [21:59:01] jak by uzyc np xchg ecx, eax [21:59:06] to byl by rowniez zblizony [21:59:23] jesli nadal mi ktos nie wierzy to mozemy po wykladzie zajrzec do dokumentacji prockow intela ;> [22:00:22] pare info o opcodach [22:00:26] niektore zajmuja jeden bajt [22:00:29] inne wiecej [22:00:36] niektore po 5 [22:00:38] niektore po 7 [22:00:51] wszystko zalezy od samego opcodu i parametrow [22:00:56] na AMD MUSI BYC TAK SAMO ;> [22:01:04] inaczej by programy kompilowane na intelu [22:01:07] nie dzialaly na amd [22:01:14] a windows/linux wam dziala ne? [22:01:14] ;> [22:01:38] AMDki i Intele to ta sama klasa procesorow.. x386 compatible ;> [22:01:39] ok [22:01:42] ale lecimy dalej [22:01:45] teraz tak [22:01:56] najwazniejsza opcja debuggerka jest wstawienie breakpointa ;>>> [22:02:07] breakpoint to miejsce w ktorym debugger ma zatrzymac program [22:02:24] dzieki czemu my bedziemy mogli sobie poogladac np rejestry (pamiec, pozmieniac cos, etc) [22:02:35] w gdb breakpoitn wrzuca sie za pomoca komendy break [22:02:38] break symbol [22:02:41] break *0xADRES [22:02:54] wrzucmy breakpoint na DRUGA instrukcje [22:03:13] czemu nie na pierwsza? z jakiegos powodu gdb nie lapie zadnych breakpointow na pierwszej instrukcji --; [22:03:19] jak dojde CZEMU to wam powiem ;> [22:03:22] narazie po prostu nie wiem [22:03:30] ale na druga lapie wiec tam wrzucamy [22:03:51] break *(_start+1) [22:03:59] _start+1 to juz nie jest symbol [22:04:00] tylko adres [22:04:03] wiec trzeba * uzyc ;> [22:04:37] (gdb) break *(_start+1) [22:04:37] Breakpoint 1 at 0x8048081 [22:04:48] i teraz jeszcze uruchamiamy program [22:04:55] za pomoca komendy r (jak run) [22:04:59] (gdb) r [22:04:59] Starting program: /home/gynvael/wyklady/./trace_me [22:04:59] Breakpoint 1, 0x08048081 in _start () [22:05:08] powinno cos takiego sie wam pojawic (mniej wiecej ofc) [22:05:21] i gdb powinien wyswietlic znak zachety [22:05:28] co oznacza ze ktorys breakpoint "wskoczyl" [22:05:41] tym razem jest to Breakpoint 1 (nad znakiem zadchety pisze) [22:05:54] o tym jak dzialaja breakpointy to mowil nie bede teraz; > bedzie przy okazji wykladu o reversingu [22:06:22] ok [22:06:25] teraz tak [22:06:27] jestesmy gdzies [22:06:30] nikt nie wie gdzie [22:06:32] znamy adres [22:06:39] 0x08048081 [22:06:43] (u mnie) [22:06:46] mozemy zrobic tak: [22:06:52] disas [22:07:09] to wystili kod "funkcji" w ktorej jestesmy (jesli gdb uda sie ja polaczyc z jakims symbolem) [22:07:15] ew, co jest duzo wygodniejsze imho [22:07:16] mozemy napisac [22:07:19] x/10i $eip [22:07:26] co ta "magiczna" instrukcja robi ? [22:07:38] ogolnie x powoduje wypisanie czegos z spod podanego adresu [22:07:45] po / podajemy w jakiej formie i ile [22:07:51] 10i oznacza "10 instrukcji" [22:07:53] a adresem jest $eip [22:07:56] co to jest $eip ? [22:08:33] ogolnie EIP to jest rejestr (tzw Instruction Pointer), czyli adres instrukcji ktora za chwile bedzie wykonana (ogolnie z poziomu asma jawnie nie da sie zmienic tego rejestru ani odczytac, ale mozna kombinowac.. o tym potem) [22:09:48] (gdb) x/10i $eip [22:09:48] 0x8048081 <_start+1>: nop [22:09:48] 0x8048082 <_start+2>: mov %eax,0x1 [22:09:48] 0x8048087 <_start+7>: mov %ebx,0x2 [22:09:48] 0x804808c <_start+12>: mov %ecx,0x3 [22:09:51] etc [22:09:56] to daje mniej wiecej wglad gdzie jestesmy [22:11:02] hmm [22:11:07] u paru osob nie dziala [22:11:11] tzn nie zaskakuje breakpoint [22:11:18] jak by te osoby moglu sprobowac zrobic: [22:11:26] awatch *(_start+2) [22:11:29] i wtedy odpalic program [22:11:36] i sprawdzic czy ten breakpoint poskutkuje [22:11:49] (awatch to tzw hardware breakpoint, o tym potem) [22:12:11] a reszta, no coz, lecimy [22:12:12] teraz tak [22:12:22] zeby wyswietlic info o rejestrach uzywamy [22:12:27] info reg [22:12:37] z tym ze to wyswitli przydlugawa liste [22:12:43] nas interesuja tylko 4 rejestry [22:12:44] wiec piszmy [22:12:52] info reg eax edx ecx ebx [22:13:02] (gdb) info reg eax edx ecx ebx [22:13:02] eax 0x0 0 [22:13:02] edx 0x0 0 [22:13:02] ecx 0x0 0 [22:13:02] ebx 0x0 0 [22:13:17] jak widac wszystkie 4 rejestry maja teraz wartosci 0 [22:14:28] teraz tak [22:14:41] mamy dwie metody zeby kazac isc debugerowi o JEDEN KROK DO PRZODU [22:14:52] instruckje step i next [22:14:55] (albo s i n) [22:15:05] mozecie napisac help s i help n zeby poczytac czym sie roznia [22:15:16] roznica jest taka [22:15:33] ze "s" gdy zobaczy wywolanie funkcji (call), wchodzi do tej funkcji [22:15:35] a "n" nie ;> [22:15:40] ale my nie mamy funkcji [22:15:44] wiec jedziemy po kolei [22:15:53] napiszcie s 5 [22:17:04] powinno wam sie przejsc o pare instrukcji do przodu [22:17:25] jesli komus nie dziala [22:17:36] to niech po prostu breakpoint tam wstawi (tj za 5 instrukcji) [22:17:52] (gdb) x/10i $eip [22:17:52] 0x8048081 <_start+1>: nop [22:17:52] 0x8048082 <_start+2>: mov $0x1,%eax [22:17:52] 0x8048087 <_start+7>: mov $0x2,%ebx [22:17:52] 0x804808c <_start+12>: mov $0x3,%ecx [22:17:55] 0x8048091 <_start+17>: mov $0x4,%edx [22:17:57] np u mnie to _start+17 [22:18:01] (gdb) break *(_start+17) [22:18:01] Breakpoint 2 at 0x8048091 [22:18:03] (gdb) c [22:18:06] Continuing. [22:18:09] Breakpoint 2, 0x08048091 in _start () [22:18:11] (gdb) [22:18:16] "c" to jest "continue", czyli kontynuuj wykonanie [22:18:37] zostaly wykonane 3 instrukcje (i nop) do tej pory [22:19:02] czyli mov eax, 1; mov ebx, 2; mov ecx, 3 [22:19:14] wiec rejestry te powinny miec dane wartosci [22:19:15] sprawdzmy [22:19:21] info reg eax edx ecx ebx [22:19:32] (gdb) info reg eax edx ecx ebx [22:19:33] eax 0x1 1 [22:19:33] edx 0x0 0 [22:19:33] ecx 0x3 3 [22:19:33] ebx 0x2 2 [22:19:39] u mnie tak jest ;> [22:20:08] sprawdzmy wiec gdzie jestesmy [22:20:13] x/5i $eip [22:20:21] (gdb) x/5i $eip [22:20:21] 0x8048091 <_start+17>: mov %edx,0x4 [22:20:21] 0x8048096 <_start+22>: pusha [22:20:21] 0x8048097 <_start+23>: push %eax [22:20:21] 0x8048098 <_start+24>: pop %ebx [22:20:23] 0x8048099 <_start+25>: mov %eax,0x5 [22:20:26] i idzmey powiezmy do _start+25 [22:20:32] (znowu breakpoint najlepiej) [22:20:38] break *(_start+25) [22:20:52] (gdb) break *(_start+25) [22:20:52] Breakpoint 3 at 0x8048099 [22:20:52] (gdb) c [22:20:52] Continuing. [22:20:52] Breakpoint 3, 0x08048099 in _start () [22:21:02] teraz wykonaly sie mov edx, 4 [22:21:06] oraz pusha [22:21:10] push eax i pop ebx [22:21:15] na mov eax, 5 wlasnie jestesmy [22:21:28] mowilem ze push eax ; pop ebx zadziala identycznie jak mov ebx, eax [22:21:37] wiec w ebx powinnna byc wartosc 1 [22:21:43] (gdb) info reg ebx [22:21:43] ebx 0x1 1 [22:21:50] jest 1 jak widac [22:22:06] (gdb) x/5i $eip [22:22:06] 0x8048099 <_start+25>: mov %eax,0x5 [22:22:06] 0x804809e <_start+30>: mov %ebx,0x7 [22:22:06] 0x80480a3 <_start+35>: xchg %ebx,%eax [22:22:06] 0x80480a4 <_start+36>: add %ecx,%ebx [22:22:09] 0x80480a6 <_start+38>: sub %edx,0x1 [22:22:14] break *(_start+38) [22:22:33] (gdb) break *(_start+38) [22:22:33] Breakpoint 4 at 0x80480a6 [22:22:33] (gdb) c [22:22:33] Continuing. [22:22:33] Breakpoint 4, 0x080480a6 in _start () [22:22:40] wykonaly sie teraz nastepujace operacje [22:22:41] mov eax, 5 [22:22:43] mov ebx, 7 [22:22:47] xchg ebx, eax [22:22:51] add ecx, ebx [22:23:03] wiec w eax powinno byc 7, w ebx 5 [22:23:26] a w ecx (w ktorym bylo 3) powinno byc 3+7, czyli 10 [22:23:34] (gdb) info reg eax ebx ecx [22:23:34] eax 0x7 7 [22:23:34] ebx 0x5 5 [22:23:34] ecx 0x8 8 [22:23:38] chyba nie klamei zbytnio [22:23:38] ;> [22:24:00] etc [22:24:08] mozna tak dalej analizowac program [22:24:12] ale to pozostawiam wam do zabawy [22:24:16] ok [22:24:33] teraz pytanka a potem hello world CD (czyli przerobienie tego zeby dzialalo na ASCIIZ) [22:31:42] lecimy dalej [22:31:47] Stops the execution of the program 5 bytes after the address labeled by _start. Due to a bug in gdb, break *_start does not stop the program before the execution of the first instruction. A workaround is to add a no operation instruction (mnemonic "nop") to the beginning of your program and use: [22:31:52] cos takiego znalazlem na googlach [22:31:59] czyli niby blad w gdb [22:32:08] ze u niektorych to sie haczy [22:32:10] I nie przeszkadzac wykladowcy na priv [22:32:10] :p [22:32:13] teraz tak [22:32:31] teraz tak [22:32:35] co do "s" i "n" [22:32:39] uzywajcie "si" i "ni" [22:32:47] to wtedy powinno dobrze dzialac [22:33:31] step instruction [22:33:33] i next instruction [22:33:43] czyli w sumie "krok o jedna instruckje" [22:33:46] w sumie moj blad [22:33:50] bo powinienem od tego zaczac [22:33:53] a nie "s" i "n" [22:33:53] ;> [22:33:54] sorx [22:34:00] ok [22:34:02] ale lecimy dalej [22:34:09] waracamy do naszego slicznego hello world [22:35:08] http://gynvael.vexillium.org/wyklady/hello_1.asm [22:35:16] to jest to pierwsze hello world [22:35:22] jedna rzecz ktora mi sie tam nie podoba [22:35:28] to helloLen: equ $-hello [22:35:55] czyli w sumie jest to STALA w ktorej jest WIELKOSC (ilosc bajtow) zajmowana przez napis "Hello World" [22:36:12] coz [22:36:19] powiedzmy sobie ze jest to dla nas malo wygodne [22:36:25] pisac taka linijke po kazdym napisie [22:36:43] mamy wiec do wyboru pare pomyslow [22:36:51] albo zrobimy jak jest w pascalu / javie [22:37:05] czyli napis poprzedzimy jego wielkoscia [22:37:07] ale to w sumie to samo [22:37:10] czyli bez sensu [22:37:18] albo jak w C, czy starym dobrym dosie, wprowadzimy terminator [22:37:34] w dosie napis konczylo sie znakiem "$", ale $ moze sie w tekscie pojawic, wiec to do bani pomsyl [22:37:42] (nie zebym mial cos do billa g. ;p) [22:37:58] w C stosuje sie tzw ASCIIZ [22:38:06] czyli ASCII string Zero-terminated [22:38:15] czyli lancuch znakow ascii zakonczony bajtem zerowym [22:38:20] o tym troche bylo na wykladzie z C [22:38:24] ok [22:38:28] wiec pomysl brzmi tak [22:38:39] wrzucimy sobie bajt 0 na koniec napisu [22:38:45] hello: db 'Hello World', 10, 0 [22:38:47] na przyklad tak [22:39:00] po czym zrobimy krotka funkcje ktora policzy znaki od poczatku napisu do 0 [22:39:03] i juz mamy dlugosc [22:39:27] jak to zrobic ? [22:39:33] w sumie w C bysmy zrobili tak: [22:39:46] p = adres_napisu; [22:39:54] while( *p != '\0' ) p++; [22:40:00] po czym p - adres_napisu to byla by dlugosc [22:40:11] tutaj mozemy rowniez uzyc tego sposobu [22:40:19] natoamist trzeba zapisac to inaczej [22:40:23] http://gynvael.vexillium.org/wyklady/hello_3.asm [22:40:29] tam jest to rozpisane [22:40:31] pomysl jest taki [22:40:57] do ESI i EDI wrzucamy adres hello (to tez sa rejestry ogolnego uzytku ;>) [22:41:20] po czym przesuwamy EDI do przodu dopuki to co jest pod adresem EDI nie bedzie zerem [22:41:27] a potem odejmujemy EDI - ESI i mamy dlugosc [22:41:27] ;> [22:41:34] po kolei [22:41:40] lea esi, [hello] ; to samo co mov edi, hello [22:41:48] lea to nowy mnemonik ;> [22:41:56] mozecie sie z nim przywitac albo cos [22:42:08] lea wywodzi sie od slow Load Effective Address [22:42:23] a w sumie robi to samo co mov esi, hello [22:42:36] notacja [costma] pojawia sie tu pierwszy raz [22:42:41] teraz cos dla panow od C ;> [22:42:51] lea esi, [hello] to to samo co [22:43:01] esi = &*hello; [22:43:09] czyli w sumie [22:43:16] esi = &costam; [22:43:27] natomiast samo [costam] to jest *costam [22:43:35] a dla reszty nie znajacych C [22:43:48] lea esi, [hello] wrzuca do ESI ADRES hello [22:44:24] natomiast np mov esi, [hello] skopiowalo by 4 bajty (bo taka jest wielkosc rejestru esi) Z ADRESU "hello" [22:44:39] mam nadzieje ze na przykladzie lepiej to bedzie widac;> [22:44:41] ok [22:44:58] lea esi, [hello] <=- ladujemy adres PIERWSZEGO BAJTU "hello" do esi [22:45:11] mov edi, esi <=- powielamy wartosc esi do edi [22:45:23] zalozmy ze adresem hello jest 0x1000 [22:45:31] czyli teraz edi = 0x1000 i esi = 0x1000 [22:45:48] a pod adresem 0x1000 w pamieci jest znak H (od Hello World) [22:46:00] po tym jest edykieta "petla" [22:46:07] a po tym jakies cudo na kiju [22:46:16] cmp byte [edi], 0 ; sprawdz czy edi wskazuje 0 [22:46:17] ok [22:46:21] co to jest [22:46:26] cmp == compare == porownaj [22:46:39] narazie powiem tyle, ze cmp powronuje dwie rzeczy [22:46:55] jesli sa rowne to ustawia flage zerowa (o niej dokladnie za chwile) [22:47:01] a jesli nie sa, to jej nie ustawia [22:47:09] z tym ze to wierzcholek gory lodowej jesli chodzi o cmp [22:47:24] w dokumentacjach roznych cmp jest opisane jako "mental substract" [22:47:32] czyli "odejmowanie w pamieci, bez zapisywania wyniku" [22:47:38] cmp a, b [22:47:48] czyli cmp robi a - b [22:47:52] i nie zapamietuje wyniku [22:47:53] ALE [22:47:54] no wlasnie [22:47:55] ALE... [22:48:09] procek ma cos takiego jak FLAGI.. o nich bedzie duuzoo [22:48:46] narazie powiem tylko [22:48:55] ze jest sobie flaga ZF (Zero Flag) [22:49:08] flaga to po prostu flaga.. wyobrazcie sobie skrawek materialu na kiju [22:49:26] jesli flaga jest podniesiona (ZF ma wartosc 1), to znaczy ze WYNIKIEM OSTATNIEJ DOWOLNEJ OPERACJI BYLO 0 [22:49:30] (slownie, ZERO) [22:49:51] natomiast jesli jest opuszczona (ZF ma wartosc 0), to znaczy ze WYNIKIEM OSTATNIEJ OPERACJI BYLO COS INNEGO NIZ ZERO [22:50:37] przyukladowo [22:50:39] mov eax, 5 [22:50:42] sub eax, 5 [22:50:48] wynikiem ostatniej operacji bylo 0 [22:50:51] (noo 5-5 to 0) [22:50:59] czyli po tym ZF = 1 (jest ustawiona) [22:51:28] WAZNA RZECZA JEST FAKT, ZE OPERACJA MOV, OPERACJE PUSH I POP, I PARE INNYCH NIE ZMIENIAJA WARTOSCI FLAGI ZF [22:51:43] przyklad z tym zwiazany bedzie za nieduza chwile [22:51:43] ;> [22:51:49] ok [22:51:57] czyli mamy osbie flage ZF ktora jest podniesiona jak bylo 0 [22:52:01] i oposzczona jka nie bylo [22:52:03] ql [22:52:18] cmp jak mowilem, to jest odejmowanie w pamieci, bez zapisywania wyniku [22:52:27] ALE flaga ZF jest odpowienio ustawiana! [22:52:30] przykladowo [22:52:32] mov eax, 5 [22:52:34] cmp eax, 5 [22:52:40] 5-5 to 0 [22:52:42] wiec ZF=1 [22:52:46] mov eax, 7 [22:52:51] cmp eax, 5 [22:52:58] 7-5 to nie 0, wiec ZF=0 [22:53:10] z flagi zerowej korzysta nastepna instruckja, czyli jz [22:53:31] jz (jump if zero - skocz jesli ZF jest ustwione) skacze pod podany adres (podana etykiete) [22:53:38] jesli flaga ZF jest ustawiona [22:53:49] jej aliasem jest je (jump if equal - skocz jesli rowne) [22:53:56] bo w sumie chciec nie chciec [22:54:00] jesli dwie liczby sa rowne [22:54:08] to jak sie je odejmnie od siebie, wychodzi 0 [22:54:11] ok [22:54:15] cmp byte [edi], 0 [22:54:19] ale co to za dziwolag [22:54:21] po kolei [22:54:24] co to cmp to juz wiemy [22:54:27] byte [edi] [22:54:29] to jest calosc [22:54:38] to oznacza "bajt spod adresu EDI" [22:54:59] pamietamy ze EDI to dla nas w tej chwili 0x1000, i pod tym adresem w pamieci jest pierwsza litera "Hello World" ? [22:55:03] tak ? to good ;> [22:55:28] czyli w sumie to byte [edi] jest "zastepywane" (w procku) literka "H" (w pierwszym wywolaniu) [22:56:08] "H" jest dla nas [22:56:15] procesor widzi ofc jej kod ascii [22:56:17] czyli 0x48 [22:56:27] czyli [22:56:31] cmp 0x48, 0x0 [22:56:40] porownuje literke wskazana przez EDI z 0 [22:56:49] literke spod adresu EDI ;> [22:57:13] czyli.. sprawdza czy to koniec stringu ;> jesli tak, ustawia ZF=1 (wkoncu jak koniec, to EDI wskazuje na 0, a 0-0 to 0, wiec ZF=1) [22:57:16] niom [22:57:22] jakos przebrnalem przez to [22:57:25] dalej juz proste rzeczy [22:57:28] jz bylo przed chwila [22:57:46] jz wyskoczy z petli jak cmp napotka na terminator, czyli 0 [22:57:56] inc edi - zwiekszenie adresu o 1 [22:57:58] czyli 0x1001 [22:58:03] a tam jest druga literka wyrazu [22:58:07] czyli "e" [22:58:11] i jmp petla [22:58:21] jmp to skok BEZWARUNKOWY (czyli zadne flagi nas nie obchodza) [22:58:31] do podanego adresu (etykiety) [22:58:50] caly ten kod dla programisty w C to po prostu while (*(char*)edi!='\0') edi++; [22:59:01] padlo na privie pytanie [22:59:07] czemu EDI i ESI [22:59:11] a nie na przyklad EAX? [22:59:15] coz ;> tak mi bylo wygodniej ;> [22:59:21] innego powodu brak w tej chwili [22:59:38] mozan bez problemu uzyc ebx i eax np [22:59:40] ok [22:59:42] wiec [22:59:47] od petla: do jmp petla [22:59:50] ten fragment [22:59:56] przesunie EDI na koniec napisu (tam gdzie jest 0) [23:00:04] czyli wystarczy jeszcze od EDI odjac ESI [23:00:06] i mamy dlugosc [23:00:45] ok [23:01:22] po tej petli mamy w EDI 0x100C (czyli 0x1000 + 12 znakow) [23:01:28] teraz ZF=1 [23:01:32] i skok do "koniec_petli" [23:01:55] koniec_petli: [23:01:55] mov edx, edi ; wrzucmy adres konca napisu do edx [23:01:55] sub edx, esi ; i odejmijmy adres poczatku [23:01:56] ; dzieki temu uzyskamy dlugosc [23:01:58] tam robimy [23:02:08] to o czym mowilem wczesniej [23:02:10] z tym ze [23:02:16] pamietamy po co liczymy ta cholerna dlugosc ? [23:02:30] zeby ja wstawic do rejestru EDX zeby uzyc funkcji "write" z kernela (int 80h) [23:02:31] ;> [23:02:45] wiec robimy w zasadzie EDX = EDI - ESI [23:02:55] w moim przypadku jest to rozbite na instrukcje [23:03:02] edx = edi [23:03:05] edx -= esi [23:03:10] mozna by zrobic np [23:03:16] sub edi, esi [23:03:20] mov edx, edi [23:03:25] na jedno wyjdzie [23:03:31] ok, dlugosc mamy w edx [23:03:45] potem jest to co bylo w hello_1.asm i _2.asm [23:03:52] wiec po prostu wywolanie write [23:03:54] i potem exit [23:04:02] koniec tlumaczenia tego przykladu ;> [23:04:12] gynvael@localhost:wyklady> ./hello_3 [23:04:12] Hello World [23:04:15] u mnie dziala ;> [23:04:16] ok [23:04:28] teraz tak, za chwile powiem o rejestrach [23:04:34] tzn jakie i do czego sa [23:04:44] a potem coz, chyba bedzie trzeba konczyc [23:04:57] zostane z 30 minutek jeszzcze i bede odpowiadal na ewentualne pytanka jesli beda [23:05:26] przyklad z flagami i konwencje wywoalania beda w takim razie przeniesione na za tydzien [23:05:32] za tydzien tym samym ostatni wyklad na linuxie [23:05:39] potem idziemy na winde [23:05:51] powiem tyle, ze asm tam sie duzo nie rozni [23:05:58] ehehe [23:06:01] no dobra ;> [23:06:06] moze jeszcze 2 wyklady na linie [23:06:08] a potem windows ;> [23:06:15] do linuxa i tak wrocimy jeszzcez [23:06:22] z uwagi na at&t i gnu as ;> [23:06:26] ale ok [23:06:29] teraz troche o rejestrach [23:06:35] jako ze w sumie duzo o nich nie mowilem [23:06:35] ;> [23:06:39] tyle ze sa ;> [23:06:49] ant_c: polecam qemu ;> [23:06:52] cli: j/w ;> [23:07:00] To sobie kupcie. [23:07:01] ;p [23:07:03] eh [23:07:04] ;> [23:07:08] cicho [23:07:10] dobra [23:07:12] Gynvael: kontynuuj [23:07:14] kk [23:07:15] ;> [23:07:16] dobra [23:07:17] wiec [23:07:28] kazdy rejestr ma jakies tam swoje przeznaczenie [23:07:36] po kolei [23:08:39] EAX - rejestr akumulator ;> do czego mial byc uzywany ? nie wiem ;> ale jest to rejestr ogolnego uzytku, ciekawa role odgrywa przy dzieleniu (tam jest liczba dzielona, a przynajmniej jej dolna czesc) [23:09:06] po za tym programisci upodobali sobie ten rejestr do zwracania tam wartosci funkcji (np taki return 1; w C robi po prostu mov eax, 1 i wychodzi z funkcji) [23:09:27] czasem (przy konwencji wywolania fastcall) jest to rejestr uzywany do przekazywania argumentu [23:09:38] ogolnie ten rejest powinien miec swoj fanklub, bo wszedzie go pelno [23:09:38] ;> [23:10:11] EBX - rejestr bazowy... w 32bitowym asmie w sumie do niczego specialnego nei jest wykozystywany (czasem do przekazywania argumentow funkcji...) [23:10:51] hehe ant_c ;> jak masz ciekawego linka tyo daj na priva to wrzuce na kanal [23:10:52] ;> [23:10:56] ok [23:11:25] ECX - counter - licznik.. jego znacie z instrukcji loop.. ogolnie przy wszystkich instrukcjach powtorzeniowych (rep*, bedzie potem) sie pojawia [23:12:19] EDX - data - rejestr danych (jak cala reszta).. uzywany jest przy dzieleniu jako gorna czesc liczby (o tym bedzie potem), po za tym mozna korzystac z niego na lewo i prawo [23:12:40] tyle "X" ow [23:12:47] kazdy z nich dzieli sie na mniejsze czesci [23:12:53] (EAX -> AX -> AL, AH) [23:13:02] ale to was odesle gdzies zebyscie sobie poczytali ;> [23:13:10] http://www.republika.pl/skowi_magik/rejestry.htm [23:13:16] http://pl.wikipedia.org/wiki/Asembler_x86 [23:13:20] takie linki mi na priva podaja ;> [23:13:23] wiec pewnie tam cos jest; > [23:13:25] teraz tak [23:13:29] po tyhc 4rech podstawowych [23:13:31] sa ESI i EDI [23:13:44] (ktore za duzo sie nie dziela, tylko SI i DI, ale raczej sie nie korzysta) [23:13:53] ESI - Source Index - index zrodla [23:14:07] EDI - Dest. Index - index celu [23:14:16] zazwyczaj jako pointery (badz indexy) sa uzywane [23:14:35] przy wszelkich instrukcjach przepisujacych (rep* costam, bedzie potem) sa uzywane jako pointerki [23:14:46] osobiscie lubie z nich korzystac jak z pointerow ;> [23:14:55] (mimo ze z kazdego rejestru mozna ;>) [23:15:00] po nich jest EBP [23:15:12] EBP - bottom/base pointer [23:15:36] narazie powiem tyle, ze jest to adres dna ramki stosu ;> co to ? bede wyjasnial pozniej [23:16:01] powiem tylko ze kompilatory upodobaly sobei ten rejestr zeby przechowywac w nim adres dna ramki stosu, i wg tego rejestru adresowac zmienne lokalne (uf ;p) [23:16:23] (ale na szczescie nie kazdy kompilator tak robi.. wkoncu to calkiem dobry rejestr) [23:16:32] i ESP [23:16:46] ESP to Stack Pointer, adres OSTATNIEGO ELEMENTU WRZUCONEGO NA STOS [23:16:49] pamietacie push ? [23:16:51] push eax etc ? [23:17:03] po kazdym push od ESP jest ODEJMOWANE 4 (32 bity = 4 bajty) [23:17:17] a po kazdym POP do ESP sa DODAWANE 4 bajty [23:17:32] (tak, stos "ROSNIE" do zera.. i tak, stos jest po prostu miejscem w pamieci) [23:17:38] ale o stosie bedzie pozniej [23:17:39] powiem tak [23:17:44] ESP NIE DOTYKAC, jesli sie nie wie co sie robi [23:18:00] ;> [23:18:10] po za tym jest jeden niejawny rejestr [23:18:14] EIP - instruction pointer [23:18:21] czyli adresi instrukcji ktora za chwile bedzie wykonana [23:18:28] niejawny dlatego ze nie mozemy napisac np [23:18:31] mov eip, adres [23:18:33] ale ;> [23:18:37] pamietacie co jmp robi ? [23:18:49] przenosi nas gdzies indziej w kodize.. takie GOTO basicowe [23:18:52] czyli [23:18:55] mov eip, adres [23:18:56] to po prostu [23:18:58] jmp adres [23:19:47] natoamiast zeby pobrac eip to huh [23:19:52] powiedzmy ze sa pewne triki [23:19:54] takie jak: [23:20:00] call costam [23:20:02] costam: [23:20:03] pop esi [23:20:21] i juz w esi mamy adres "costam", czyli wartosc eip z przedchiwli [23:20:39] coz, pociesze tylko ze wartosc EIP zadko do czegos jest potrzebna [23:20:44] (klania sie SME i shellcody) [23:21:03] teraz tak [23:21:11] wszystko co wymienilem przed chwila ma 32 bity [23:21:14] czyli 4 bajty [23:21:20] a co tam bedzie zapisane [23:21:24] czy to liczba calkowita [23:21:27] czy naturalna [23:21:30] czy 4 literki stringu [23:21:32] czy jeden znak [23:21:34] czy co [23:21:39] to juz zalezy tylko i wylacznie od nas [23:21:55] i od tego jakimi instrukcjami operujemy na rejestrach i czego od nich oczekujemy [23:21:58] ok [23:21:59] na dzisiaj tyle [23:22:00] teraz tak [23:22:03] nastepny wyklad planowo [23:22:07] za tydzien [23:22:11] o 21 w poniedzialek [23:22:18] ALE.. moze sie zdarzyc ze bedzie odwolany [23:22:31] powniewaz nie wiem czy na stancji nadal mam net (na studia jade...) [23:23:39] ok [23:23:41] tyle [23:23:42] ;ppp [23:23:45] nie moge ;ppp [23:23:46] ehehe [23:23:48] ciekawe sa ;p [23:23:50] ok [23:23:52] teraz tak [23:23:59] odpowiem na pare zaleglych pytan [23:24:03] i zdejmuje +m [23:24:05] informa ;> [23:24:21] wrocek polibuda [23:24:22] ;> [23:24:25] dobra [23:24:28] pytanie padlo [23:24:35] czy jak mamy taka sytuacje: [23:24:43] mov eax, 0xffffffff (czyli pelen rejestr) [23:24:49] i wrzucamy jakas mala wartosc [23:24:49] np [23:24:51] 5 [23:24:55] mov eax, 5 [23:25:12] to czy po tym zostanie nadpisana czesc eax [23:25:13] czy calosc [23:25:18] no wiec zostanie nadpisana calosc [23:25:21] ale [23:25:24] mozemy np zrobic [23:25:26] mov ax, 5 [23:25:29] albo mov al, 5 [23:25:30] albo [23:25:33] mov ah, 5 [23:25:37] zalezy co chcemy uzyskac [23:25:43] (macie poczytac o tych al ax i ah) [23:25:50] odpowiednio w eax po tych operacjach znajdzie sie [23:26:00] mov ax, 5; 0xffff0005 [23:26:04] mov ah, 5; 0xffff05ff [23:26:07] mov al, 5; 0xffffff05 [23:26:25] ok [23:26:30] teraz pytanka ;> [23:26:38] btw lista zadanek bedzie rano ;>