基础知识
汇编语言是最基本的。程序员在实际硬件之上所拥有的唯一接口就是内核本身。为了在汇编中构建有用的程序,我们需要使用内核提供的linux系统调用。这些系统调用是内置在操作系统中的一个库,用于提供诸如从键盘读取输入和将输出写入屏幕等功能。
当你调用一个系统调用时,内核会立即挂起你的程序的执行。然后,它将联系必要的驱动程序,需要执行您在硬件上请求的任务,然后将控制返回给您的程序。
注意:驱动程序之所以被称为驱动程序,是因为内核从字面上使用它们来驱动硬件。
我们可以通过用我们想要执行的函数号(操作码OPCODE)加载EAX,并用我们想传递给系统调用的参数填充剩余的寄存器来完成这一切。一个软件中断被INT指令请求,内核接管并使用我们的参数从库中调用函数。简单。
例如,当EAX=1调用sys_exit时请求中断,而当EAX=4调用sys_write时请求中断。如果函数需要EBX、ECX和EDX,它们将被作为参数传递。点击这里查看Linux系统调用表及其相应的操作码。
写我们的程序
首先,我们在。data区域中创建一个变量'msg',并将我们想要输出的字符串赋值给它(在本例中是'Hello, world!')。在.text部分中,我们通过为内核提供全局标签_start:来表示程序的入口点,来告诉内核从哪里开始执行。
我们将使用系统调用sys_write将消息输出到控制台窗口。该函数在Linux系统调用表中分配OPCODE 4。该函数还接受3个参数,在请求软件中断执行任务之前,依次加载到EDX、ECX和EBX中。
传递的参数如下:
EDX将加载字符串的长度(以字节为单位)。
ECX将加载在.data部分中创建的变量的地址。
EBX将装载我们想要写入的文件——在本例中是STDOUT。
传递的参数的数据类型和意义可以在函数的定义中找到。
我们使用下面的命令编译、链接和运行程序。
; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
SECTION .data
msg db 'Hello World!', 0Ah ; assign msg variable with your message string
SECTION .text
global _start
_start:
mov edx, 13 ; number of bytes to write - one for each letter plus 0Ah (line feed character)
mov ecx, msg ; move the memory address of our message string into ecx
mov ebx, 1 ; write to the STDOUT file
mov eax, 4 ; invoke SYS_WRITE (kernel opcode 4)
int 80h
上面这段代码将会编译报错,如何写一下正确的程序, 将在下一节将介绍。