汇编语言程序设计读书笔记(1)- 相关工具

linux下汇编语言采用的是AT&T语法,可使用GNU工具,包括汇编器gas,连接器ld,编译器gcc,调试器gdb或kdbg,objdump的反汇编功能,简档器gprof。以简单的例子分别对每个工具在汇编语言开发中的用法进行简单说明。

这些工具都要在linux环境下使用,先建立linux的开发环境,可参考文章“windows7 64位系统安装VMware Centos 64位系统搭建开发环境”。

假设有以下简单的c程序test1.c。

#include <stdio.h>

int main()
{
    printf("hello, world!\n");
    exit(0);
}

1. gcc用法介绍

gcc用于编译源文件,加上参数可以生成中间文件。

用gcc把test1.c编译成执行文件test1:

用gcc把test1.c编译成文件test1-g,带调试参数-g:

用gcc把test1.c生成汇编语言文件test1-s.s,用参数-S:

用gcc生成目标代码test1.o,用参数-c:

疑问:gcc带调式的参数除了-g外,还有-gstabs,-gstabs+,-ggdb和调式有关的参数,man gcc得到以下的说明。从说明中,我还是不能了解这几个参数的具体区别以及何时该用哪个,如果哪位朋友知道,请给于解释。

-g  Produce debugging information in the operating system’s native format (stabs, COFF, XCOFF, or DWARF 2).  GDB can work with this debugging
           information.

-gstabs

Produce debugging information in stabs format (if that is supported), without GDB extensions.  This is the format used by DBX on most BSD

systems.  On MIPS, Alpha and System V Release 4 systems this option produces stabs debugging output which is not understood by DBX or SDB.  On

System V Release 4 systems this option requires the GNU assembler.

-gstabs+

Produce debugging information in stabs format (if that is supported), using GNU extensions understood only by the GNU debugger (GDB).  The use

of these extensions is likely to make other debuggers crash or refuse to read the program.

-ggdb

Produce debugging information for use by GDB.  This means to use the most expressive format available (DWARF 2, stabs, or the native format if

neither of those are supported), including GDB extensions if at all possible.

汇编语言程序设计这本书是使用-gstabs这个参数。为什么不用其它参数?

最后,test1.c用这四个参数生成的的test1的大小记录如下,可见参数不一样生成的文件大小是不一样的。-g和-ggdb生成的结果大小一样。

2. objdump用于反汇编的用法

上面产生的目标文件test1.o和可执行文件test1,可使用objdump反汇编。

3. gas汇编用法

gas把汇编程序汇编成目标文件,命令是as,找到以下的汇编程序test1.s:

.section .text
.globl _start
_start:
    movl $1, %eax
    movl $0, %ebx
    int $0x80

如下汇编,生成test1.o文件:

4. ld的用法

把前面的test1.o连接成可执行文件test1。

5. gdb和kdbg用法

gdb用的是命令方式,用惯了像VS之类的IDE调试的,感觉gdb非常不好用,尤其是对于较复杂的工程,不如kdbg好用。

从界面看,比较方便操作,不用记复杂的命令,一目了然,可以把注意力放在软件的查错上。注意编译或汇编时一定要带调试的参数,比如gcc –gstabs或者as –gstabs,否则无法调式。

kdbg需要kde和qt支持,而且在用ssh2登录linux后的secureCRT中执行会提示无法连接连接到X server,需要在启动图形界面后的,输入命令运行。

疑问:在secureCRT中怎么执行?

6. 简档器gprof用法

简档器用于分析程序中所有函数的执行时间,编译时要用-pg参数,但是查阅了帮助,as和ld都不支持-pg参数,因此只能使用gcc -pg。

用以下的test2.c为例:

/*********************************************
* test2.c
*********************************************/
#include <stdio.h>

void func1(void)
{
    int i, j;

    for(i=0,j=0; i<1000000; i++)
        j++;
}

void func2(void)
{
    int i, j;

    func1();
    for(i=0,j=0; i<2000000; i++)
        j++;
}

int main()
{
    int i;

    for(i=0; i<100; i++)
        func1();

    for(i=0; i<200; i++)
        func2();

    return 0;
}

先要带参数-pg编译程序生成可执行文件test2,然后执行test2,执行一次就会生成一个新的gmon.out文件,执行gprof  test2可执行文件就可以输出简档,可以重定向到test2-gprof.txt,方便查看。如下:

最后得到的test2-gprof.txt文件摘录如下:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 58.24      0.54     0.54      200     2.68     3.99  func2
 42.86      0.93     0.39      300     1.31     1.31  func1


Call graph (explanation follows)


granularity: each sample hit covers 2 byte(s) for 1.08% of 0.93 seconds

index % time    self  children    called     name
                                                 <spontaneous>
[1]    100.0    0.00    0.93                 main [1]
                0.54    0.26     200/200         func2 [2]
                0.13    0.00     100/300         func1 [3]
-----------------------------------------------
                0.54    0.26     200/200         main [1]
[2]     85.9    0.54    0.26     200         func2 [2]
                0.26    0.00     200/300         func1 [3]
-----------------------------------------------
                0.13    0.00     100/300         main [1]
                0.26    0.00     200/300         func2 [2]
[3]     42.4    0.39    0.00     300         func1 [3]
-----------------------------------------------

可以分析到func1和func2执行的时间。

%time: 表示函数占总运行时间的百分比。

cumulative seconds:表示改行及其以上的行所用的时间。

self seconds:表示函数自己本身执行的时间。

calls:函数被调用的次数。

self ms/call:函数自己每次调用所用的执行时间。不包含函数中调用的别的函数执行的时间。

total ms/call:表示函数每次调用所用的执行时间,包含调用的别的函数的时间。

name:函数名。

疑问:汇编程序.s怎么产生简档?

时间: 2024-11-07 16:14:16

汇编语言程序设计读书笔记(1)- 相关工具的相关文章

汇编语言程序设计读书笔记(3)- 程序范例

主要描述三方面的内容:第一是汇编语言的程序模版,以及模版涉及到的一些知识点:第二是如何调试汇编语言:第三是如何在汇编语言中调用C库函数. 1. 汇编语言的组成 汇编语言由段(section)组成,一个程序中执行的代码,叫文本段(text),程序还可能有定义变量,有付给初始值的变量放在数据段(data)中,没有赋初值或者付给零初值的放在bss段中.text段一定是要有的,data和bss可以没有. 2. 段的定义 用.section语法定义段.比如: .section .text定义文本段, .s

汇编语言程序设计读书笔记(2)- 相关工具64位系统篇

汇编语言程序设计一书,在32位系统下应该不会有什么问题,然而在64位系统下,则会有些不一样的地方.有些程序范例还会汇编错误或者执行错误. 博主所用系统为CentOS v6.4 x64.本文主要解决32位的汇编程序如何在64位环境下汇编.连接,而不论述64位汇编语言如何设计. 1. 64位系统下编译32位的C程序 以程序test5.c为例,程序代码很简单,如下: test5.c#include <stdio.h> int main() { char str[4]; str[0]='f'; str

汇编语言程序设计读书笔记(4)- 程序设计基础之一

目录: 一.数据定义 1.变量数据定义 2.常量数据定义 3.缓冲区定义 二.寻址方式 1.立即数寻址 2.寄存器寻址 3.直接寻址 4.寄存器间接寻址 5.寄存器相对寻址 6.变址寻址 三.数据传送和mov指令 1.数据传送规则 2.mov指令 四.条件传送数据cmov指令 1.状态标志位 2.cmov指令 五.交换数据 1.xchg指令 2.bswap指令 3.xadd指令 4.cmpxchg指令 5.cmpxchg8b指令 六.堆栈 1.堆栈简介 2.入栈指令push 3.出栈指令pop

JavaScript高级程序设计-读书笔记(2)

第6章 面向对象的程序设计 创建对象 1.最简单方式创建Object的实例,如 var person = new Object(); person.name = “Greg”; person.age = 27; person.job = ”Doctor”; person.sayName = function() { alert(this.name); }; person. sayName(): 缺点:会产生大量重复代码 2.工厂模式:用函数来封装以特定接口创建对象的细节,如 function c

JavaScript 高级程序设计读书笔记(1)

第6章 面向对象的程序设计 属性的类型 JS 中对象的属性有两种,数据属性和访问器属性(accessor property ),属性有其自身的特性(arrribute),可以理解为关于属性的属性. 数据属性包含4个特性,分别是[[Configurable]], [[Enumerable]], [[Writable]], [[Value]]. 使用 Object.defineProperty 修改属性描述符时,若该属性之前不存在,除了代码里指定的特性值,其他特性值默认将是 false, 举例如下:

Intel汇编语言程序设计学习笔记1

第一章 汇编器链接器:汇编器将汇编语言翻译成机器语言,链接器将单个文件合并为可执行文件 intel 80X86系列处理器的汇编语言与VAX或者motorala 68x00等系统的汇编是否相同?不相同,汇编语言和CPU指令集是密切关联的,每种CPU体系对应不同的汇编. 什么是设备驱动程序:将操作系统的通用命令转化为对硬件具体细节实现的程序 常规机器语言指的是第二层 一条机器语言会被翻译成几条微指令,微指令是商业机密 高级语言会被解释成汇编语言,汇编语言被解释成机器语言(第二层),由操作系统(第三层

Javascript高级程序设计读书笔记(第六章)

第6章  面向对象的程序设计 6.2 创建对象 创建某个类的实例,必须使用new操作符调用构造函数会经历以下四个步骤: 创建一个新对象: 将构造函数的作用域赋给新对象: 执行构造函数中的代码: 返回新对象. 构造函数的问题:每个方法都要在每个实例上重新创建一遍: 理解原型对象: 无论何时,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象.默认情况下,所有原型对象都会自动获得一个constructor属性,这个属性包含一个指向proto

新标准C++程序设计读书笔记_类和对象

面向对象的程序设计方法 抽象:将某类客观事物共同特点(属性)归纳出来,形成一个数据结构(可以用多个变量描述事物的属性):将这类事物所能进行的行为也归纳出来,形成一个个函数,这些函数可以用来操作数据结构. 封装:通过某种语法形式,将数据结构和操作该数据结构的函数“捆绑”在一起,形成一个“ 类”,从而使得数据结构和操作该数据结构的算法呈现出显而易见的紧密关系. 从客观事物抽象出类 写一个程序,输入矩形的长和宽,输出面积和周长. 比如对于“矩形”这种东西,要用一个类来表示,该如何做“抽象”呢?矩形的属

JavaScript高级程序设计-读书笔记(6)

第20章 JSON JSON是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量 JSON的语法可以表示一下三种类型的值 l        简单值:使用与JavaScript相同的语法,可以在JSON中表示字符串.数值.布尔值和null.但JSON不支持JavaScript中的特殊数值undefined. “Hello world!” l        对象(属性的值可以是简单值,也可以是复杂类型值,如下这样在对象嵌入对象) { “name” : ”Nicholas”, “age” : 29