Подальше читання для будь-якої з тем тут: Постійний посібник із системних дзвінків Linux
Я перевірив їх за допомогою GNU Assembler (газ) в Linux.
Інтерфейс ядра
x86-32 aka i386 Конвенція про системний виклик Linux:
У x86-32 параметри для системного виклику Linux передаються за допомогою регістрів. %eax
для syscall_number. % ebx,% ecx,% edx,% esi,% edi,% ebp використовуються для передачі 6 параметрів до системних викликів.
Повертається значення в %eax
. Усі інші регістри (включаючи EFLAGS) зберігаються по всій території int $0x80
.
Я взяв наступний фрагмент з підручника Linux Assembly, але я сумніваюся з цього приводу. Якщо хтось може показати приклад, було б чудово.
Якщо аргументів більше шести,
%ebx
повинно містити місце пам’яті, де зберігається список аргументів, - але не хвилюйтеся з цього приводу, оскільки навряд чи ви будете використовувати системний виклик з більш ніж шістьма аргументами.
Для прикладу та трохи більше прочитання див. Http://www.int80h.org/bsdasm/#alternate-calling-convention . Ще один приклад Hello World для i386 Linux, що використовує int 0x80
: Привіт, світ у мові складання з системними дзвінками Linux?
Існує більш швидкий спосіб здійснення 32-бітних системних дзвінків: використання sysenter
. Ядро відображає сторінку пам'яті у кожному процесі (vDSO), з боку простору користувача sysenter
танцю, який повинен співпрацювати з ядром, щоб він міг знайти зворотну адресу. Аргумент для реєстрації відображення такий же, як і для int $0x80
. Зазвичай ви повинні зателефонувати в vDSO, а не використовувати sysenter
безпосередньо. (Дивіться Посібник з остаточних системних викликів Linux для отримання інформації про з'єднання та виклик у vDSO, а також про додаткову інформацію про sysenter
все та інше, що стосується системних дзвінків.)
x86-32 [Безкоштовно | Відкрити | Net | DragonFly] Конвенція про системний виклик BSD UNIX:
Параметри передаються на стек. Натисніть параметри (останній параметр, натиснутий першим) в стек. Потім натисніть додаткові 32-розрядні манекенні дані (фактично це не манекенні дані. Для отримання додаткової інформації див. Наступне посилання), а потім дайте інструкцію щодо системного викликуint $0x80
http://www.int80h.org/bsdasm/#default-calling-convention
x86-64 Конвенція про системний виклик Linux:
x86-64 Mac OS X схожий, але різний . TODO: перевірити, що робить * BSD.
Дивіться розділ: "А.2 AMD64 Linux Kernel конвенції" про System V Application Binary Interface AMD64 архітектури процесора доповнення . Останні версії iAB-i386 та x86-64 System V psABI можна знайти на цій сторінці в репо- репортажі технічного обслуговування ABI . (Див. Такожx86 тег-вікі для оновлених посилань ABI та багатьох інших хороших матеріалів про x86 asm.)
Ось фрагмент із цього розділу:
- Програми рівня користувача використовують як цілі регістри для передачі послідовності% rdi,% rsi,% rdx,% rcx,% r8 та% r9. Інтерфейс ядра використовує% rdi,% rsi,% rdx,% r10,% r8 та% r9.
- Виклик системи здійснюється за допомогою
syscall
інструкції . Це клобери% rcx і% r11 , а також повернене значення% rax, але інші регістри зберігаються.
- Кількість syscall має бути передана в регістр% rax.
- Системні виклики обмежені шістьма аргументами, жоден аргумент не передається безпосередньо в стек.
- Повернувшись із системного виклику, регістр% rax містить результат системного виклику. Значення в діапазоні між -4095 і -1 вказує на помилку, воно є
-errno
.
- Ядра передаються лише значення класу INTEGER або MEMORY класу.
Пам'ятайте, що це додаток для ABI, що стосується Linux, і навіть для Linux це інформативно не є нормативним. (Але насправді це точно.)
Цей 32-розрядний int $0x80
ABI можна використовувати в 64-бітовому коді (але настійно не рекомендується). Що станеться, якщо ви використовуєте 32-розрядний int 0x80 Linux ABI у 64-бітному коді? Він все ще скорочує свої входи до 32-розрядних, тому він не підходить для покажчиків, і це нулі r8-r11.
Інтерфейс користувача: виклик функції
Конвенція про виклик x86-32:
У x86-32 параметри передавались на стек. Останній параметр був спочатку натиснений на стек, поки всі параметри не виконані, а потім call
виконана інструкція. Це використовується для виклику функцій бібліотеки С (libc) в Linux з монтажу.
Сучасні версії i386 System V ABI (використовуються на Linux) вимагають 16-байтового вирівнювання %esp
до a call
, як завжди вимагало система x86-64 System V ABI. Калеям дозволяється припускати, що вони використовують та використовують 16-байтові навантаження / сховища SSE, які виходять з ладу при несанкціонованому навантаженні. Але історично для Linux потрібно було лише вирівнювання 4-байтних стеків, тому знадобилася додаткова робота, щоб резервувати природно вирівняний простір навіть для 8-байтового double
чи іншого.
Деякі інші сучасні 32-бітні системи все ще не потребують вирівнювання стека більше 4-х байт.
x86-64 Система V в просторі користувача Функція Конвенція про виклик:
x86-64 System V передає аргументи в регістри, що є більш ефективним, ніж конвенція про стеки аргументів i386 System V. Це дозволяє уникнути затримки та додаткових вказівок зберігання аргументів у пам'яті (кеш-пам'яті) та повторного завантаження їх назад у виклику. Це добре працює, оскільки доступно більше регістрів, і це краще для сучасних високопродуктивних процесорів, де значення мають затримка та виконання поза замовленням. (ABI i386 дуже старий).
У цьому новому механізмі: Спочатку параметри діляться на класи. Клас кожного параметра визначає спосіб передачі його викликаної функції.
Повну інформацію див. У розділі "3.2 Послідовність викликів функцій" додатку System V Бінарний інтерфейс AMD64 Додаток архітектури процесора, який читає, зокрема:
Після класифікації аргументів реєстри призначаються (у лівому та правому порядку) для передачі наступним чином:
- Якщо клас MEMORY, передайте аргумент на стек.
- Якщо клас INTEGER, використовується наступний доступний регістр послідовності% rdi,% rsi,% rdx,% rcx,% r8 і% r9
Так само %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 загальних аргументів реєстру.)
Різноманітні функції ( якprintf
) завжди потребують %al
= кількість аргументів реєстру FP.
Існують правила, коли потрібно упакувати структури в регістри ( rdx:rax
при поверненні) проти пам'яті. Детальні відомості див. У ABI та перевірте вихід компілятора, щоб переконатися, що ваш код узгоджується з компіляторами про те, як щось потрібно передавати / повертати.
Зауважте, що умова виклику функції Windows x64 має декілька суттєвих відмінностей від системи x86-64 System V, як тіньовий простір, який повинен бути зарезервований абонентом (замість червоної зони), і збережений виклик xmm6-xmm15. І дуже різні правила, за якими аргументами йде в який реєстр.