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


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

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

4 110

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.)

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

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

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

  1. если класс является памятью, передайте аргумент в стек.
  2. если класс целочисленный, то следующий доступный реестр последовательность %РДИ, %РСИ %индекса 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):

A good rendering of calling conventions vs registers usage

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

для 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

а для встроенных есть КПП EABI:

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

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

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

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