Chinaunix首页 | 论坛 | 博客
  • 博客访问: 166098
  • 博文数量: 56
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 17:36
文章分类

全部博文(56)

文章存档

2016年(43)

2015年(9)

2014年(2)

2013年(2)

我的朋友

分类: LINUX

2015-08-28 09:50:51

调试是编写程序中一个永恒的话题,除非你的程序永远没有错误。本文介绍Linux下如何使用gdb调试汇编程序:

gdb(GNU Debugger)是一款功能非常强大的调试器,它的GUI版本叫做Kdbg,运行于KDE桌面环境。很多Linux发行版默认含有gdb

例子程序:
程序中-start:标签后加上nop语句是为了在gdb中能够暂停程序
复制内容到剪贴板
代码:
#cpuid.s  Sample program

.section .data

output:
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"

.section .text
.globl _start

_start:

nop                   //gdb中暂停程序用

movl $0, %eax

cpuid

movl $output, %edi

movl %ebx, 28(%edi)

movl %edx, 32(%edi)

movl %ecx, 36(%edi)

movl $4, %eax

movl $1, %ebx

movl $output, %ecx

movl $42, %edx

int $0x80

movl $1, %eax

movl $0, %ebx

int $0x80
为了使用gdb调试汇编程序,必须对源程序加上-gstabs选项进行编译,编译之后的程序中含有可供gdb识别的调试附加信息:
复制内容到剪贴板
代码:
$as -gstabs -o cpuid.o cpuid.s

$ld -o cpuid cpuid.o

$
然后启动gdb进行调试:
复制内容到剪贴板
代码:
$gdb cpuid

GNU gdb //此处为版权信息若干行

(gdb)
用run命令运行程序
复制内容到剪贴板
代码:
(gdb)run

Starting program: /home/path/cpuid

The processor Vendor ID is 'GenuineIntel'

Program exited normally

(gdb)
程序正常运行,并显示了结果The processor Vendor ID is 'GenuineIntel'。gdb中单步调试程序必须先设置断点(breakpoint)。我们这里把断点设置在开头,使用命令break * label+offset来设置断点:
复制内容到剪贴板
代码:
(gdb)break * _start+1

Breakpoint 1 at 0x12345678: file cpuid.s 12

(gdb)run

Starting program: /home/path/cpuid

Breakpoint 1,_start() at cpuid.s 12

12        movl $0, $eax

(gdb)
断点设置的时侯,必须指定其对最近标签的相对位置,所以这里设定断点为_start标签之后的一个偏移,也就是nop语句,如果没有nop语句,或者设定断点为_start标签位置,那么程序不会停止,而会继续执行下去(gdb的bug?)。现在程序停在了第一条语句,屏幕显示的是将要执行的语句,接下来可以使用next或者step命令单步执行程序,cont继续执行余下全部程序。
复制内容到剪贴板
代码:
(gdb)next

_start() at cpuid.s:13

13       cpuid

(gdb)step

_start() at cpuid.s:14

14       movl $output, %edi

(gdb)cont

Continuing.

The processor Vendor ID is 'GenuineIntel'

Program exited normally

(gdb)
暂停程序的过程中可以使用info registers命令来查看当前所有寄存器的值:
复制内容到剪贴板
代码:
(gdb)next

_start() at cpuid.s:13

13       cpuid

(gdb)info registers

eax    0x0    0

ecx    0x0    0

...    ...    ...   //其他寄存器省略

gs     0x0    0
还可以用print命令显示某个寄存器的值,x命令用来显示特定内存位置的值,格式如下:
   print/d $reg   以十进制显示reg的值
   print/t $reg   二进制
   print/x $reg   十六进制
   x/nyz          n是要显示的字段数,y是输出格式(c字符,x是16进制,d是十进制),z是字段长度(b字节,h半字,w32位字)
例如,x/42cb &output就是以字符模式显示output变量前42字节的值。
阅读(1402) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~