下面分别是AT&T风格和Intel风格的汇编示例程序hello.s和hello.asm:
hello.s
-----------
#hello.s
.data # 数据段
msg : .string "Hello,world!\n" # 要输出的字符串
len = . - msg # 字串长度
.text # 代码段
.global _start # 指定入口函数
_start:
# 以下是sys_write的3个输入参数
movl $len, %edx # 参数三,字符串长度
movl $msg, %ecx # 参数二,要显示的字符串
movl $1, %ebx # 参数一,文件描述符stdout
movl $4, %eax # 调用sys_write
int $0x80 # 调用内核功能
# 退出程序
movl $0, %ebx # 参数一,退出代码
movl $1, %eax # 调用sys_exit
int $0x80 #调用内核功能
------------------------
编译命令为
#as -o hello.o hello.s
#ld -s -o hello hello.o
------------------------
hello.asm
---------------
;hello.asm
section .data ; 数据段
msg db "Hello,world!",0xA ; 要输出的字符串
len equ $ - msg ; 字串长度
section .text ; 代码段
global _start ; 指定入口函数
_start:
; 以下是sys_write的3个输入参数
mov edx, len ; 参数三,字符串长度
mov ecx, msg ; 参数二,要显示的字符串
mov ebx, 1 ; 参数一,文件描述符stdout
mov eax, 4 ; 调用sys_write
int 0x80 ; 调用内核功能
; 退出程序
mov ebx, 0 ; 参数一,退出代码
mov eax, 1 ; 调用sys_exit
int 0x80 ; 调用内核功能
--------------------------
编译命令为
#nasm -f elf hello.asm
#ld -s -o hello hello.o
----------------------------------------
系统函数调用的定义在linux内核源文件
include/asm-i386/unistd.h 中。
比如它定义了
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
...
而在linux平台下的/usr/include/bits/syscall.h中会重定义,如
#define SYS_write __NR_write
#define SYS_waitpid __NR_waitpid
...
-------------------------------
Linux 下的系统调用是通过中断(int 0x80)来实现的:
在执行 int 80 指令时,寄存器 eax 中存放的是系统调用的功能号,而传给系统调用的参数则必须按顺序放到寄存器 ebx,ecx,edx,esi,edi 中,当系统调用完成之后,返回值可以在寄存器 eax 中获得。