Страницы

Поиск по вопросам

воскресенье, 15 марта 2020 г.

Как сделать функцию syscall?

#c #linux #ассемблер #arm


Я хочу написать "Hello World" без glibc, для этого мне нужно написать свою маленькую
libc, я сделал несколько простых функций которые не требуют системных вызовов, но теперь
хочу сделать функцию write чтоб функция puts заработала, но для write нужна функция
syscall, а для того чтоб сделать syscall нужно знать Асембрер, а я его совсем не знаю,
я всеже рискнул попробовать написать hello world, после долгого гугления и через несколько
десятков компиляций, я на экране увидел  "Hello World!", в первые пол секунды я не
поверил что у меня вышло Гг

__asm__(
    ".data;"
    "msg:"
        ".ascii \"Hello, world!\n\";" // Строка для вывода
        "len = . - msg;" // Записуем в переменную len длину msg
);

void _start() {


    __asm__(
        "mov  r0, #1;" // Запись в поток #1 - stdout
        "ldr  r1, =msg;" // Указатель на строку
        "ldr  r2, =len;" // Длина строки
        "mov  r7, #4;" // Номер системного вызова - 4 (write)
        "swi  0;" // Системный вызов ядра
    );

    __asm__(
        "mov  r0, #0;"  // Возращаемое значение - 0
        "mov  r7, #1;" // Номер системного вызова - 1 (exit)
        "swi  0;" // Системный вызов ядра
    );
}


Насколько я понял для системного вызова нужно записать в переменную(или это ригистры,
я не знаю чем отличается первое от второго) r7 номер вызова, а в переменные r1, r2,
r3... передаваемые аргументы, но как написать функцию syscall(номер вызова,Аргументы...)
я не знаю, тут нужно либо полностью писать её на Ассемблере, а это я точно не смогу,
либо писать на C и передавать аргументы в Ассемблер, это я тоже не умею.

Может кто либо помочь написать функцию syscall для arm?
    


Ответы

Ответ 1



Вот, накидал по-быстрому "Hello World", где системные вызовы осуществляются с помощью ряда функций syscall, для различного количества аргументов N. Можно, конечно, заморочиться, и сделать еще единую функцию с переменным числом аргументов с помощью va_list. #include #define SYS_EXIT 1 #define SYS_WRITE 4 #define STDIN 0 #define STDOUT 1 #define STDERR 2 size_t strlen(const char *s) { size_t n; for (n = 0; *s; ++n, ++s) ; return n; } void syscall1(int cnum, int arg1) { __asm__ __volatile__( "mov r0, %0;" "mov r7, %1;" "swi 0;" : : "r"(arg1), "r"(cnum) : "r0", "r7" ); } void syscall3(int cnum, int arg1, int arg2, int arg3) { __asm__ __volatile__( "mov r0, %0;" "mov r1, %1;" "mov r2, %2;" "mov r7, %3;" "swi 0;" : : "r"(arg1), "r"(arg2), "r"(arg3), "r"(cnum) : "r0", "r1", "r2", "r7" ); } void _start() { char *msg = "Hello world\n"; syscall3(SYS_WRITE, STDOUT, (int)msg, strlen(msg)); syscall1(SYS_EXIT, 0); } Компиляция и запуск: $ gcc -nostdlib test.c -o test $ ./test Hello World

Ответ 2



пример отсюда для intel-архитектуры: # hello.c static inline long syscall1(long syscall, long arg1) { long ret; asm volatile ("int $0x80" : "=a" (ret) : "a" (syscall), "b" (arg1) : "memory"); return ret; } static inline long syscall3(long syscall, long arg1, long arg2, long arg3) { long ret; asm volatile ("int $0x80" : "=a" (ret) : "a" (syscall), "b" (arg1), "c" (arg2), "d" (arg3) : "memory"); return ret; } int write(int fd, const void *buf, int count) { return syscall3(4, fd, (long)buf, count); } void exit(int status) { syscall1(1, status); } void _start() { int retval; retval = write(1, "hello world\n", 12); exit(0); } компилируем: $ gcc -m32 -nostdlib -nostdinc -static hello.c -o hello запускаем: $ ./hello hello world -- у архитектуры же arm другой ассемблер. проверить не могу, т.к. arm-а под рукой нет, поэтому привожу пример отсюда как есть: void _start() __attribute__ ((naked)); void _start() { main(); asm volatile( "mov r7, #1\n" /* exit */ "svc #0\n" ); } int main() { linuxc('X'); return 42; } void linuxc(int c) { asm volatile( "mov r0, #1\n" /* stdout */ "mov r1, %[buf]\n" /* write buffer */ "mov r2, #1\n" /* size */ "mov r7, #4\n" /* write syscall */ "svc #0\n" : /* output */ : [buf] "r" (&c) : "r0", "r1", "r2", "r7", "memory" ); } компилировать, как я понимаю, надо с теми же параметрами (ну, разве что без указания битности — -m32 — которая и в первом примере была необязательна).

Комментариев нет:

Отправить комментарий