Asembler x86/Jak używać debuggera ALD: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Linia 187:
#wyjscie
incl %eax
incl %ebx
int $80h
 
Linia 212:
decl %ecx
movl %ecx($msg),%dl
cmpl $0orl %ecx,%ecx
jne jnz N1
 
movl $4,%eax
Linia 245:
Chcielibyśmy zatem wstrzymać działanie programu tuż przed wykonaniem tej operacji, by dokładnie sprawdzić argumenty instrukcji oraz wynik jej działania. W tym celu uruchamiamy debugger poleceniem:
 
<source lang=textbash>
user@myhost:~$ ./ald decimalPrint
Assembly Language Debugger 0.1.7
Copyright (C) 2000-2004 Patrick Alken
 
decimalPrint: ELF Intel 80386 (32 bit), LSB - little endian, Executable, Version 1 (Current)
Loading debugging symbols...(11 symbols loaded)
ald>
</source>
 
Następnie przeprowadzamy deasemblację (klawisz '''d''' i '''ENTER''') w celu poznania adresu wskaźnika do interesującej na instrukcji:
 
<source lang=textbash>
ald> d
# 08048080:<_start> B807000000 mov eax, 0x7
# 08048085 E80C000000 call near +0xc (0x8048096:_printEAXdecimal)
# 0804808A B801000000 mov eax, 0x1
# 0804808F BB05000000 mov ebx, 0x5
# 08048094 CD80 int 0x80
# 08048096:<_printEAXdecimal> 52 push edx
# 08048097 51 push ecx
# 08048098 53 push ebx
# 08048099 50 push eax
# 0804809A BB0A000000 mov ebx, 0xa
# 0804809F B90A000000 mov ecx, 0xa
# 080480A4 31D2 xor edx, edx
# 080480A6:<N1> F7F3 div ebx
# 080480A8 81C230000000 add edx, 0x30
# 080480AE 49 dec ecx
# 080480AF 8891D8900408 mov byte [ecx+0x80490d8], dl
# 080480B5 81F900000000 cmp ecx, 0x0
# 080480BB 75E9 jne +0xe9 (0x80481a6)
# 080480BD B804000000 mov eax, 0x4
# 080480C2 BB01000000 mov ebx, 0x1
# 080480C7 B9D8900408 mov ecx, 0x80490d8
# 080480CC BA0A000000 mov edx, 0xa
# 080480D1 CD80 int 0x80
# 080480D3 58 pop eax
# Hit <return> to continue, or <q> to quit
</source>
 
Naciskamy klawisz '''q''' oraz '''ENTER''', by nie wyświetlać dalszych obszarów pamięci. Szukany adres to ''0x080480A6''. Trzeba zatem pod wskazanym adresem ustawić pułapkę. Do tego celu służy polecenie '''break''':
 
<source lang=textbash>
ald> break 0x080480a6
# Breakpoint 1 set for 0x080480A6
ald>
</source>
 
Dla pewności możemy wyświetlić wszystkie zdefiniowane pułapki, aby mieć pewność, czy program nie będzie dodatkowo wstrzymany w żadnym innym miejscu. Do tego celu służy polecenie '''lbreak''':
 
<source lang=textbash>
ald> lbreak
# Num Type Enabled Address IgnoreCount HitCount
# 1 Breakpoint y 0x080480A6 none 0 (N1+0x0)
ald>
</source>
 
Jeśli wszystko się zgadza, możemy uruchomić program poleceniem '''run''':
 
<source lang=textbash>
ald> run
# Starting program: decimalPrint
# Breakpoint 1 encountered at 0x080480A6
# eax = 0x00000007 ebx = 0x0000000A ecx = 0x0000000A edx = 0x00000000
# esp = 0xBFC9251C ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000
# ds = 0x007B es = 0x007B fs = 0x0000 gs = 0x0000
# ss = 0x007B cs = 0x0073 eip = 0x080480A6 eflags = 0x00000246
 
# Flags: PF ZF IF
 
 
# 080480A6:<N1> F7F3 div ebx
ald>
</source>
 
Przede wszystkim interesują nas zawartości rejestrów EAX, EBX oraz EDX, gdyż tylko one są argumentami powyższej instrukcji. Dzielna znajduje się w rejestrach EDX:EAX, natomiast dzielnik umieszczony jest w rejestrze EBX. Na tym etapie nie widać żadnych potencjalnych problemów, możemy więc kontynuować wykonanie programu krok po kroku używając polecenia '''n''':
 
<source lang=textbash>
n
ald> n
# eax = 0x00000000 ebx = 0x0000000A ecx = 0x0000000A edx = 0x00000007
# esp = 0xBFC9251C ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000
# ds = 0x007B es = 0x007B fs = 0x0000 gs = 0x0000
# ss = 0x007B cs = 0x0073 eip = 0x080480A8 eflags = 0x00000246
 
# Flags: PF ZF IF
 
 
# 080480A8 81C230000000 add edx, 0x30
ald>
</source>
 
Dzielenie całkowite zostało wykonane poprawnie. Wynik dzielenia znajduje się w rejestrze EAX, natomiast reszta z dzielenia w rejestrze EDX. Być może w następnym przebiegu pętli ujawnią się jakieś problemy. Kontynuujemy zatem wykonanie programu poleceniem '''continue''' (lub w skrócie '''c'''):
 
<source lang=textbash>
c
ald> c
# Breakpoint 1 encountered at 0x080480A6
# eax = 0x00000000 ebx = 0x0000000A ecx = 0x00000009 edx = 0x00000037
# esp = 0xBFC9251C ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000
# ds = 0x007B es = 0x007B fs = 0x0000 gs = 0x0000
# ss = 0x007B cs = 0x0073 eip = 0x080480A6 eflags = 0x00000206
 
# Flags: PF IF
 
 
# 080480A6:<N1> F7F3 div ebx
ald>
</source>
 
Linia 357 ⟶ 346:
 
<source lang=text>
n
ald> n
 
# Program received signal SIGFPE (Arithmetic exception)
# Location: 0x080480A6
# eax = 0x00000000 ebx = 0x0000000A ecx = 0x00000009 edx = 0x00000037
# esp = 0xBFBA9ADC ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000
# ds = 0x007B es = 0x007B fs = 0x0000 gs = 0x0000
# ss = 0x007B cs = 0x0073 eip = 0x080480A6 eflags = 0x00010206
 
# Flags: PF IF RF
 
 
# 080480A6:<N1> F7F3 div ebx
ald>
</source>
 
Widzimy, że operacja dzielenia nie została wykonana i zgłoszony jest wyjątek za pomocą sygnału ''SIGFPE''. Kolejna próba wykonania operacji skończy się zamknięciem programu wraz ze zwróceniem kodu błędu:
 
<source lang=textbash>
n
ald> n
# Program terminated with signal SIGFPE (Arithmetic exception)
ald>
</source>