Question:
I want to write "Hello World" without glibc, for this I need to write my little libc, I made some simple functions that do not require system calls, but now I want to make a write function so that the puts function works, but write needs a syscall function, and for In order to make a syscall, you need to know Asembrer, but I don’t know him at all, I still ventured to try to write hello world, after a long googling and after several dozen compilations, I saw “Hello World!” On the screen, in the first half a second I did not believe that I got gg
__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;" // Системный вызов ядра
);
}
As far as I understand, for a system call, you need to write to a variable (or are they registers, I don’t know how the first one differs from the second one) r7 is the call number, and the arguments passed to the variables r1, r2, r3 … but how to write the syscall(номер вызова,Аргументы...)
I don’t know, here you need to either write it completely in Assembler, which I definitely won’t be able to, or write in C and pass arguments to Assembler, I don’t know how either.
Can anyone help write a syscall function for arm?
Answer:
Here, I threw in a quick "Hello World", where system calls are made using a number of syscall<N>
functions, for a different number of arguments N
. You can, of course, get confused and make another single function with a variable number of arguments using va_list
.
#include <stdint.h>
#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);
}
Compiling and running:
$ gcc -nostdlib test.c -o test
$ ./test
Hello World