_start: # 在屏幕上显示一个字符串 movl $len, %edx # 参数三:字符串长度 movl $msg, %ecx # 参数二:要显示的字符串 movl , %ebx # 参数一:文件描述符 (s td out) movl , %eax # 系统调用号 (sys_write) int x80 # 调用内核功能 # 退出程" name="description" />

Linux汇编语言开发指南(二)

发表于:2007-06-09来源:作者:点击数: 标签:
接(一) MI LY: "> _start: # 在屏幕上显示一个字符串 movl $len, %edx # 参数三:字符串长度 movl $msg, %ecx # 参数二:要显示的字符串 movl , %ebx # 参数一:文件描述符 (s td out) movl , %eax # 系统调用号 (sys_write) int x80 # 调用内核功能 # 退出程
接(一)

MILY: ˎ̥">_start:                  # 在屏幕上显示一个字符串
       movl $len, %edx  #
参数三:字符串长度
       movl $msg, %ecx  #
参数二:要显示的字符串
       movl , %ebx    #
参数一:文件描述符(stdout)
       movl , %eax    #
系统调用号(sys_write)
       int  x80       #
调用内核功能
       
                        #
退出程序
       movl ,%ebx     #
参数一:退出代码
       movl ,%eax     #
系统调用号(sys_exit)
       int  x80       #
调用内核功能

   
初次接触到 AT&T 格式的汇编代码时,很多程序员都认为太晦涩难懂了,没有关系,在 Linux 平台上你同样可以使用 Intel 格式来编写汇编程序:

2. Intel 格式

; hello.asm
section .data            ;
数据段声明
       msg db "Hello, world!", 0xA     ;
要输出的字符串
       len equ $ - msg                 ;
字串长度

section .text            ;
代码段声明
global _start            ;
指定入口函数

_start:                  ;
在屏幕上显示一个字符串
       mov edx, len     ;
参数三:字符串长度
       mov ecx, msg     ;
参数二:要显示的字符串
       mov ebx, 1       ;
参数一:文件描述符(stdout)
       mov eax, 4       ;
系统调用号(sys_write)
       int 0x80         ;
调用内核功能

                        ;
退出程序
       mov ebx, 0       ;
参数一:退出代码
       mov eax, 1       ;
系统调用号(sys_exit)
       int 0x80         ;
调用内核功能

   
上面两个汇编程序采用的语法虽然完全不同,但功能却都是调用 Linux 内核提供的 sys_write 来显示一个字符串,然后再调用 sys_exit 退出程序。在 Linux 内核源文件 include/asm-i386/unistd.h 中,可以找到所有系统调用的定义。

    四、Linux 汇编工具

    Linux
平台下的汇编工具虽然种类很多,但同 DOS/Windows 一样,最基本的仍然是汇编器、连接器和调试器。

    1.
汇编器

   
汇编器(assembler)的作用是将用汇编语言编写的源程序转换成二进制形式的目标代码。Linux 平台的标准汇编器是 GAS,它是 GCC 所依赖的后台汇编工具,通常包含在 binutils 软件包中。GAS 使用标准的 AT&T 汇编语法,可以用来汇编用 AT&T 格式编写的程序:

[xiaowp@gary code]$ as -o hello.o hello.s 

    Linux
平台上另一个经常用到的汇编器是 NASM,它提供了很好的宏指令功能,并能够支持相当多的目标代码格式,包括 bina.outcoffelfrdf 等。NASM 采用的是人工编写的语法分析器,因而执行速度要比 GAS 快很多,更重要的是它使用的是 Intel 汇编语法,可以用来编译用 Intel 语法格式编写的汇编程序:

[xiaowp@gary code]$ nasm -f elf hello.asm

    2.
链接器
 
   
由汇编器产生的目标代码是不能直接在计算机上运行的,它必须经过链接器的处理才能生成可执行代码。链接器通常用来将多个目标代码连接成一个可执行代码,这样可以先将整个程序分成几个模块来单独开发,然后才将它们组合(链接)成一个应用程序。 Linux 使用 ld 作为标准的链接程序,它同样也包含在 binutils 软件包中。汇编程序在成功通过 GAS NASM 的编译并生成目标代码后,就可以使用 ld 将其链接成可执行程序了:

[xiaowp@gary code]$ ld -s -o hello hello.o

    3.
调试器

   
有人说程序不是编出来而是调出来的,足见调试在软件开发中的重要作用,在用汇编语言编写程序时尤其如此。Linux 下调试汇编代码既可以用 GDBDDD 这类通用的调试器,也可以使用专门用来调试汇编代码的 ALD(Assembly Language Debugger)

   
从调试的角度来看,使用 GAS 的好处是可以在生成的目标代码中包含符号表(symbol table),这样就可以使用 GDB DDD 来进行源码级的调试了。要在生成的可执行程序中包含符号表,可以采用下面的方式进行编译和链接:

[xiaowp@gary code]$ as --gstabs -o hello.o hello.s
[xiaowp@gary code]$ ld -o hello hello.o

   
执行 as 命令时带上参数 --gstabs 可以告诉汇编器在生成的目标代码中加上符号表,同时需要注意的是,在用 ld 命令进行链接时不要加上 -s 参数,否则目标代码中的符号表在链接时将被删去。

   
GDB DDD 中调试汇编代码和调试 C 语言代码是一样的,你可以通过设置断点来中断程序的运行,查看变量和寄存器的当前值,并可以对代码进行单步跟踪。

   
1 DDD 中调试汇编程序

   
汇编程序员通常面对的都是一些比较苛刻的软硬件环境,短小精悍的ALD可能更能符合实际的需要,因此下面主要介绍一下如何用ALD来调试汇编程序。首先在命令行方式下执行ald命令来启动调试器,该命令的参数是将要被调试的可执行程序:


[xiaowp@gary doc]$ ald hello
Assembly Language Debugger 0.1.3
Copyright (C) 2000-2002 Patrick Alken

hello: ELF Intel 80386 (32 bit), LSB, Executable, Version 1 (current)
Loading debugging symbols...(15 symbols loaded)
ald>

ALD 的提示符出现之后,用 disassemble 命令对代码段进行反汇编:

ald> disassemble -s .text
Disassembling section .text (0x08048074 - 0x08048096)
08048074  BA0F000000                 mov edx, 0xf
08048079  B998900408                 mov ecx, 0x8049098
0804807E  BB01000000                 mov ebx, 0x1
08048083  B804000000                 mov eax, 0x4
08048088  CD80                       int 0x80
0804808A  BB00000000                 mov ebx, 0x0
0804808F  B801000000                 mov eax, 0x1

原文转自:http://www.ltesting.net