Следующие ссылки объясняют соглашения о системных вызовах x86-32 для UNIX (BSD-версия) и Linux:
Но каковы соглашения о системных вызовах x86-64 в UNIX и Linux?
Следующие ссылки объясняют соглашения о системных вызовах x86-32 для UNIX (BSD-версия) и Linux:
Но каковы соглашения о системных вызовах x86-64 в UNIX и Linux?
sysret
работы, а rax заменяется возвращаемым значением. Все остальные регистры сохраняются на amd64.Ответы:
Дальнейшее чтение по любой из тем здесь: Полное руководство по системным вызовам Linux
Я проверил это с помощью GNU Assembler (gas) в Linux.
Интерфейс ядра
x86-32 aka i386 Linux Соглашение о системных вызовах:
В x86-32 параметры для системного вызова Linux передаются с использованием регистров.
%eax
для syscall_number. % ebx,% ecx,% edx,% esi,% edi,% ebp используются для передачи 6 параметров системным вызовам.Возвращаемое значение в
%eax
. Все остальные регистры (включая EFLAGS) сохраняются по всемуint $0x80
.Я взял следующий фрагмент из Руководства по сборке Linux, но сомневаюсь в этом. Если кто-то может показать пример, было бы здорово.
Для примера и немного больше чтения, обратитесь к http://www.int80h.org/bsdasm/#alternate-calling-convention . Другой пример Hello World для Linux на i386
int 0x80
: Hello, world на ассемблере с системными вызовами Linux?Существует более быстрый способ совершать 32-битные системные вызовы: использование
sysenter
. Ядро отображает страницу памяти в каждый процесс (vDSO) со сторонойsysenter
танца в пользовательской области, которая должна взаимодействовать с ядром, чтобы он мог найти адрес возврата. Arg для регистрации сопоставления такой же, как и дляint $0x80
. Обычно вы должны звонить в vDSO, а неsysenter
напрямую. (См . Полное руководство по системным вызовам Linux для получения информации о подключении и вызове в vDSO, а также для получения дополнительной информацииsysenter
и всего остального, что связано с системными вызовами.)x86-32 [Free | Open | Net | DragonFly] BSD UNIX Системный вызов UNIX:
Параметры передаются в стек. Перенесите параметры (последний параметр вставлен первым) в стек. Затем добавьте дополнительные 32-битные фиктивные данные (на самом деле это не фиктивные данные. Обратитесь к следующей ссылке для получения дополнительной информации), а затем дайте инструкцию системного вызова.
int $0x80
http://www.int80h.org/bsdasm/#default-calling-convention
Соглашение о системных вызовах Linux x86-64:
x86-64 Mac OS X похожа, но отличается . ТОДО: проверь, что делает * BSD.
См. Раздел: «A.2 Соглашения о ядре AMD64 Linux » двоичного интерфейса приложений System V, добавление к процессору архитектуры AMD64 . Последние версии psABI i386 и x86-64 System V можно найти на этой странице в репозитории сопровождающего ABI . (См. Такжеx86 пометьте вики актуальными ссылками ABI и множеством других полезных вещей о x86 asm.)
Вот фрагмент из этого раздела:
Помните, что это из специфического для Linux приложения к ABI, и даже для Linux это информативно, а не нормативно. (Но это на самом деле точно.)
Этот 32-битный
int $0x80
ABI может использоваться в 64-битном коде (но настоятельно не рекомендуется). Что произойдет, если вы используете 32-битный int 0x80 Linux ABI в 64-битном коде? Он по-прежнему усекает свои входные данные до 32-разрядных, поэтому он не подходит для указателей и имеет нули r8-r11.Пользовательский интерфейс: вызов функции
Соглашение о вызове функции x86-32:
В x86-32 параметры были переданы в стек. Последний параметр помещался сначала в стек, пока все параметры не были выполнены, а затем
call
была выполнена инструкция. Это используется для вызова функций библиотеки C (libc) в Linux из сборки.Современные версии i386 System V ABI (используемые в Linux) требуют 16-байтового выравнивания
%esp
перед acall
, как всегда требовалось для x86-64 System V ABI. Вызывающим лицам разрешается предполагать, что они используют 16-байтовые загрузки / хранилища SSE, которые выдают ошибку при невыравнивании. Но исторически, Linux требовал только 4-байтового выравнивания стека, поэтому потребовалась дополнительная работа, чтобы зарезервировать естественно выровненное пространство даже для 8-байтовогоdouble
или чего-то еще.Некоторые другие современные 32-разрядные системы все еще не требуют выравнивания стека более 4 байтов.
x86-64 System V user-space Соглашение о вызове функций:
x86-64 System V передает аргументы в регистрах, что более эффективно, чем в i386 в соглашении о стеке в System v. Это позволяет избежать задержек и дополнительных инструкций по сохранению аргументов в памяти (кеш), а затем снова загружать их в вызываемый объект. Это хорошо работает, потому что доступно больше регистров, и лучше для современных высокопроизводительных ЦП, где важны задержки и неупорядоченное выполнение. (I386 ABI очень старый).
В этом новом механизме: сначала параметры делятся на классы. Класс каждого параметра определяет способ его передачи в вызываемую функцию.
Для получения полной информации см. «3.2 Последовательность вызова функций» Приложения к архитектуре AMD64 для двоичного интерфейса приложения System V, которое гласит:
Так же
%rdi, %rsi, %rdx, %rcx, %r8 and %r9
как и регистры , используемые для передачи параметров целочисленного значения / указателя (т. Е. Класса INTEGER) в любую функцию libc из сборки. % rdi используется для первого параметра INTEGER. % rsi для 2-го,% rdx для 3-го и так далее. Тогдаcall
инструкция должна быть дана. Стек (%rsp
) должен быть выровнен по 16B при выполненииcall
.Если имеется более 6 параметров INTEGER, 7-й параметр INTEGER и более поздние передаются в стек. (Звонящий звонит, так же, как x86-32.)
Первые 8 аргументов с плавающей запятой передаются в% xmm0-7, а затем в стеке. Не существует сохраняемых при вызове векторных регистров. (Функция с сочетанием FP и целочисленных аргументов может иметь более 8 аргументов в регистре.)
Функции Variadic ( например
printf
) всегда должны%al
= число аргументов регистра FP.Существуют правила, когда упаковывать структуры в регистры (
rdx:rax
при возврате) и в память. Посмотрите ABI для деталей и проверьте выходные данные компилятора, чтобы убедиться, что ваш код согласен с компиляторами о том, как что-то должно быть передано / возвращено.Обратите внимание, что соглашение о вызове функций в Windows x64 имеет несколько существенных отличий от x86-64 System V, таких как теневое пространство, которое должно быть зарезервировано вызывающей стороной (вместо красной зоны), и сохраняемый вызов xmm6-xmm15. И совсем другие правила, по которым arg идет в каком регистре.
источник
int 0x80
ABI Linux в 64-битном коде, это именно то, что происходит: stackoverflow.com/questions/46087730/… . Это нули R8-R11, и работает точно так же, как при запуске в 32-разрядном процессе. В этом Q & A у меня есть пример, показывающий, что он работает или не работает с усечением указателя. И я также покопался в исходном коде ядра, чтобы показать, почему он так себя ведет.Возможно, вы ищете ABI x86_64?
Если это не совсем то, что вам нужно, используйте «x86_64 abi» в предпочитаемой вами поисковой системе, чтобы найти альтернативные ссылки.
источник
Соглашения о вызовах определяют, как параметры передаются в регистрах при вызове или при вызове другой программой. И лучший источник этих соглашений в форме стандартов ABI, определенных для каждого из этих аппаратных средств. Для простоты компиляции тот же ABI также используется в пространстве пользователя и программе ядра. Linux / Freebsd используют тот же ABI для x86-64 и другой набор для 32-разрядных. Но x86-64 ABI для Windows отличается от Linux / FreeBSD. И вообще ABI не различает системные вызовы от обычных «вызовов функций». То есть, вот конкретный пример соглашений о вызовах 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
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
источник
Исходные комментарии ядра Linux 5.0
Я знал, что специфика x86 ниже
arch/x86
, и что системные вызовы не работаютarch/x86/entry
. Так что быстрый переходgit grep rdi
в этот каталог приводит меня к arch / x86 / entry / entry_64.S :и для 32-битной в arch / x86 / entry / entry_32.S :
glibc 2.29 Реализация системного вызова Linux x86_64
Теперь давайте обманем, посмотрев основные реализации libc и посмотрим, что они делают.
Что может быть лучше, чем смотреть на glibc, который я использую сейчас, когда пишу этот ответ? :-)
В glibc 2.29 определены системные вызовы x86_64,
sysdeps/unix/sysv/linux/x86_64/sysdep.h
которые содержат интересный код, например:и:
которые я чувствую, довольно понятны. Обратите внимание, что, похоже, это было разработано для точного соответствия правилам вызова обычных функций ABI AMD64 в System V: https://en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions
Быстрое напоминание о сгустках:
cc
означает флаг регистров. Но Питер Кордес комментирует, что в этом нет необходимости.memory
означает, что указатель может быть передан в сборку и использован для доступа к памятиДля явного минимального запускаемого примера с нуля смотрите этот ответ: Как вызвать системный вызов через sysenter во встроенной сборке?
Сделайте несколько системных вызовов в сборке вручную
Не очень научно, но весело
x86_64.S
GitHub upstream .
aarch64
Я показал минимальный работающий пример пользовательского пространства по адресу: /reverseengineering/16917/arm64-syscalls-table/18834#18834 код ядра grep TODO здесь, должно быть легко.
источник
"cc"
Колошматить ненужно: Системные вызовы Linux сохранение / восстановление RFLAGS (Вsyscall
/sysret
инструкции сделать это с помощью R11, и ядро не изменяет сохраненную R11 / RFLAGS только посредствомptrace
системных вызовов отладчика.) Не то, что он никогда не имеет значение, потому что"cc"
колошматить является неявный для x86 / x86-64 в GNU C Extended asm, поэтому вы ничего не можете получить, оставив его вне.