注:
1.linux的系统调用号在“/usr/include/asm/unistd.h”文件中,有32位和64位之分
2.linux下函数参数是用寄存器进行传递的,因此同时最多只能传递6个参数。
3.linux的软中断号为0x80,因此调用中断汇编指令为“int $0x80”(AT&T汇编)。
4.这里涉及的功能号有三个,read为3,write为4,程序退出是1,要存入eax。
5.要将需要的功能号存入eax,然后执行中断“int $0x80”。
代码:
.section .bbs .lcomm buf,50 #.lcomm用来声明一个名称为buf、长度为50 byte的储存区 .section .text .globl _start #.globl指定程序入口,建议标号设置为“_start”,否则如果在linux中用ld链接时会有警告 _start: #下面将参数存入相应的寄存器 movl $buf,%ecx movl $50,%edx movl $0,%ebx movl $3,%eax #将3存入eax,执行“int $0x80”后,系统会调用sys_read,读取字符 int $0x80 movl $1,%ebx movl $4,%eax #将4存入eax,执行“int $0x80”后,系统会调用sys_write相应的函数,向屏幕输出buf内存区的字符 int $0x80 //下面的代码用来退出程序,并返回0(返回值储存在8位寄存器bl中,因此最大只能返回255,。bl是16位寄存器bx的低8位,而bx是ebx的低16位) movl $0,%ebx movl $1,%eax int $0x80
以上程序的基本执行过程就是划出一个50 byte的内存块,将内存块的首地址(即名称:buf)存入ecx,内存块长度存入edx,功能号3存入eax,软件中断(int),系统调用相应的读取函数,从寄存器中获取参数,执行,填满内存块。
然后返回程序,调用功能号4(之前为ecx,edx存入的内容并没有变),软件中断,系统调用相应的打印函数,再从寄存器获取参数,向屏幕输出内存块的内容,输出的字符数量由edx的值决定。打印完后自动返回程序。
最后向eax存入1,向ebx存入0,软件中断,程序退出,并向系统返回bl中的值(本程序中返回值是0,你可以使用"echo $?"命令来查看程序的返回值。)
运行结果如下:
你可以看到有一个make命令,这是用来编译代码用的,需要事先在该目录下建立一个makefile文件。
对应这个小程序的makefile文件内容如下:
input:input.o ld input.o -o input input.o:input.s as input.s -o input.o
makefile文件的写法很简单,就上面的内容而言:我们需要的可执行文件是input,如果想要生成input,需要input.o,因此第一行就是“input:input.o”,紧接着下一行,(ld和as前面是tab符号,不然会报错),是生成input的命令“ld input.o -o input”,这样就完成了一组make命令。简单来讲,基本格式如下:
你想要生成的文件:源文件
(tab)生成这个文件的命令
建议倒着来写,即从你想要生成的最终文件向上回溯,这样可以保证生成最新的目标文件(make程序可以自动判断你的源文件是否修改过,来确定用不用再生成一次,避免了在编译上浪费时间,在这点上真的很棒)