Asembler x86/Jak używać debuggera ALD: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
→Wstrzymanie wykonania: błąd |
→Wstrzymanie wykonania: poprawki |
||
Linia 187:
#wyjscie
incl %eax
incl %ebx
int $80h
Linia 212:
decl %ecx
movl %ecx($msg),%dl
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=
</source>
Następnie przeprowadzamy deasemblację (klawisz '''d''' i '''ENTER''') w celu poznania adresu wskaźnika do interesującej na instrukcji:
<source lang=
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=
# Breakpoint 1 set for 0x080480A6
</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=
# Num Type Enabled Address IgnoreCount HitCount
# 1 Breakpoint y 0x080480A6 none 0 (N1+0x0)
</source>
Jeśli wszystko się zgadza, możemy uruchomić program poleceniem '''run''':
<source lang=
# 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
</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=
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
</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=
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
</source>
Linia 357 ⟶ 346:
<source lang=text>
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
</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=
n
# Program terminated with signal SIGFPE (Arithmetic exception)
</source>
|