Каковы соглашения о вызовах для системных вызовов UNIX и Linux на i386 и x86-64
следующие ссылки объясняют соглашения о системных вызовах x86-32 для UNIX (BSD flavor) и Linux:
но каковы соглашения о системных вызовах x86-64 как для UNIX, так и для Linux?
4 ответа:
я проверил их с помощью ассемблера GNU (gas) на Linux.
Ядра Интерфейс
x86-32 соглашение о системных вызовах Linux:
в x86-32 параметры для системного вызова Linux передаются с помощью регистров.
%eax
для syscall_number. %значение регистра ebx, %Екб, %неделя, %в ESI, %EDI, в %эбп используются для прохождения 6 параметры системных вызовов.возвращаемое значение находится в
%eax
. Все остальные регистры (включая EFLAGS) сохраняются по всему элементint x80
.я взял следующий фрагмент из Linux Assembly Tutorial но я сомневаюсь в этом. Если кто-то может показать пример, это было бы здорово.
если аргументов больше шести,
%ebx
должен содержать память место, где находится список аргументов хранится-но не беспокойтесь об этом потому что вряд ли вы будете использовать в операции с более, чем шесть аргументы.для пример и немного больше чтения, см. 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 System Call convention:
x86-64 Mac OS X похож, но отличается. TODO: проверьте, что делает *BSD.
обратитесь к разделу: "А. 2 для amd64 Linux соглашения ядра " из система V приложение бинарный интерфейс amd64 архитектура процессор дополнение. Последнее слово версии i386 и x86-64 System V psABIs можно найти ссылка с этой страницы в репозитории ABI maintainer. (См. также x86 tag wiki для современных ссылок ABI и многих других хороших вещей о x86 asm.)
вот фрагмент из этого раздела:
- приложения пользовательского уровня используют в качестве целочисленных регистров для передачи последовательность %РДИ, %РСИ %гексогена, %rcx следует, %Р8 и Р9. интерфейс ядра использует %rdi, %rsi, %rdx, %r10, %r8 и %r9.
- системный вызов выполняется через
syscall
- инструкции. Это clobbers %rcx и %r11, а также %rax, но другие регистры сохраняются.- номер syscall должен быть передан в регистр %rax.
- системные вызовы ограничены шестью аргументами, аргумент не передается прямо на стеке.
- возвращение из системного вызова, зарегистрируйтесь %Ракс содержит результат системный вызов. Значение в диапазоне от -4095 до -1 указывает ошибка, это
-errno
.- ядру передаются только значения класса INTEGER или класса MEMORY.
помните, что это из специфичного для Linux приложения к ABI, и даже для Linux это информативно, а не нормативно. (Но это на самом деле точно.)
Пользовательский Интерфейс
x86-32 вызов функции конвенция:
в x86-32 параметры были переданы в стек. Последний параметр был помещен сначала в стек, пока все параметры не будут выполнены, а затем
call
инструкция была выполнена. Это используется для вызова функций библиотеки C (libc) в Linux из сборки.
x86-64 соглашение о вызове функций:
х86-64 передает Аргументы через регистры, что является более эффективным, чем конвенции для i386 системы в стеке аргументы. Это позволяет избежать задержка и дополнительные инструкции хранения args в память (кэш), а затем загрузка их обратно в вызываемый объект. Это хорошо работает, потому что есть больше доступных регистров, и лучше для современных высокопроизводительных процессоров, где задержка и выполнение вне порядка имеют значение. (I386 ABI очень старый).
в этой новая механизм: сначала параметры делятся на классы. Класс каждого параметра определяет способ его передачи вызываемому объекту функция.
для получения полной информации см.: "3.2 последовательность вызова функций" из система V приложение бинарный интерфейс amd64 архитектура процессор дополнение, который, в частности, говорится:
как только аргументы классифицируются регистры назначают (в слева-направо) для прохождения следующим образом:
- если класс является памятью, передайте аргумент в стек.
- если класс целочисленный, то следующий доступный реестр последовательность %РДИ, %РСИ %индекса RDX, %rcx следует, %R8 и %R9 используется
так
%rdi, %rsi, %rdx, %rcx, %r8 and %r9
это регистры в целях используется для передачи параметров integer / pointer (т. е. целочисленного класса) в любую функцию libc из сборки. %rdi используется для первого целочисленного параметра. %rsi для 2-го, %rdx для 3-го и так далее. Тогдаcall
инструкция должна быть дана. Стек (%rsp
) должен быть выровнен по 16B, когдаcall
выполняет.если существует более 6 целочисленных параметров, 7-й целочисленный параметр и более поздние передаются в стек. (Вызывающий абонент появляется, так же, как x86-32.)
первые 8 аргументов с плавающей запятой передаются в %xmm0-7, затем в стек. Нет сохраненных вызовов векторных регистров. (Функция со смесью FP и целочисленных аргументов может иметь более 8 полных аргументов регистра.)
функции с переменным числом аргументов (как
printf
) всегда нужны%al
= число аргументов регистра 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. И вообще аби не делает дифференцировать системный вызов против обычных "вызовов функций". Ie, вот конкретный пример соглашений о вызовах x86_64, и он одинаков как для пользовательского пространства Linux, так и для ядра:http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/ (Обратите внимание на последовательность параметров a,b,c,d,e,f):
производительность является одной из причин этих ABI (например, передача параметров через регистры вместо сохранения в памяти стеки)
для 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
а для встроенных есть КПП EABI:
http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf
этот документ является хорошим обзором всех различных условные обозначения:
в дополнение к ссылке, которую Джонатан Леффлер предоставляет в своем ответе, также Агнер Фог Соглашения О Вызове pdf может быть вам полезен.