Hello world!
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;
}
would provide the output of
Hello world!
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;
}
- The system call number is put in register
rax
- The rest of the arguments are put in registers
rdi
,rsi
andrdx
- %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")
);
Running of code under Linux x86-x64
$ gcc -o helloworld helloworld.c
$ ./helloworld
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();
}
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");
}
The print function is similar as the example described just now. For the exit()
function, it is executing system call of
exit(EXIT_SUCCESS);
with return code 0, while 60 is system call number for exit
To check the return code, we can type
$ echo $?
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
-
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 withputs
function to save time for formatting interpretation.exit()
function is one of the internal function for GCC, hence we have to putno-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)
welcome!