Каковы соглашения о вызовах для системных вызовов 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.)
вот фрагмент из этого раздела:
- приложения пользовательского уровня используют как целочисленные регистры для передачи последовательность %РДИ, %РСИ %гексогена, %rcx следует, %Р8 и Р9. интерфейс ядра использует %rdi, %rsi, %rdx, %r10, %r8 и %r9.
- системный вызов выполняется через
syscall
- инструкции. Это clobbers %rcx и %r11, а также %rax, но другие регистры сохраняются.- номер syscall должен быть передан в регистре %rax.
- системные вызовы ограничены шестью аргументами, аргумент не передается прямо в стопку.
- возвращаясь из syscall, регистр %rax содержит результат системный вызов. Значение в диапазоне от -4095 до -1 указывает ошибка, это
-errno
.- ядру передаются только значения класса 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 архитектура процессор дополнение, который, в частности, говорится:
как только аргументы классифицируются регистры назначают (в слева-направо) для прохождения следующим образом:
- если класс является памятью, передайте аргумент в стек.
- если класс является целочисленным, то следующий доступный регистр последовательность %РДИ, %РСИ %индекса 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 параметров):
производительность является одной из причин этих ABI (например, передача параметров через регистры вместо сохранения в память stacks)
для ARM есть различные ABI:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html
конвенция 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
этот документ является хорошим обзором всех различных условные обозначения:
в дополнение к ссылке, которую Джонатан Леффлер предоставляет в своем ответе, также Agner Fog's Соглашения О Вызове pdf может быть вам полезен.