先看看下面通过系统调用实现的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
没有评论:
发表评论