Dec 27, 2024

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 .bss

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

ABOUT HACKSLAND

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

CATEGORIES
SOCIAL
RANDOM ARTICLES