前面使用系统调用 write() 来输入输出。一般来说,在 /usr/include/asm/unistd.h 可以找到可用的系统调用的定义(在我的机器上实际是 unistd_32.h):
...
#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
...
定义了系统调用和各自对应的值。
使用系统调用前要把对应的系统调用值放到 eax 中,再把需要的参数放到对应的位置,最后使用中断 int $0x80 使用系统调用。如果系统调用的参数小于 6 个,参数的顺序依次是:ebx,ecx,edx,esi,edi。如果系统调用的参数超过 6 个,则把参数内存位置的地址放到 ebx 中,输入的参数按照顺序连续存放。系统调用的返回值存放在 eax 中。
使用 c 程序时,参数通过栈传递,返回值也是放在 eax 中。
# syscall.s
.section .rodata
msg1:
.ascii "Hello, world.\n"
msg2:
.asciz "write str len = %d.\n"
msg3:
.asciz "printf str len = %d.\n"
.section .text
.globl main
main:
movl $4, %eax # system call
movl $1, %ebx # file descriptor
movl $msg1, %ecx # string address
movl $msg2, %edx
subl $msg1, %edx # string length
int $0x80
pushl %eax
pushl $msg2
call printf
addl $8, %esp
pushl %eax
pushl $msg3
call printf
addl $8, %esp
movl $1, %eax
movl $0, %ebx
int $0x80
第 35-40 行使用了 1 号系统调用 write() 向屏幕输出一串字符串。根据定义,write() 的返回值(输出的字符数)存放在 eax 中。接着第 21-23 行使用 c 标准库函数 printf() 打印 eax 的值,printf() 的返回值(输出的字符数)也存放在 eax 中。最后第 26-28 行打印 printf() 的返回值。
近期评论