Inputs and Outputs in Assembly Programming
Printing a string to the stdout
In this section, we are going to see how we can print something on the screen using assembly instructions. We learned in the previous tutorial that we can use system calls to do things like these.
First of all, we know that we need to store the string we are going to print somewhere in the memory. This can be bss segment or the data section. Let's revise those two sections quickly. If we are going to allocate some memory space for uninitialized data that should be in the bss segment. f we are allocating memory for initialized data it should be stored in the data section.
str1 db "Hello World!", 10, 0 size equ $ - str1
In the second line of the above code, I have used some ASCII values. The value 10 represents the newline character. So when we use it it'll go to a new line. This is pretty much equal to the usage of \n in C programming.
The value 0 is known as the NULL character. It'll act as the ending point of a string.
Now the next step is to execute the system call. To do that we need to load arguments into the required registers. If you are unclear about what's going on please read the previous tutorial assembly programming for beginners.
mov rax,4 mov rbx,1 mov rcx, str1 mov rdx, size int 0x80
The RAX register should be filled with the specific system call number. The sys call number for printing something is 4. So mov rax, 4 will do that. The registers RBX, RCX, and RDX should be filled with the required arguments for the system call. When considering the stdout system call, the RBX register should contain the stream. In this case, we are going to use stdout (Console). Therefore the value 1 represents the stdout. (Just keep in mind that the value 0 represents the std in or the keyboard input). At the moment we have specified that we want to print out something and we are going to use the stream stdout (console).
Next, we want to specify what we are going to print. The Register RCX should contain the starting address of the character array. That is pointed out by str. ( Note that str is just a label and it is not a keyword). Then the register RDX contains the size of the string. This can be done with the instruction mov rdx, size. Finally, we are executing the system call by the instruction int 0x80. The rest of the job of printing will be handled by the kernel.
After printing the string we need to exit the program. Let's use the exit system call for that.
mov rax,1 mov rbx, 0 int 0x80
The exit system call number is 1. So I filled it to the register EAX, The status code is filled to the register EBX as 0 and executed the exit system call with the instruction int 0x80.
The complete assembly program for the above task can be seen in the following snippet. See how we have separated different parts of the instruction set into sections such as s.data and .txt.
section .data textlabel db "Hello World!", 10, 0 size equ $ - textlabel
section .text global _start _start: mov rax,4 mov rbx,1 mov rcx, str mov rdx, size int 0x80
mov rax, 1 mov rbx, 0 int 0x80
We can assemble, link, and run it using NASM and ld as follows. In this example, I've used an Ubuntu virtual maching on my MacBook.
Getting a string from stdin
Now we're going to get input from the keyboard. For that, there is another system call. First of all, we need some memory space to read the input and store it. At this time we have to use the bss segment because until the reading it is uninitialized.
buff resb 40
I have named the storage area as buff and allocated 40 bytes for that. The term resb stands for reserve bytes. Before getting the input we have to print a message to the user saying to input a string. For that, we are going to use the previously discussed method. I'm not going to aging explain it here.
textlabel1 db "Enter your Name:", 0
But here we have to note one thing. You may notice that the string doesn't have a new line character. This is because we are getting input from the user on the same line.
After that the most important instructions set for the input system call going on.
mov rax,3 mov rbx,0 mov rcx, buff mov rdx, 40 int 0x80
The system call number for the input is 3. There fore the value 3 is copied to the RAX register. RBX should contain the stream. The value for stdin or the keyboard is 0. Therefore zero is filled to RBX. The register RCX should point to a location to take the input buffer. In this case, it is the allocated memory space in the bss segment.
The RDX register contains the size to be read and it is 40 bytes. Finally, we execute the system call. Followinfg i the complete code for the read a string and display it.
section .data str1 db "Enter your Name:", 0 size1 equ $ - str1 str2 db "Hello ", 0 size2 equ $ - str2 section .bss buff resb 40 section .text global _start _start: mov rax,4 mov rbx,1 mov rcx, str1 mov rdx, size1 int 0x80 mov rax,3 mov rbx,0 mov rcx, namelabel mov rdx, 40 int 0x80 mov rax,4 mov rbx,1 mov rcx, str2 mov rdx, size2 int 0x80 mov rax,4 mov rbx,1 mov rcx, buff mov rdx, 40 int 0x80 mov rax, 1 mov rbx, 0 int 0x80
Well explained and interesting cyber security articles and tutorials on the topics such as System exploitation, Web application hacking, exploit development, malwara analysis, Cryptography etc. Let's explorer the awesome world of computer