Каковы соглашения о вызовах для системных вызовов UNIX и Linux на i386 и x86-64

следующие ссылки объясняют соглашения о системных вызовах x86-32 для UNIX (BSD flavor) и Linux:

но каковы соглашения о системных вызовах x86-64 для UNIX и Linux?

4 ответов


я проверил их с помощью GNU Assembler (gas) в Linux.

Ядра Интерфейс

x86-32 соглашение о системных вызовах Linux:

в x86-32 параметры для системного вызова Linux передаются с помощью регистров. %eax для syscall_number. %значение регистра ebx, %Екб, %неделя, %в ESI, %EDI, в %эбп используются для прохождения 6 параметры системных вызовов.

возвращаемое значение в %eax. Все остальные регистры (включая EFLAGS) сохраняются через the int x80.

я взял следующий фрагмент из Linux Assembly Tutorial но я сомневаюсь в этом. Если кто-то может показать пример, это было бы здорово.

если есть более шести аргументов, %ebx должен содержать память расположение списка аргументов хранится-но не беспокойтесь об этом потому что маловероятно, что вы будете использовать syscall с более чем шестью аргументы.

для пример и немного больше чтения, см.http://www.int80h.org/bsdasm/#alternate-calling-convention

есть более быстрый способ сделать 32-битные системные вызовы: с помощью sysenter. Ядро отображает страницу памяти в каждый процесс (vdso) со стороны пользовательского пространства sysenter, который должен сотрудничать с ядром, чтобы он мог найти обратный адрес. arg для регистрации отображения такое же, как для int x80, но вместо этой инструкции код должен вызовите функцию в vdso. (TODO: обновите это со ссылкой и / или конкретной информацией).

x86-32 [Free / Open|Net / DragonFly]соглашение о системных вызовах BSD UNIX:

параметры передаются в стеке. Нажмите Параметры (последний параметр, нажатый первым) на стек. Затем нажмите дополнительный 32-бит фиктивных данных (на самом деле это не фиктивные данные. см. следующую ссылку для получения дополнительной информации), а затем дайте инструкцию системного вызова int x80

http://www.int80h.org/bsdasm/#default-calling-convention


x86-64 соглашение о системных вызовах Linux:

x86-64 Mac OS X похож, но отличается. TODO: проверьте, что делает *BSD.

см. раздел: "A. 2 AMD64 Linux соглашения ядра " из System V Application бинарный интерфейс amd64 архитектура процессор дополнение. Последнее слово версии системы i386 и x86-64 V psABIs можно найти ссылка с этой страницы в репо сопровождающего ABI. (См. также x86 tag wiki для современных ссылок ABI и многих других хороших вещей о x86 asm.)

вот фрагмент из этого раздела:

  1. приложения пользовательского уровня используют как целочисленные регистры для передачи последовательность %РДИ, %РСИ %гексогена, %rcx следует, %Р8 и Р9. интерфейс ядра использует %rdi, %rsi, %rdx, %r10, %r8 и %r9.
  2. системный вызов выполняется через syscall - инструкции. Это clobbers %rcx и %r11, а также %rax, но другие регистры сохраняются.
  3. номер syscall должен быть передан в регистре %rax.
  4. системные вызовы ограничены шестью аргументами, аргумент не передается прямо в стопку.
  5. возвращаясь из syscall, регистр %rax содержит результат системный вызов. Значение в диапазоне от -4095 до -1 указывает ошибка, это -errno.
  6. ядру передаются только значения класса INTEGER или памяти класса.

помните, что это из специфичного для Linux приложения к ABI, и даже для Linux это информативно, а не нормативно. (Но на самом деле это так.)

Пользовательский Интерфейс

х86-32 вызова конвенция:

в x86-32 параметры были переданы в стек. Последний параметр был нажат сначала в стек, пока все параметры не будут выполнены, а затем call инструкция была выполнена. Это используется для вызова функций библиотеки C (libc) в Linux из сборки.


x86-64 соглашение о вызове функций:

x86-64 передает args в регистрах, что более эффективно, чем соглашение args стека i386 System V. Он избегает задержка и дополнительные инструкции хранения args в память (кэш), а затем загрузка их обратно в вызываемого абонента. Это хорошо работает, потому что доступно больше регистров, и лучше для современных высокопроизводительных процессоров, где важна латентность и выполнение вне заказа. (I386 ABI очень старый).

в этой new механизм: сначала параметры делятся на классы. Класс каждого параметра определяет способ, которым он передается вызываемому параметру функция.

для получения полной информации обратитесь к : "3.2 функция вызова последовательность"System V Application бинарный интерфейс amd64 архитектура процессор дополнение, который, в частности, говорится:

как только аргументы классифицируются регистры назначают (в слева-направо) для прохождения следующим образом:

  1. если класс является памятью, передайте аргумент в стек.
  2. если класс является целочисленным, то следующий доступный регистр последовательность %РДИ, %РСИ %индекса RDX, %rcx следует, %R8 и %R9 используется

так %rdi, %rsi, %rdx, %rcx, %r8 and %r9 являются регистры в целях используется для передачи параметров integer / pointer (т. е. INTEGER class) любой функции libc из сборки. %rdi используется для первого целочисленного параметра. %rsi для 2-го, %rdx для 3-го и так далее. Тогда call инструкция должна быть дана. Стек (%rsp) должен быть выровнен по 16B, когда call выполняет.

если имеется более 6 целочисленных параметров, 7-й целочисленный параметр и более поздние передаются в стек. (Звонящий соз, так же, как x86-32.)

первые 8 args с плавающей запятой передаются в %xmm0-7, позже в стеке. Нет называют сохранившиеся векторные регистры. (Функция с сочетанием аргументов FP и integer может иметь более 8 общих аргументов регистра.)

функции с переменным числом аргументов (как printf) всегда нужны %al = число args регистра FP.

существуют правила, когда паковать структуры в регистры (rdx:rax о возврате) и в памяти. Подробнее см. В ABI и проверьте вывод компилятора, чтобы убедиться, что ваш код согласен с компиляторами о том, как что-то должно быть передано/возвращено.


возможно, вы ищете x86_64 ABI?

Если это не совсем то, что вам нужно, используйте 'x86_64 abi' в предпочитаемой поисковой системе, чтобы найти альтернативные ссылки.


соглашения о вызовах определяют, как параметры передаются в регистрах при вызове или вызываются другой программой. И лучший источник этих соглашений находится в форме стандартов ABI, определенных для каждого из этих аппаратных средств. Для удобства компиляции тот же ABI также используется программой userspace и kernel. Linux / Freebsd следуют тому же ABI для x86-64 и другому набору для 32-бит. Но x86-64 ABI для Windows отличается от Linux/FreeBSD. И вообще аби не дифференцировать системный вызов против обычных "вызовов функций". Т. е. вот конкретный пример соглашений о вызовах x86_64, и он одинаков как для пользовательского пространства Linux, так и для ядра:http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/ (Обратите внимание на последовательность A,b,c,d,e, f параметров):

A good rendering of calling conventions vs registers usage

производительность является одной из причин этих ABI (например, передача параметров через регистры вместо сохранения в память stacks)

для ARM есть различные ABI:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf

конвенция ARM64:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

для Linux на PowerPC:

http://refspecs.freestandards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf

и для встроенного есть PPC EABI:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

этот документ является хорошим обзором всех различных условные обозначения:

http://www.agner.org/optimize/calling_conventions.pdf


в дополнение к ссылке, которую Джонатан Леффлер предоставляет в своем ответе, также Agner Fog's Соглашения О Вызове pdf может быть вам полезен.