We will use NASM as our assembler.
First, let me add source code for the hello world program for the blog post and then I will explain the source code.
First, to let the linker know where my program starts, we need to add "_start:" as an identifier to the start of our program (line 8).
To add comments in an assembly program, we can use ";" at the start of the line.
All the code (instructions) for our program will remain in text section. For our program, the text section declaration syntax can be seen on line 6.
All the initialized data will be in our data section. The declaration of data section is on line 24.
The message that we want to print, "Hello World" is initialized under label "message". db is "define bytes"; It will store our string in consecutive memory location (thanks to nasm).
To print our string, we will use a system call that can print our string.
In IA-32, we will use interrupt 0x80 (line 16)to enter a system call.
For more information on interrupt and int 0x80, I will recommend reading this stackoverflow post and wiki page on interrupt vector table.
When the interrupt handler catches an interrupt, the program will execute as per the current state or values of the registers in the processor. In our case, when the system receives an interrupt on line 18, the value of eax register is 0x4. Which means, that OS will know that write syscall needs to be executed. The mapping of the values to specific syscall can be fonund in "/usr/include/i386-linux-gnu/asm/unistd_32.h" in Ubuntu 21 bit.
There are many system calls defined in "/usr/include/i386-linux-gnu/asm/unistd_32.h" (in Ubuntu 32 OS). Example system calls are printing to the screen, make directory, link files, fork exit. Here is a small preview of the file in which system calls are defined.
For our example, we will be using wring system call (line 8 in unistd_32.h).
As per Linux manual page for write system call, we need 3 arguments.
fd (file descriptor) is stdout in our case. For any program in Linux, by default, stdin (input) is mapped to fd 0, stdout to fd 1 and stderr fd 2. This will be in ebx register.
buf will be pointing to our hello world string. This will be in ecx register.
count will be the length of our string. This will be in edx register.
Almost every system will have a return value and will be stored in eax register. Write syscall's return value is the length of the string.
Similarly, when the next interrupt is received, the OS will find value 1 in the eax register and will know that this is an exit syscall. The return value is 0x5 as per the argument passed in ebx register.
To summarize, we created two interrupts in our program. One for printing a string to stdout and the second one for exiting with return value 0x5.