Определенно есть, более того, только там она и существует в реальности.
Собственно вопрос можно сформулировать как, можно ли писать на "голом цэ", но без либцэ и как следствие вообще без каких-либо зависимостей?
Как оказалось в этом нет почти ничего сложного.
Проблема в том, что вменяемого множества букв на тему встроенного асма в гугле я не нашел, с примерами таже ситуация, мне было интересно, как вызвать syscall, ежели число аргументов больше 3-х, а именно:
нулевой аргумент = "a" = RAX = номер syscall
первый аргумент = "D" = RDI
второй аргумент = "S" = RSI
третий аргумент = "d" = RDX
а вот дальше следует "c", что как не сложно догадаться означает RCX, а еще дальше R8, R9, так ведь?
А вот и нет, разрабы гцц забили болт на R8 - R15 регистры, и что удивительно на RCX тоже, ниже приведен один из вероятных примеров кода, как можно забить болт на разрабов гцц, может кому на что и сгодиться:
Код: Выделить всё
// x86_64 Linux only
// компилить, как вариант, можно так:
// cc -Wall -s -nostdlib -march=native -pipe -O2 -Os -mfpmath=sse -std=c99 -o main main.c
#include <sys/types.h>
#include <sys/mman.h>
#define sys_write 1
#define sys_close 3
#define sys_mmap 9
#define sys_munmap 11
#define sys_exit 60
#define sys_create 85
#define MAP_ANONYMOUS 0x20
void exit(int code)
{
__asm__ __volatile__(
"syscall"
:
: "a"(sys_exit), "D"(code)
: "cc", "rcx", "r11", "memory");
__builtin_unreachable(); // syscall above never returns
}
ssize_t write(int fd, const void * buf, size_t size)
{
ssize_t result;
__asm__ __volatile__(
"syscall"
: "=a"(result)
: "a"(sys_write), "D"(fd), "S"(buf), "d"(size)
: "cc", "rcx", "r11", "memory");
return result;
}
void * mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset)
{
void * p = 0;
register int r8 __asm__ ("r8") = fd;
register off_t r9 __asm__ ("r9") = offset;
register int r10 __asm__ ("r10") = flags;
__asm__ __volatile__(
"syscall"
: "=a"(p)
: "a"(sys_mmap), "D"(addr), "S"(len), "d"(prot), "r"(r10), "r"(r8), "r"(r9)
: "cc", "rcx", "r11", "memory");
return p;
}
int munmap(void * addr, size_t len)
{
int result;
__asm__ __volatile__(
"syscall"
: "=a"(result)
: "a"(sys_munmap), "D"(addr), "S"(len)
: "cc", "rcx", "r11", "memory");
return result;
}
int creat(const char * pathname, mode_t mode)
{
int result;
__asm__ __volatile__(
"syscall"
: "=a"(result)
: "a"(sys_create), "D"(pathname), "S"(mode)
: "cc", "rcx", "r11", "memory");
return result;
}
int close(int fd)
{
int result;
__asm__ __volatile__(
"syscall"
: "=a"(result)
: "a"(sys_close), "D"(fd)
: "cc", "rcx", "r11", "memory");
return result;
}
void _start()
{
int fd = creat("/tmp/test.txt", 0600);
int * map = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(map == MAP_FAILED)
{
write(1, "mmap failed\n", 12);
exit(-1);
}
write(fd, "The truth is you don't need libc", 32);
munmap(map, 4096);
close(fd);
map = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(map == MAP_FAILED)
{
write(1, "mmap failed\n", 12);
exit(-1);
}
map[49] = 0xff000000;
munmap(map, 4096);
write(1, "Success\n", 8);
exit(0);
}
На "правильность" не претендую, написано в рамках "just for fun"