|
Asm/C++/Delphi/Py/PHP/VBA
|
||||||||||||||||||||||||||||||||||||||||||||||
Системные вызовы в Linux18.07.2018, 12:37. Показов 23959. Ответов 11
Метки asm, asm7x, int 0x80, int 80h, linux, nasm, syscall, sysenter, system calls, ubuntu, ассемблер, с, системные вызовы (Все метки)
В Linux, в отличие от Windows, прямые системные вызовы используются довольно часто. По меньшей мере, консольные приложения, написанные на ассемблере, порой содержат лишь системные вызовы, без обращений к функциям библиотек. Причём, этот механизм (как и номера функций(!)) различается для кода 32- и 64-битной разрядности (кстати, в Linux существует ещё и x32 ABI – это, попросту говоря, 64-битный код с 32-битными указателями). Давайте разберёмся... ![]() 32-битный код (x86 ABI, архитектура i386) Для приложений x86 имеется 2 варианта вызова системных функций:
Наиболее распространённый (хотя и более медленный), поскольку осуществляется проще и поддерживается любым процессором 386+.
Осуществляется быстрее, но немного сложнее и поддерживается только процессорами Pentium II и старше (а что, у кого-то более старый? )
Зачем нужны такие сложности?
Дело в том, что инструкция
sysenter, осуществляющая вход (переключение) в режим ядра, заносит в регистры EIP и ESP определённые значения (предварительно загруженные системой в специальные MSR-регистры), не сохраняя нигде адреса возврата и старого значения ESP. Поэтому вызывающему коду необходимо делать это самостоятельно (чтобы продолжить своё выполнение), и вполне логично сохранять их именно в стеке. Инструкция выхода из режима ядра (переключения в режим пользователя) sysexit загружает в ESP значение регистра ECX, а в EIP – значение регистра EDX, поэтому эти регистры, во избежание их порчи, также необходимо сохранять (в стеке). Ну и для того, чтобы передать ядру указатель стека пользовательской программы (оно же изменяется инструкцией sysenter, см. выше), значение ESP записывается в EBP, предварительно сохранив последний.Однако, если системные функции заканчивались бы просто инструкцией sysexit, было бы логичнее сохранять адрес возврата последним, чтобы ядро выполняло:
sysexit) не сразу обратно в пользовательскую программу, а в промежуточную процедуру, которая делает следующее:
Здесь всё несколько проще (за исключением странной очерёдности использования регистров для передачи параметров).
Почему это происходит?
Дело в том, что инструкция входа в режим ядра
syscall сохраняет в регистре RCX значение RIP, а в R11 – значение регистра флагов (указатель стека RSP при этом не меняется) и переходит к выполнению функции ядра (адрес которой хранится в специальном MSR-регистре). Инструкция sysret же выполняет всё наоборот: восстанавливает RIP из регистра RCX и регистр флагов (почти весь) из регистра R11.Поскольку в x64 кол-во регистров довольно много, а RCX и R11 не участвуют для передачи параметров, создатели системы решили не заморачиваться с сохранением этих регистров (возможно, заодно и для ускорения системного вызова и возврата). Почему используются именно эти 2 регистра? Спросите об этом у специалистов Intel (и заодно про sysexit) – потом расскажете ![]() Что же касается странной очерёдности использования регистров для передачи параметров, то здесь ситуация такова. В соответствии с соглашением о вызовах в 64-битной Linux параметры функций заносятся в регистры в следующем порядке: RDI, RSI, RDX, RCX, R8, R9. Однако поскольку регистр ECX имеет специальное назначение при системном вызове (сохраняет RIP), его заменили на другой свободный регистр – R10.
Возврат результата системных вызовов Системные вызовы, как и [почти] все библиотечные функции возвращают результат в регистре EAX (RAX). Все остальные регистры сохраняются (разумеется, кроме RCX и R11 в x64 и x32). Реализация механизма системных вызовов В MASM и fasm имеется директива (макрос) invoke, cinvoke для вызова функций WinAPI, а как насчёт Linux? Для Linux чаще всего используют ассемблеры NASM и GAS.Для NASM есть проект NASMX, включающий в себя 3 include-файла, в которых описан 1 макрос syscall, номера функций для x86 и x64 (про доп.функции x32 забыли) и константы с кодами ошибок и т.п. Для GAS, как я понимаю, можно использовать стандартные Linux'овские include'ы, а про макросы я ничего не знаю (знаете – напишите мне). Мои макросы системных вызовов для NASM ![]() Предлагаю вам несколько написанных мной include-файлов для NASM с различными макросами системных вызовов для 32- и 64-битного кода, а также примеры их использования. Основные файлы:
Как этим пользоваться? Всё предельно просто ![]()
Если у вас пока нет желания более глубоко разбираться в моих макросах, либо вы хотите сперва опробовать описанное выше, можете пропустить нижеследующие списки ![]() Дополнительные макросы 32-битного режима (linux_syscall_32.mac):
Дополнительные макросы именованных вызовов (linux_syscall_fn.mac):
Макросы для внутреннего применения, которые тем не менее можно использовать и в программах (любой разрядности):
При подключении файла linux_syscall.inc становятся доступны следующие идентификаторы (которые позволяют создавать программы разной разрядности без изменения кода):
Пара слов про чувствительность к регистру букв.
Вот, собственно, и всё. Все исходники прикреплены к данной статье! (см. ниже файл Linux_syscall.NASM.zip) Примеры использования находятся в папке examples (все они выполняют одно и то же, но разными способами, при этом генерируется код x86, x64 и x32). Там же расположены cmd/sh-файлы для компиляции и готовые программы ![]() p.s. Есть планы по доработке и созданию новых макросов, по пока обещать ничего не буду. Где найти описание системных функций, их номера и параметры? ![]() Приведу несколько ссылок:
![]() О программировании в Linux:
7
|
||||||||||||||||||||||||||||||||||||||||||||||
| 18.07.2018, 12:37 | |
|
Ответы с готовыми решениями:
11
Системные вызовы и brk vs sbrk в частности Системные вызовы. Получение заголовка консольного окна Вызовы sento и recvfrom в получении udp пакетов |
|
4188 / 1836 / 220
Регистрация: 06.10.2010
Сообщений: 4,124
|
|
| 27.03.2019, 07:47 | |
|
Когда-то писал на FASM под x64 и пришлось делать свой include. Просто оставлю его здесь без комментариев - может быть кому-то пригодится.
2
|
|
|
3 / 3 / 0
Регистрация: 26.10.2017
Сообщений: 12
|
|||||||||||
| 20.06.2019, 18:05 | |||||||||||
|
Номера системных вызовов можно получить из соотв. *.h файлов, пропустив их через sed-скрипт, котороый конвертирует заголовочный файл с командами C-препроцессора #define в определение констант nasm EQU и преобразует строки вида
#define ENOENT 2 /* No such file or directory */ в строки вида ENOENT EQU 2 ; No such file or directory
0
|
|||||||||||
| 20.06.2019, 21:18 | |
|
0
|
|
|
3 / 3 / 0
Регистрация: 26.10.2017
Сообщений: 12
|
|
| 22.06.2019, 15:20 | |
|
Скрипту все равно, ошибки это или системные вызовы -- он переводит #условное в %условное, а #define в equ.
P.S. Наверное нужно было какой-нибудь сискол примером взять, но важнее было найти костыль для форматирования моноширинного текста (тега для sed ведь нету:-)), так что не обессудьте.
0
|
|
|
|
|
| 22.06.2019, 18:12 | |
|
Если вопрос ставится так, чтобы включить в код номер системного вызова, используя стандартные хидера, то незачем такой геморрой разводить, ведь в процесс компиляции можно естественным способом включить препроцессирование
Code $ cat t.S
#include <asm/unistd.h>
mov __NR_lseek, %eax
$ gcc t.S -E
...
mov 8, %eax
1
|
|
|
3 / 3 / 0
Регистрация: 26.10.2017
Сообщений: 12
|
|
| 02.07.2019, 11:27 | |
|
То, что вы написали, годится для (g}as, а nasm требует немного другой синтаксис, а именно %define. Однако, {#|%}define слишком небезопасен, поэтому в скрипте используется equ, который константы "отливает в граните", в отличие от "палочкой по песку на морском берегу".
0
|
|
|
Asm/C++/Delphi/Py/PHP/VBA
|
||
| 02.07.2019, 19:30 [ТС] | ||
%assign (%iassign). Да, equ переопределить нельзя (ибо он "отливается в граните"), но нужно ли это и является ли это преимуществом?К тому же, раз в сишных хедерах используется #define, значит его побочные эффекты учтены и можно смело юзать %define.
0
|
||
|
3 / 3 / 0
Регистрация: 26.10.2017
Сообщений: 12
|
|
| 04.07.2019, 11:39 | |
|
Исторически #define в си используется для определения констант времени компиляции, однако, эту константу можно изменить, используя переопределение. В простом коде это несложно контролировать, но если используется вложенная условная компиляция, можно запросто налететь на трудно обнаруживаемые проблемы. Поэтому комитет си дабл-кросс навязчиво рекомендует везде где можно, использовать вместо #define костыль в виде определения const-переменной.
Однако, здесь засада -- эта const-переменная не является константой времени компиляции, а переменной времени исполнения, обращение к которой контролируется на стадии компиляции. И она будет размещена в секции data, в то время как константа времени компиляции будет частью кода команды (непосредственный операнд). Собственно, удивляет, что в си и си дабл-кросс нет конструкции, аналогичной equ, которая есть в ассемблерах.
0
|
|
|
Asm/C++/Delphi/Py/PHP/VBA
|
||
| 04.07.2019, 14:24 [ТС] | ||
const int) ![]() А что касается возможности переопределения, то для ассемблера, где на программиста возложены полномочия контролировать и ломать, а также ответственность отвечать за всё, запрет на переопределение – это сомнительное преимущество, ИМХО. Добавлено через 19 минут К примеру, нужно в одном исходнике написать код и для x86, и для x64. Номера функций будут разные. Если есть возможность переопределения, можно в одном месте написать %include 'linux_syscall_32.inc', затем в другом месте %include 'linux_syscall_64.inc'.
1
|
||
|
Неэпический
|
||||||||
| 04.07.2019, 23:24 | ||||||||
1
|
||||||||
|
3410 / 1829 / 489
Регистрация: 28.02.2015
Сообщений: 3,696
|
||
| 05.07.2019, 19:47 | ||
|
Atakai, Ну, Вас предупреждали:
Не по теме: Трудно быть "самым умным" у себя на районе, только тут "батенька тырнет" разных районов, областей, республик и стран.
0
|
||
| 05.07.2019, 19:47 | |
|
Помогаю со студенческими работами здесь
12
Системные вызовы (функции) в с++ под Linux Системные вызовы Системные вызовы Qt и системные вызовы Системные вызовы Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
||||
|
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта
Симптом:
После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
|
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
|
Новый ноутбук
volvo 07.12.2025
Всем привет.
По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне:
Ryzen 5 7533HS
64 Gb DDR5
1Tb NVMe
16" Full HD Display
Win11 Pro
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|