【版权声明:尊重原创,转载请保留出处: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
$