Почему `write ()` выполняется с помощью инструкции `call` вместо прерывания? - PullRequest
2 голосов
/ 05 марта 2020

Я пытался немного поиграть в сборку. Насколько я понимаю, системные вызовы выполняются через прерывание, генерируемое инструкцией 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

Почему это так?

Есть ли способ увидеть, как на самом деле выполняется вызов sys в OS X?

Ответы [ 2 ]

3 голосов
/ 05 марта 2020

Поскольку вы вызываете функцию из стандартной библиотеки C. Эта функция может или не может обернуть системный вызов, может использовать неожиданный системный вызов (например, более современный, чем оригинал) и, как правило, должна выполнять различные операции настройки и разрыва для адаптации между C и соглашениями о вызовах системного вызова.

Оболочка, как правило, довольно тонкая, но она все еще является оберткой (например, на linux системные вызовы обычно возвращают либо успех, либо -errno в случае сбоя, затем lib c должна проверить на неудачу, оставаясь sh ошибка в соответствующем локальном потоке и возврат «правильного» значения, определенного стандартом или POSIX вместо этого).

0 голосов
/ 05 марта 2020

Поскольку @ user207421 упоминается в комментарии, write, являющаяся C стандартной библиотечной функцией, должна в конечном итоге обернуть платформу, определяющую c запись системного вызова. В MacOS фасадный слой определен в libsystem_kernel.dylib, который используется в стандартной реализации библиотеки MacOS C libSystem.B.dylib. Номер системных вызовов не является общедоступным c интерфейсом и может изменяться в разных версиях MacOS. Кроме того, к отличной точке @fuz некоторые из них могут даже устареть и больше не иметь прямой syscall записи / номера, но останутся поддерживаемыми слоем оболочки.

При запуске вашей программы вы можете проверить фактическую syscall в действии в 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) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...