Недавно я занялся низкоуровневым программированием и узнал о системных прерываниях. Насколько я понял, оба прерывания отвечают за системные вызовы, однако я не понимаю разницы между ними и когда что использовать. Хотелось бы объяснения.
Это как спросить «в чем разница между DIR
и ls
». Это два разных механизма, с помощью которых две разные системы выполняют аналогичные задачи.
int 21h
(написано в синтаксисе MASM/TASM, так как это самый распространенный ассемблер для DOS) — прерывание системного вызова для DOS. Вы можете легко найти документацию по доступным услугам в Интернете. Краткий список наиболее важных служб DOS, к которым вы можете получить доступ из программ DOS, находится по адресу http://spike.scu.edu.au/~barry/interrupts.html.
С другой стороны, int 0x80
(написано в синтаксисе gas, поскольку это «родной» ассемблер для Linux) — это прерывание системного вызова для Linux на 32-разрядных процессорах Intel. Вы не получите хороших таблиц о том, как его использовать, как для DOS, потому что обычно вы не вызываете его напрямую. Если вы хотите вызвать его напрямую, посмотрите справочную страницу для системного вызова , чтобы узнать, какие регистры вам нужно установить, и где вы найдете результат. Вы можете найти номер для системных вызовов, например, на https://fedora.juszkiewicz.com.pl/syscalls.html.
Поведение вашей программы, когда она вызывает int 21h
или int 0x80
, не определяется Intel или архитектурой процессора 80386. Вместо этого инструкция int
просит процессор найти точку входа в таблице точек входа («таблица дескрипторов прерываний») и переходит к этой точке входа. Этот переход может включать переключение из пространства пользователя в пространство ядра (если процессор работает в режиме, поддерживающем разные уровни привилегий). DOS устанавливает точку входа с номером 21h, чтобы она указывала на функцию диспетчеризации, которая предлагает большинство служб DOS. С другой стороны, Linux/i386 устанавливает номер точки входа 0x80, чтобы указать на функцию диспетчеризации, которая предлагает все службы ядра Linux. Это означает, что программа, использующая int 0x80
, будет работать только в том случае, если она выполняется в среде Linux (или совместимой, как подсистема Windows для Linux, версия 1), тогда как программа, использующая int 21h
, будет работать только в том случае, если она выполняется под DOS ( или совместимую среду, такую как DOSBox или окно OS/2 DOS).
Поведение обработчиков для int 21h
и int 0x80
не определяется Intel. С другой стороны, поведение int 21h
и int 0x80
полностью определяется Intel (это то, что вы подробно объяснили).
Есть «хорошие таблицы» системных вызовов Linux, такие как chromium.googlesource.com/chromiumos/docs/+/master/constants/…. Но вам они не нужны, потому что знание соглашения о вызовах позволяет вам узнать, какой аргумент куда идет из прототипа C на странице руководства. то есть правила ABI документируются один раз, а не для каждого системного вызова в отдельности, включая диапазон значений, означающий -errno (от -4095
до -1
)
В основном разные ABI (соглашения о системных вызовах) для разных ОС. DOS и Linux (и BSD / MacOS) также имеют разные API, разные наборы доступных функций / системных вызовов, поэтому не обязательно существует эквивалент системного вызова Linux для некоторых вещей DOS или наоборот. (Особенно верно для экрана консоли BIOS int 0x10: в Linux у вас нет специальных системных вызовов только для экрана консоли и клавиатуры, вы всегда имеете дело со слоем TTY, если вы даже не открываете необработанную клавиатуру или USB HID или PS /2 драйвер события)