汇编中系统调用的返回值是多少?

Pic*_*ana 4 linux assembly return-value nasm system-calls

当我尝试研究内核的系统调用的返回值时,我找到了描述它们的表,以及我需要将它放在不同的寄存器中以使它们工作.但是,我没有找到任何文档说明我从系统调用获得的返回值是什么.我只是在不同的地方找到我收到的东西将在EAX寄存器中.


TutorialsPoint:

结果通常在EAX寄存器中返回.

汇编语言循序渐进: Jeff Duntemann 编写的Linux书籍在他的程序中多次说明:

  • 查看sys_read在EAX中的返回值

  • 复制sys_read返回值以便安全保存


我没有解释任何有关此返回值的网站.有没有互联网资源?或者有人能解释我这个价值观吗?

Pet*_*des 7

另请参阅这篇关于系统调用的优秀LWN文章,该文章假定具有C知识.

另外:Linux系统调用的权威指南(在x86上)和相关:如果在64位代码中使用32位int 0x80 Linux ABI会发生什么?


C是Unix系统编程的语言,所以所有文档都是用C语言编写的.然后是文档,说明任何给定平台上C接口和asm之间的细微差别,通常在手册页的Notes部分.

sys_read表示原始系统调用(与libc包装函数相对).read系统调用的内核实现是一个名为的内核函数sys_read().你不能用call指令调用它,因为它在内核中,而不是库中.但人们仍然在谈论"召唤sys_read"以区别于libc函数调用.但是,read即使你的意思是原始系统调用(特别是当libc包装器没有做任何特殊操作时),也可以这样说,就像我在这个答案中所做的那样.

另请注意,syscall.h定义常量SYS_read与实际系统调用号一样.(在a int 0x80syscall指令之前放入EAX的值).


Linux系统调用返回值(在x86 中EAX/ RAX上)是成功的非负值或负错误代码.例如,-EFAULT如果您传递无效指针.

syscalls(2)手册页中记录了此行为.

实际上,-1到-4095意味着错误,其他任何意味着成功.glibc的通用syscall(2)包装器使用这个序列: cmp rax, -4095/ jae SYSCALL_ERROR_LABEL,显然可以保证所有Linux系统调用都具有面向未来的能力.有趣的情况包括mmap有效地址可以设置符号位,但必须页面对齐,并且getpriority内核ABI将-20..19返回值范围映射到1..40,并且libc对其进行解码.有关解码系统调用错误返回值的相关答案中的更多详细信息.

更新,是的,对于所有系统调用来说,它肯定是有保证的-4095..这-1是Linux运行的所有体系结构上的错误范围.有关更多详细信息,请参阅AOSP非显而易见的syscall()实现.(将来,不同的体系结构可以为MAX_ERRNO使用不同的值,但是像x86-64这样的现有arches的值保证与Linux保持内核ABI稳定的非破坏用户空间策略的一部分相同. )


要查找特定平台的常量的实际数值,您需要找到它们所在的C头文件#define.有关详细信息,请参阅有关该问题的答案.


每个sys调用的返回值的含义记录在第2节手册页中,如read(2).(sys_read是原始系统调用,glibc read()函数是一个非常薄的包装器.)大多数手册页都有一个返回值的整个部分.例如

返回值

成功时,返回读取的字节数(零表示文件结束),文件位置按此编号提前.如果此数字小于请求的字节数,则不是错误; 这可能发生在例如因为
现在实际可用的字节数较少(可能是因为我们接近
文件结尾,或者因为我们正在从管道或终端
读取),或者因为read()被中断信号.另见说明.

出错时,返回-1,并正确设置errno.在这种情况下,未指定文件位置(如果有)是否
改变.

需要注意的是最后一段描述glibc的包装如何解码值,并设置errno-EAX如果原始系统调用的返回值是负的,所以errno=EFAULT并返回-1如果原始系统调用返回-EFAULT.

并且有一个完整的部分列出了read()允许返回的所有可能的错误代码,以及它们的具体含义read().(POSIX标准化了大多数此行为.)


我不确定glibc解码返回值的确切位置mmap(2),其中返回值不是有符号类型.它可能使用与通用系统调用包装器相同的方法(检查无符号值> -4096UL),但每个系统调用的特定包装器没有实际调整寄存器之间的args并调用该函数的开销.

我没有在glibc源代码树中看到它; 据推测,它被埋藏在某些宏层之下.例如在x86-64宏中

  • @PichiWuana:嗯,C太可移植了,因此有很多规则,比如签名溢出是未定义的行为,签名类型的右移是实现定义的,无论它们是算术还是逻辑移位.但是,知道asm有助于理解C的工作原理,反之亦然.C中的指针和数组与asm中的指针和数组相同.知道了这两个,我可以很容易地看到C函数将如何简单地编译为asm.你甚至可以利用这些知识[通过调整源代码将手持编译器变成更好的asm](http://stackoverflow.com/a/34410357/224132) (2认同)

归档时间:

查看次数:

7758 次

最近记录:

7 年,9 月 前