lidaibin ([info]lidaibin) wrote,
@ 2007-07-26 10:18:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Entry tags:asm, linux

汇编学习之系统调用
最近工作比较闲散,因此抽空看了看汇编,基本上从头开始,看了前面几章不知不觉也学会了“Hello world”,刚好看的这本书基本上都是以GNU的开发工具为开发环境的,这比较适合我的兴趣。其实看的这几章也就只有一章(这一章还没看完^_^)才是汇编语言的基础,刚学会了点AT&T的汇编语法,知道了跟Intel的汇编语法的区别,另外这一章用不同的方式实现了cpuid的调用,学会了如何调用系统调用以及如何调用C函数库中的函数。

先看看下面通过系统调用实现的hello world代码:

.section .data
msg:
        .ascii "Hello world!\n"

.section .text

.globl _start

_start:
        movl $4, %eax
        movl $1, %ebx
        movl $msg, %ecx
        movl $13, %edx
        int $0x80
        movl $1, %eax
        movl $0, %ebx
        int $0x80
        

系统调用是通过int 0x80来实现的,eax寄存器中为调用的功能号,ebx、ecx、edx、esi等等寄存器则依次为参数,从/usr/include/asm/unistd.h中可以看到exit的功能号_NR_exit为1,write(_NR_write)功能号为4,因此第一个int $0x80调用之前eax寄存器值为4,ebx为文件描述符,stdout的文件描述符为1,ecx则为buffer的内存地址,edx为buffer长度。第二个int $0x80之前eax为1表示调用exit,ebx为0表示返回0。编译链接步骤如下所示:
as -o helloworld.o helloworld.s
ld -o helloworld helloworld.o

再看看调用C函数的代码:
.section .data
output:
        .asciz "Hello world!\n"

.section .text

.globl _start

_start:
        pushl $output
        call printf
        addl $8, %esp
        pushl $0
        call exit
        

这个例子相对来说看起来简单得多,将参数压入堆栈调用相应的函数即可,不过要注意的是:1、C函数需要调用的字符串参数必须以asciz声明,而不是ascii,这样才会给字符串后面加'\0'。2、压栈顺序刚好与C函数顺序相反,最后的参数应最先入栈。3、链接的时候需要链接libc.so库并指定动态链接库加载器/lib/ld-linux.so.2,步骤如下:
as -o helloworld2.o helloworld2.s
ld -dynamic-linker /lib/ld-linux.so.2 -lc -o helloworld2 helloworld2.o



(1 comment) - (Post a new comment)


[info]zhllg
2007-08-03 09:05 am UTC (link)
看Programming from groud up吧
正是将Linux汇编的,很通俗易懂

(Reply to this)


(1 comment) - (Post a new comment)

Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…