以下链接解释了UNIX(BSD风格)和Linux的x86-32系统调用约定:
但是UNIX和Linux上的x86-64系统调用约定是什么?
我们如何在x86 Linux中直接使用sysenter/syscall实现系统调用?有人可以提供帮助吗?如果您还可以显示amd64平台的代码,那就更好了.
我知道在x86中,我们可以使用
__asm__(
" movl $1, %eax \n"
" movl $0, %ebx \n"
" call *%gs:0x10 \n"
);
Run Code Online (Sandbox Code Playgroud)
间接路由到sysenter.
但是我们如何使用sysenter/syscall直接编码来发出系统调用呢?
我找到了一些材料http://damocles.blogbus.com/tag/sysenter/.但仍然难以弄明白.
我读了LKD 1中的一些段落, 我无法理解下面的内容:
从用户空间访问系统调用
通常,C库提供对系统调用的支持.用户应用程序可以从标准头中提取函数原型并与C库链接以使用您的系统调用(或者库例程,而该库例程又使用您的系统调用).但是,如果您刚刚编写了系统调用,那么glibc已经支持它是值得怀疑的!
值得庆幸的是,Linux提供了一组用于包装系统调用访问的宏.它设置寄存器内容并发出陷阱指令.这些宏被命名,其中介于0和6之间.该数字对应于传递给系统调用的参数数量,因为宏需要知道预期的参数数量,从而推入寄存器.例如,考虑系统调用,定义为
_syscalln()nopen()Run Code Online (Sandbox Code Playgroud)long open(const char *filename, int flags, int mode)在没有显式库支持的情况下使用此系统调用的syscall宏将是
Run Code Online (Sandbox Code Playgroud)#define __NR_open 5 _syscall3(long, open, const char *, filename, int, flags, int, mode)然后,应用程序可以简单地调用
open().对于每个宏,有2 + 2×n个参数.第一个参数对应于系统调用的返回类型.第二个是系统调用的名称.接下来是系统调用顺序的每个参数的类型和名称.的
__NR_open定义是在<asm/unistd.h>; 它是系统呼叫号码.的_syscall3宏扩展到与联汇编C函数; 程序集执行上一节中讨论的步骤,将系统调用号和参数推送到正确的寄存器中,并发出软件中断以陷入内核.将此宏放在应用程序中是使用open()系统调用所需的全部内容.让我们编写宏来使用我们精彩的新
foo()系统调用,然后编写一些测试代码来展示我们的努力.Run Code Online (Sandbox Code Playgroud)#define __NR_foo 283 __syscall0(long, foo) int main () { long stack_size; stack_size = foo (); printf ("The kernel stack size is %ld\n", stack_size); return 0; }
是什么 …
https://www.cs.fsu.edu/~langley/CNT5605/2017-Summer/assembly-example/assembly.html
我看到如下示例。但是我没有找到系统调用的手册。例如,60 表示退出,1 表示写入。是否有所有系统调用的完整手册(包括调用号和参数的含义)?
global _start
section .text
_start:
; ssize_t write(int fd, const void *buf, size_t count)
mov rdi,1 ; fd
mov rsi,hello_world ; buffer
mov rdx,hello_world_size ; count
mov rax,1 ; write(2)
syscall
; exit(result)
mov rdi,0 ; result
mov rax,60 ; exit(2)
syscall
hello_world: db "Hello World!",10
hello_world_size EQU $ - hello_world
Run Code Online (Sandbox Code Playgroud)