为什么通过调用指令而不是中断来执行write()?

问题描述 投票:1回答:2

我试图参加一些集会。我的理解是,系统调用是通过syscall指令生成的中断进行的。

但是使用clang -S在计算机上编译一个简单程序后:

int main() {
  write(0, "HI", 2);
  return 0;
}

生成的相关程序集是:

    movl    $0, -4(%rbp)
    leaq    L_.str(%rip), %rsi
    movl    $2, %edx
    movb    $0, %al
    callq   _write

为什么?

是否有办法查看在OS X上正在执行的实际sys调用?

macos assembly clang x86-64
2个回答
1
投票

因为您正在从C标准库中调用函数。该功能可能会也可能不会包装系统调用,可能会使用意外的系统调用(例如比原始系统调用更现代的系统调用),并且通常必须执行各种设置和拆卸操作以适应C和系统调用调用约定。

包装器通常很薄,但是它仍然是包装器(例如,在linux上,系统调用通常在失败的情况下返回成功或-errno,libc然后必须检查是否失败,将errno存放在相应的threadlocal和返回标准或POSIX定义的“适当”值)。


0
投票

您正在看到这是因为所有系统调用都由Apple包装,并在libsystem_kernel.dylib中定义了外观层。苹果之所以这样做,是因为系统调用号码不是公共接口,并且在MacOS版本之间可能会发生变化。启动程序时,可以使用以下命令验证lldb中实际的系统调用:

lldb ./a.out
b write
run
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00007fff63e0f040 libsystem_kernel.dylib`write
libsystem_kernel.dylib`write:
->  0x7fff63e0f040 <+0>:  mov    eax, 0x2000004
    0x7fff63e0f045 <+5>:  mov    r10, rcx
    0x7fff63e0f048 <+8>:  syscall 
    0x7fff63e0f04a <+10>: jae    0x7fff63e0f054            ; <+20>
Target 0: (a.out) stopped.
(lldb) 
© www.soinside.com 2019 - 2024. All rights reserved.