Reverse string

SYS_WRITE - 'write' syscall number

STD_OUT - stdout file descriptor

SYS_EXIT - 'exit' syscall number

EXIT_CODE - exit code

NEW_LINE - new line (

) symbol

INPUT - our input string, which we will reverse

mov rdi, $ + 15

$ - returns position in memory of string where $ defined

$$ - returns position in memory of current section start

String operations

REP - repeat while rcx is not zero

MOVSB - copy a string of bytes (MOVSW, MOVSD and etc..)

CMPSB - byte string comparison

SCASB - byte string scanning

STOSB - write byte to string

Conclusion

Some time ago i started to write series of blog posts about assembly programming for x86_64. You can find it by asm tag. Unfortunately i was busy last time and there were not new post, so today I continue to write posts about assembly, and will try to do it every week.Today we will look at strings and some strings operations. We still use nasm assembler, and linux x86_64.Of course when we talk about assembly programming language we can't talk aboutdata type, actually we're dealing with array of bytes. Let's try to write simple example, we will define string data and try to reverse and write result to stdout. This tasks seems pretty simple and popular when we start to learn new programming language. Let's look on implementation.First of all, I define initialized data. It will be placed insection (You can read about sections in part):Here we can see four constants:syscall list you can find - here . Also there defined:Next we definesection for our buffer, where we will put reversed string:Ok we have some data and buffer where to put result, now we can definesection for code. Let's start from mainroutine:Here are some new things. Let's see how it works: First of all we putaddress toregister at line 2, as we did for writing to stdout and write zeros toregister, it will be counter for calculating length of our string. At line 4 we can seeoperator. It resetsflag to zero. We need in it because when we will calculate length of string, we will go through symbols of this string, and ifflag will be 0, we will handle symbols of string from left to right. Next we callfunction. I missed line 5 withinstruction, i will tell about it little later. And now let's look atimplementation:As you can understand by it's name, it just calculates length ofstring and store result inregister. First of all we check thatregister doesn't point to zero, if so this is the end of string and we can exit from function. Next isinstruction. It's simple, it just put 1 byte toregister (low part of 16 bit ax) and changespointer. As we executedinstruction,everytime will moveto one byte from left to right, so we will move by string symbols. After it we pushvalue to stack, now it contains symbol from our string (lodsb puts byte from si to al, al is low 8 bit of rax). Why we did push symbol to stack? You must remember how stack works, it works by principle LIFO (last input, first output). It is very good for us. We will take first symbol from, push it to stack, than second and so on. So there will be last symbol of string at the stack top. Than we just pop symbol by symbol from stack and write to OUTPUT buffer. After it we increment our counter () and loop again to the start of routine.Ok, we pushed all symbols from string to stack, now we can jump toreturn tothere. How to do it? We haveinstruction for this. But if code will be like this:It will not work. Why? It is tricky. Remember we calledat. What occurs when we call a function? First of all function's parameters pushes to stack from right to left. After it return address pushes to stack. So function will know where to return after end of execution. But look at, we pushed symbols from our string to stack and now there is no return address of stack top and function doesn't know where to return. How to be with it. Now we must take a look to the weird instruction before call:First all:So we have position of, but why we add 15 here? Look, we need to know position of next line after. Let's open our file with objdump util:We can see here that line 12 (our) takes 10 bytes and function call at line 16 - 5 bytes, so it takes 15 bytes. That's why our return address will be. Now we can push return address fromto stack and return from function:Now we return to start. Aftercall we write zeros toandand jump tolabel. It's implementation is following:Here we check our counter which is length of string and if it is zero we wrote all symbols to buffer and can print it. After checking counter we pop from stack toregister first symbol and write it tobuffer. We addbecause in other way we'll write symbol to first byte of buffer. After this we increasefor moving next bybuffer, decrease length counter and jump to the start of label.After execution ofwe have reversed string inbuffer and can write result to stdout with new line:and exit from program:That's all, now we can compile our program with:and run:Of course there are many other instructions for string/bytes manipulations:It was a fourth part of series 'say hello to x64 assembly', if you will have a questions/suggestions write me a comment or ping me at twitter for discussing. In next part we will talk about nasm macroses. If you're interesting in some additional themes about assembly and x86_64 programming write me a comment and I will try to write blog post about it in near time.All source code you can find as everytime - here p.s. English is not my first language, so you'll find mistakes in blog post please write me in comments or drop me email