Linux下的汇编程序学习体会(1)(转载)

Linux下的汇编程序学习体会(1)

一、为什么学习linux下的汇编
Linux的应用领域越来越广泛,特别是在嵌入式领域有着得天独厚的优势。涉及到硬件相关的开发自然少不了汇编语言。
大学里学习的汇编都是16位的,与现在32位芯片有些出入。
而且很多AT/T的汇编格式代码也让我们感到困惑
Linux内核代码由一些核心部分也是用汇编写的。为了读懂linux内核,需要对汇编有一定的了解。本人正是基于这个目的出发,才学习汇编的。

二、硬件和汇编语言
汇编语言根机器语言是一一对应的;所以,不同型号的机器有不同的汇编语言,本文所有的论述都是基于X86的体系结构。
Linux汇编按照语法格式可以分为两种inter格式和AT/T格式。前者跟我们大学里学习的汇编语言格式相近;后者在linux内核代码中得到了广泛的应用。关于这两种格式的详细描述请参考《linux下的汇编程序学习体会(2)》。Linux下还有一个小工具,intel2gas可以把inter格式转换成AT/T格式。本文所涉及的都是AT/T格式的汇编。
三、开发环境
编辑器
Linux下任何一款文本编辑器,vi, emac, etc. 如果喜欢直接写屏,也没什么不妥(男人就要对自己狠一点)。不过本人还是钟爱vi.

编译器
推荐as, 没啥可说的,看man page吧。

连接器
当然是老牌劲旅ld, (其实我没用过别的),用法还是参考man page.

调试器
可以用gdb, 不过康奈尔大学的好事者Patrick Alken先生独立开发了一个ald。本人就是用ald, 这个软件可以从http://ald.sourceforge.net/ 获得,它的编译需要依赖行编辑器readline, readline可以从http://www.gnu.org/ 上找到。

教材
推荐ProgrammingGroundUp, 浅显易懂实用


四、入门实例
先来个感性的认识,用一个Hello World程序把汇编语言的开发过程完整的走一编。

第一步,编辑程序。

用编辑器编译下列程序保存文件名为hello.s

#hello.s

.data # 数据段声明

msg : .string "Hello, world!" # 要输出的字符串

len = . - msg # 字串长度


.text # 代码段声明

.global _start # 指定入口函数


_start: # 在屏幕上显示一个字符串

movl $len, %edx # 参数三:字符串长度

movl $msg, %ecx # 参数二:要显示的字符串

movl $1, %ebx # 参数一:文件描述符(stdout)

movl $4, %eax # 系统调用号(sys_write)

int $0x80 # 调用内核功能


# 退出程序

movl $0, %ebx # 参数一:退出代码

movl $1, %eax # 系统调用号(sys_exit)

int $0x80 # 调用内核功能


第二步,编译

运行命令as –gstabs –o hello.o hello.s 就得到了二进制目标文件hello.o, 参数—gstabs 的意义是保存符号表,以方便将来的调试。

第三步,连接

运行命令ld –o hello hello.o 就输出了可执行程序hello.

第四步,运行

敲入命令./hello, 就看到了输出。

第五步,调试

这个程序工作正常,实际上无需调试。这里只是介绍调试器的使用方法。运行命令ald hello

就进入了调试状态。

Assembly Language Debugger 0.1.7

Copyright (C) 2000-2004 Patrick Alken



hello: ELF Intel 80386 (32 bit), LSB - little endian, Executable, Version 1 (Current)

Loading debugging symbols...(15 symbols loaded)

ald>

用反汇编命令得到程序的代码段

ald> d -s .text

Disassembling section .text (0x08048074 - 0x08048096)

08048074:<_start> BA0E000000 mov edx, 0xe

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

08048094 CD80 int 0x80

设置断点

ald> b 0x0804807E

Breakpoint 1 set for 0x0804807E

运行程序

ald> r

Starting program: hello

Breakpoint 1 encountered at 0x0804807E

eax = 0x00000000 ebx = 0x00000000 ecx = 0x08049098 edx = 0x0000000E

esp = 0xBFFFFCC0 ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000

ds = 0x007B es = 0x007B fs = 0x0000 gs = 0x0000

ss = 0x007B cs = 0x0073 eip = 0x0804807E eflags = 0x00200212



Flags: AF IF ID





0804807E BB01000000 mov ebx, 0x1

单步运行到结束

ald> n

eax = 0x00000000 ebx = 0x00000001 ecx = 0x08049098 edx = 0x0000000E

esp = 0xBFFFFCC0 ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000

ds = 0x007B es = 0x007B fs = 0x0000 gs = 0x0000

ss = 0x007B cs = 0x0073 eip = 0x08048083 eflags = 0x00200312



Flags: AF TF IF ID





08048083 B804000000 mov eax, 0x4

ald> n

eax = 0x00000004 ebx = 0x00000001 ecx = 0x08049098 edx = 0x0000000E

esp = 0xBFFFFCC0 ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000

ds = 0x007B es = 0x007B fs = 0x0000 gs = 0x0000

ss = 0x007B cs = 0x0073 eip = 0x08048088 eflags = 0x00200312



Flags: AF TF IF ID





08048088 CD80 int 0x80

ald> n

Hello, world!eax = 0x0000000E ebx = 0x00000000 ecx = 0x08049098 edx = 0x0000000E

esp = 0xBFFFFCC0 ebp = 0x00000000 esi = 0x00000000 edi = 0x00000000

ds = 0x007B es = 0x007B fs = 0x0000 gs = 0x0000

ss = 0x007B cs = 0x0073 eip = 0x0804808F eflags = 0x00200312

你可能感兴趣的:(数据结构,编程,linux,嵌入式,D语言)