汇编语言是程序的根本骨架,对于一个程序员而言,在硬件之上的接口就是内核,为了实现一些游泳的功能我们需要调用linux内核提供的系统调用。系统调用是指,操作系统内在提供的一些库,它们提供了一些像如读取一个键盘的录入和输入到屏幕的功能。
当你程序调用一个系统调用时内核会立即暂停该程序并试图联系执行该调用必须的驱动并执行你的请求然后返回继续控制你的程序
驱动之所以被叫做驱动是因为,内核确实是使用它们驱动硬件的。
我们可以在汇编语言里完成系统调用,仅仅通过将功能码(opcode)加载到eax寄存器并将我们想传输给参数存放在其它的寄存器上
软件中断用int指令调用内核会接受指令并执行对应的无参函数。
例如当eax为1的时候调用中断会调用sys_exit,当eax为4时会调用sys_write 在linux,edx,ecx,ebx就会当作参数被传递如果有必要 。
首先,在.data段里新建一个变量叫做msg并且赋值为我们想要输出的字符串这里是"Hello World!"在我们的.text 段里我们通过全局的标记_start:告诉内核我们该从哪里开始运行程序, _start代表程序的开始点。
我们将调用系统调用 sys_wirte 来输出我们的信息到控制台上,在linux的OPCODE中4是代表输出函数会调用三个参数,它们通常被加载在edx,ecx,ebx在软件中断被调用之前。
数据类型和意义可以通过该函数(sys_wirte)的定义里面查看到
下面是该程序的代码。
xxxxxxxxxx
;helloworld 程序
section .data ;data段
msg db 'Hello World!',0ah ;将hello world!赋值给msg
section .text ;.text段
global _start ;程序入口
_start:
mov edx,13 ;将要输出的字符串长度赋值给edx寄存器
mov ecx,msg ;将msg的地址移动到ecx寄存器
mov ebx,1 ;移动1到ebx 代表输出到标准输出
mov eax,4 ;调用系统调用sys_write
int 80h
编译执行的命令:
xxxxxxxxxx
nasm -f elf hello.s
ld -m elf_i386 hello.o hello
./hello
此处会发生段错误
程序将会发生错误不能正常退出,下一节将讲述如何正常退出。