💾 Archived View for home.tobot.dev › cgi › env.c captured on 2022-03-01 at 15:12:56.

View Raw

More Information

-=-=-=-=-=-=-

typedef unsigned int size_t;

#define noreturn _Noreturn

#define SYS_exit 1
#define SYS_write 4
#define STDOUT 1

noreturn void exit(int error_code)
{
  asm("mov r0, %0\n\t"
      "mov r7, %1\n\t"
      "swi 0\n\t"
      :
      : "r" (error_code),
        "r" (SYS_exit)
      : "r0", "r7");
  while(1);
}

#define writel(fd, buf) write(fd, buf, strlen(buf))
inline int write(unsigned int fd, const char* buf, size_t count)
{
  asm("mov r0, %0\n\t"
      "mov r1, %1\n\t"
      "mov r2, %2\n\t"
      "mov r7, %3\n\t"
      "swi 0\n\t"
      :
      : "r" (fd),
        "r" (buf),
        "r" (count),
        "r" (SYS_write)
      : "r0", "r1", "r2", "r7");
}

inline size_t strlen(char const* const str)
{
  size_t len = 0;
  while(str[len++] != 0);
  return len;
}

int main(int argc, char* argv[], char* envp[]) {
  (void)argc; (void)argv; (void)envp;
  writel(STDOUT, "20 text/gemini\r\n# Hello, C!\r\nThis page was generated from C code (without any libraries like glibc!)");
  if(argc > 0)
  {
    writel(STDOUT, "\r\n## argv:");
    for(int i = 0; i < argc; i++)
    {
      writel(STDOUT, "\r\n");
      writel(STDOUT, argv[i]);
    }
  }

  if(envp[0] != 0)
  {
    writel(STDOUT, "\r\n## envp:");
    unsigned char i = 0;
    while(envp[i] != 0 && i < 254)
    {
      writel(STDOUT, "\r\n");
      writel(STDOUT, envp[i]);
      i++;
    }
  }
  return 0;
}

asm(
".global _start\n"
"_start:\n"
// Clear frame pointer and link register because there's no outer scope
"mov fp, #0\n"
"mov lr, #0\n"
// ----

// set up argc, argv, and envp
// in r0, r1, and r2 respectively
"ldr r0, [sp]\n"   // argc = *sp
"mov r1, #4\n"     // argv = 4
"add r1, sp\n"     // argv += sp
                   // => argv = sp+4

"mov r2, #8\n"     // envp = 8
"mul r2, r2, r0\n" // envp *= argc
"add r2, sp\n"     // envp += sp
"add r2, #8\n"     // envp += 8
                   // => envp = sp + 8 + (8 * argc)

"bl main\n"        // main(argc, argv, envp)
"bl exit\n"        // exit($?)
);