Номера и порядок передачи аргументов системных вызовов ARM Linux соответствуют таковым на платформе Intel, и это очень хорошо и правильно. Существует два режима системных вызовов – старый и новый (новый является частью стандарта EABI). Нынешние ядра ARM Linux поддерживают оба режима, но использовать режим EABI, разумеется, предпочтительнее. У двух режимов много общего: аргументы вызова передаются в регистрах r0-r6, а сам вызов выполняется с помощью инструкции SWI.
В старом режиме номер вызова является частью операнда инструкции SWI. Операнд инструкции выглядит так:
MOV r0, дескриптор_файла; MOV r1, адрес_буфера; MOV r2, длина_буфера; SWI 0x900004;
В режиме EABI номер вызова передается в регистре r7, а операндом SWI всегда является значение 0×0. Еще одно отличие связано с передачей 64-битных аргументов. В обоих режимах их передают в паре 32-битных регистров, но в старом режиме это просто два следующих не занятых регистра, а в режиме EABI – следующая пара регистров, в которой первый регистр имеет четный номер. Тот же вызов _write() в режиме EABI будет выглядеть так:
MOV r0, дескриптор_файла; MOV r1, адрес_буфера; MOV r2, длина_буфера; MOV r7, #4; SWI 0x0;
Помимо прочего, между двумя режимами существует одно, не сразу заметное, различие: режим EABI может использовать как в режиме ARM MODE (32-битные инструкции), так и в более компактном THUMB MODE. Старый режим не может использоваться в THUMB MODE просто потому, что число 0×900000 не поместится в 16-битном операнде инструкции SWI режима THUMB.
Ну и напоследок, описания нескольких системных вызовов ARM Linux. Зная общий принцип, остальные описания легко «конвертировать» из описаний аналогичных вызовов для Intel.
Номер | Обозначение | Используемые регистры |
1 | sys_exit() | r0 |
3 | sys_read() | r0, r1, r2 |
4 | sys_write() | r0, r1, r2 |
5 | sys_open() | r0, r1, r2 |
6 | sys_close() | r0 |