现在的位置: 首页 > 综合 > 正文

[131115汇编] Linux 汇编程序 打印字符串 笔记

2013年04月24日 ⁄ 综合 ⁄ 共 2643字 ⁄ 字号 评论关闭
文章目录

Linux下的汇编为AT&T格式

 

1 目前学习汇编的步骤

  • 怎么将汇编代码添加到汇编程序框架中。
  • 理解汇编语句的含义。
  • 汇编源代码是怎么转换为可执行代码的。

 

2 AT&T汇编程序结构

在汇编中,一般具有如下的结构:

  • 数据段(.data)
  • 附加段(.bss)
  • 代码段(.text)

 

在汇编程序中,数据和附加段可选,但在汇编程序中经常包含有这两个段。代码段必含,是声明指令代码的地方。

 

(1)定义段

每个段用”.section”或“.标识符”标识。如”.section.data””.data”就形象的表示一个数据段。其实对于对于系统来说,它只是一个段,以“.”标识。

 

(2) 汇编程序入口

当汇编代码被编译成为可执行程序的时候,连接器必须要知道程序入口点在哪里。在GNU汇编器中,_start被定义为汇编程序的入口标识符,_start标识符暗示程序从这里开始运行。

 

为了让这个入口标识符能被其它文件的汇编代码认识,提供 “.globl”指令实现,即用.globl  _start语句声明程序入口标识符。

 

所以,一个AT&T汇编程序的结构大概如此:

.section  .data

         < initialized data here>

 

.section  .bss

         < uninitialized data here>

 

.section .text

.globl _start

_start:

         <instruction code goes here>

在代码段中,汇编代码依靠系统调用来完成一些操作,包括在程序退出之前的一些操作及程序退出操作

 

3一个简单的汇编程序

(1) 数据段

.data

msg:   .ascii  "write asm code first  day\n"

len= .-msg

  •  形象的标名数据段。
  • .asciiAT&T汇编中的数据类型,类似的数据类型还有“.short”、“.int”、“.long”、“.byte”、“.float”、“.double”、“.comm”。第二条语句叫表示msg作为后续字符串的起始地址。
  • len求得字符串的长度。

(2) 代码段

代码段主要是用系统调用来完成程序功能。包含“程序入口”、“功能代码”和“程序退出代码”。

 

[1]程序入口

.text

.global _start

_start:

按照GNU AT&T汇编的格式,_start为汇编程序的入口,且由.global保证其它文件内的汇编代码可识别_start入口。

 

[2]功能代码

_start:

    movl $4, %eax       #Linux system wirte call

    movl$1, %ebx       #STDOUT

    movl $msg, %ecx  #Give string start address to %ecx

    movl $len, %edx  #Give string lenght to %edx

    int  $0x80                    #Software interrupt

 这几行代码表示一次Linux系统调用。Linux系统的软件中断由命令int发起。系统调用的中断号为0x80处。int  $0x80引来一次系统调用软件中断,在一次Linux系统调用中会访问一些内核函数。在这次系统调用中断过程中将执行什么样的系统调用取决于eax寄存器内的值。每一种系统调用对应一个内核函数的调用。

 

int $0x80引发的系统调用中,在eax寄存器内不同的值表示不同的系统调用。4代表linux write system call1代表linux
exitsystem  call
And so on

 

linux 写系统调用(eax值为4)下,其它的寄存器内所存值也会代表一些含义:

  • ebx包含要写向的文件描述符(STANDOUT1STDIN0STDERR2)。
  • ecx包含子符串的起始地址。
  • edx包含ecx字符串的长度。

 

故而,在为写操作准备好所有的条件之后。int $0x80经执行引起的软件中断后,照eax内存的值就访问linux内核的一些函数,向控制台(ebx:1)输出字符串(ecx:msg)。

 

[3]程序退出

movl $1, %eax   #Linux systemexit call

movl $0, %ebx   #Acceptprogram exit value

int $0x80       #software interrupt

Linux汇编程序的退出也是依靠系统调用来完成。此时寄存器eax中的值应该为1ebx只是为了获得程序退出后返回给shell的值。

 

到此,一个简单的linux程序就编写好了,基本模糊的原理也给笔记清楚了。

 

4 编译执行AT&T linux汇编

加入以上各部分组成的代码文件名为,learn.s,则编译执行过程为:

as     -o   learn.o     learn.s      [生成learn.o文件]

ld      -o   learn         learn.o   [生成learn可执行文件]

./learn                                      得程序执行结果]

write   asm code first day

 

5 总结

关于涉及到的AT&T汇编的语法

  • 立即数前面需要加$。
  • 直接引用符号常数,在符号常数前加$表示引用符号常数的地址。
  • movl  %eax, %ebx,源操作数为eax内的值,目的操作数为ebx的值。源、目的操作数符合从左到右的操作顺序。
  • 寄存器前面要加%。
  • Linux 下用vim编辑器编辑AT&T代码时#表示注释符号。

 

初学汇编,在了解汇编程序框架后,如果不知代码段应该写什么内容,不明白要用哪一个寄存器来操作时。应该查查各寄存器在系统调用软件中断发生时(int $0x80)要发生的操作所对应的寄存器的值。这样,起码就能编写“hello world!”的入门代码了。

 

当然,要了解整个汇编代码的机制还得多编写,达到只需查询就可完成功能的目标。目前根据这个程序得到的经验是:汇编代码可以依靠系统调用软件中断来调用内核的函数,系统调用的类型由eax寄存器你的值。我们需要提前配置好eax及相关寄存器的值,从而实现咱的目标功能一般是eax寄存器里面的值决定软件中断后linux系统调用的类型(eax:4linux write
system call,eax:1 linux exit system call),然后其它的寄存器配合这种统调用
[好像总结得有点浅显]

 

此次笔记记录完毕。

抱歉!评论已关闭.