我在网上找到了图表,其中显示了x86_64 linux nasm程序集的各种系统调用,总的系统调用似乎有380ish,但是我每本书或每本教程都只能找到“一些系统调用的工作方式以及它们的作用?” 有谁知道我可以使用nasm汇编程序在x86_64 linux汇编程序的每个系统调用中找到信息?
任何帮助都会很棒。
查看Linux手册页(第2节)。 http://man7.org/linux/man-pages/dir_section_2.html
创建x86-64机器代码所用的汇编程序(或C编译器)都没有关系,您可以进行的系统调用相同。(在RAX中放置一个呼叫号码并运行syscall
指令;在内核内部,它使用该号码为函数指针表建立索引。-ENOSYS
如果超出范围,则返回。)
调试程序strace ./my_program
以跟踪其进行的系统调用。 这会在每次调用的基础上对args进行解码并将值返回为有意义的内容,因此您可以轻松查看是否传递了错误的指针-EFAULT
,例如使syscall返回。(系统调用不会引发SIGSEGV / segfault,它们只会返回错误。)
/usr/include/asm/unistd_64.h
有实际数字。(包含<asm/unistd.h>
在64位编译时)。手册页将以C语法记录args。 给定C原型,您可以根据x86-64 System V ABI来设计asm ABI。(与功能调用ABI相同,除了第4个arg用R10代替RCX,如果有的话。) 在i386和x86-64上UNIX和Linux系统调用的调用约定是什么?
syscall(2)
是用于系统调用的glibc包装函数,并且syscall手册页还记录了适用于各种Linux平台(x86-64,SPARC,ARM等)的asm ABI,包括用于调用号和ret val的寄存器,以及用于进入内核。注意,函数名称与x86-64 syscall
指令相同只是一个巧合。
没有人愿意为每种不同类型的asm语法的每个系统调用编写详尽的文档 -手册页以及调用约定文档中都包含所有信息;Linux手册页的NOTES部分记录了C库包装器API与底层asm系统调用之间的区别。
又见https://blog.packagecloud.io/eng/2016/04/05/the-definitive-guide-to-linux-system-calls/更多包括VDSO东西高效getpid
/ clock_gettime
甚至没有进入内核。
但是,有些人会编译系统调用名称以及Linux x86-64调用编号和arg寄存器的表。我从来没有发现它有用(syscall调用约定与函数调用约定非常接近,以至于容易记住),但是如果需要的话,也可以使用https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/。
两次调用之间存在POSIX函数和原始Linux系统调用之间的显着差异:例如brk
/sbrk
,并且getpriority
“ nice”级别的返回值也有偏差,因此它们不在-4095..-1
错误代码范围内。 但是大多数系统调用都具有与C库包装器原型完全匹配的ABI,在这种情况下,NOTES部分未提及任何内容。
如果我能在网上和书本上找到的只是300个总系统调用中的几个系统调用是如何工作的,那么如何学习汇编程序呢?
@Spencer_J:那是一个非主流。一般来说,有很多关于如何学习asm的材料。一旦了解了asm和调用约定,就可以直接阅读任何Linux手册页并知道如何从asm调用它。(因为它们都遵循将C args映射到asm的标准调用约定,并且在ABI中有记录。 在i386和x86-64上UNIX和Linux系统调用的调用约定是什么)
不幸的是,甚至手册页有时也是错误的。比较
struct stat
在man7.org/linux/man-pages/man2/stat.2.html中描述的实例和在stackoverflow.com/questions/27216616/中发现的真实结构。在手册页中交换结构成员st_mode和st_nlink的顺序。