DEV Community

Pin Loon Lee
Pin Loon Lee

Posted on

Hello world!

Hello world!

cover

Hello world! I believe this is what a normal beginner for programming would see as they first try to code in certain programming language.

As this is also my very first post in Dev, I would like to say Hello world! too!

As a C/C++ programmer, a simple program as below:

#include <iostream>

int main(int argc, char **argv) { 
  std::cout << "Hello world!" << std::endl; 
  return 0;
}
Enter fullscreen mode Exit fullscreen mode

would provide the output of

Hello world!
Enter fullscreen mode Exit fullscreen mode

Nevertheless, it would be boring if we only able to produce the output by using the sample above especially in the world of C/C++ where we should know everything in detail underlying the code.

To do that, we will compile the code in a bare metal version using inline assembly language.

Inline assembly language

One of the way is to have helloworld.c as below

int main(void) {
  register int    syscall_no  asm("rax") = 1;
  register int    arg1        asm("rdi") = 1;
  register char*  arg2        asm("rsi") = "Hello world!\n";
  register int    arg3        asm("rdx") = 13;
  asm("syscall");
  return 0;
}
Enter fullscreen mode Exit fullscreen mode
  • The system call number is put in register rax
  • The rest of the arguments are put in registers rdi, rsi and rdx
  • %rdi, %rsi, %rdx, %rcx, %r8, and %r9 are used to pass the first six integer or pointer parameters to called functions

In other words, the code above is executing the system call of

write(STDOUT_FILENO,
   "Hello world!\n",
   sizeof("Hello world!\n")
);
Enter fullscreen mode Exit fullscreen mode

Running of code under Linux x86-x64

$ gcc -o helloworld helloworld.c
$ ./helloworld
Enter fullscreen mode Exit fullscreen mode

Program without main

To make more fun, we are going to write code that does not have main, let's call it nomain program

The entry point for the program would be

void nomain() {
  print();
  exit();
}
Enter fullscreen mode Exit fullscreen mode

where the print and exit functions would be

void print() {
  register char* arg2 asm("rsi") = "Hello world!\n";
  asm("mov $1,%%rax \n\t"
      "mov $1,%%rdi \n\t"
      "mov $13,%%rdx \n\t"
      "syscall \n\t" ::
          : "rdi", "rdx");
}

void exit() {
  asm("mov $0,%rdi \n\t"
      "mov $60,%rax \n\t"
      "syscall \n\t");
}
Enter fullscreen mode Exit fullscreen mode

The print function is similar as the example described just now. For the exit() function, it is executing system call of

exit(EXIT_SUCCESS);
Enter fullscreen mode Exit fullscreen mode

with return code 0, while 60 is system call number for exit

To check the return code, we can type

$ echo $?
Enter fullscreen mode Exit fullscreen mode

after executing the executable.

Running of nomain code under Linux x86-x64

$ gcc -c -fno-builtin helloworld.c
$ ld -static -e nomain -o helloworld helloworld.o
$ ./helloworld
Enter fullscreen mode Exit fullscreen mode
  • GCC has provided a lot of built-in functions, normally it would replace C function with internal function of compiler for optimization purposes. For example, if only strings are involved in the printf function, it would be replaced with puts function to save time for formatting interpretation. exit() function is one of the internal function for GCC, hence we have to put no-builtin flag to disable the built-in functions
  • The entry point is then configured through -e nomain

Thanks for reading my very first post, hope you enjoy the reading!

Top comments (1)

Collapse
 
vulcanwm profile image
Medea

welcome!