使用gdb調試彙編程序

【版權聲明:尊重原創,轉載請保留出處:blog.csdn.net/shallnet,文章僅供學習交流,請勿用於商業用途】

正如C語言一樣,編寫所有語言程序一樣會出現一些一些錯誤,發生錯誤時,我們可以使用調試器一步一步運行程序以監視數據是如何被處理的。本節使用GNU調試器檢查上一節hello程序,監視處理過程中寄存器和內存的值的變化。要調試彙編語言程序,在編譯時,需要使用-gstabs參數重新彙編源代碼,使用了該參數編譯出來的可執行文件要比之前稍大一些,因為添加了附加信息。上一節程序不使用-gstabs參數彙編生成文件如下:

$ ls -lh hello

-rwxrwxr-x. 1 allen allen 628 4月 11 15:28 hello 使用-gstabs之後,編譯後生成文件如下:

$ ls -lh hello

-rwxrwxr-x. 1 allen allen 888 4月 11 15:29 hello 由於gnu調試時忽略開始處斷點, 需要在開始標籤處執行一個空指令nop。 當程序包含了必要的調試信息時,我們就可以在gdb中運行它:

$gdb hello
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/allen/as/1_hello/hello...done.
(gdb)

在gdb中,使用命令break(b)指定斷點:

(gdb) break *_start
Note: breakpoint 1 also set at pc 0x8048074.
Breakpoint 2 at 0x8048074: file hello.s, line 12.
(gdb)

使用命令run(r)啟動程序:

(gdb) run
Starting program: /home/allen/as/1_hello/hello
Breakpoint 1, _start () at hello.s:12
12    movl $len, %edx
(gdb)

可以看到程序啟動了,停留在我們之前設置的斷點處,使用next(n)和step(s)命令讓程序單步執行:

(gdb) step
13    movl $msg, %ecx
(gdb) next
14    movl $1, %ebx
(gdb) s
15    movl $4, %eax
(gdb) n
16    int $0x80
(gdb)

在單步調試運行時可以查看檢查數據元素值。最常被檢查的元素是寄存器和內存位置,使用info register命令可以顯示所有寄存器的值,使用print命令可以顯示指定寄存器或變量的值,使用x命令顯示指定內存位置的內容。

(gdb) info registers
eax            0x4 4
ecx            0x8049098 134516888
edx            0xd 13
ebx            0x1 1
esp            0xbffff3d0 0xbffff3d0
ebp            0x0 0x0
esi            0x0 0
edi            0x0 0
eip            0x8048088 0x8048088 <_start+20>
eflags         0x212 [ AF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x0 0
(gdb)

使用命令print 加上指定寄存器也可以顯示寄存器的值:

(gdb) print $eax
$1 = 4
(gdb) print $ebx
$4 = 1
(gdb) print $ecx
$5 = 134516888
(gdb) print $edx
$6 = 13
(gdb)
print命令加上修飾符可以改變pritn命令輸出格式:
print/d 顯示十進制的值
print/t顯示二進制的值
print/x顯示十六進制的值
(gdb) print/x $edx
$9 = 0xd

x命令也可以使用修飾符修改輸出,其格式為:

  • x/nyz
  • n為要顯示的字段數;
  • y是輸出格式,可以是c(字符)、d(十進制)、x(十六進制);
  • z是要顯示的字段的長度,可以是b(字節)、h(16位字)、w(32位字)。
    (gdb) x/13cb &msg
    0x8049098 <msg>: 104 'h' 101 'e' 108 'l' 108 'l' 111 'o' 32 ' ' 119 'w' 111 'o'
    0x80490a0 <msg+8>: 114 'r' 108 'l' 100 'd' 33 '!' 10 '\n'
    (gdb)
    
    其中msg前的&表明其是一個內存位置。 命令cont使程序按正常的方式繼續運行,沒如果後面沒有斷點,則直接運行到最後。
    (gdb) cont
    Continuing.
    Program exited normally.
    (gdb)
    
    最後可以使用quit命令退出gdb調試。
    (gdb) quit
    $