Task: Displaying the Reversed String
Navigate to tasks/print-rev-string/support/.
In the file print_rev_string.asm, add the reverse_string() function so that you have a listing similar to the one below:
[...]
section .text
extern printf
extern puts
global print_reverse_string
reverse_string:
push rbp
mov rbp, rsp
mov rax, rdi ; get the address of the string
mov rcx, rsi ; get the length of the string
; the address of the buffer to store the reversed string is already in rdx
test rcx, rcx ; check if length is zero
jz done ; if zero, skip to null termination
add rax, rcx ; point to one past the last character
dec rax ; point to the last character
copy_loop:
mov bl, [rax] ; get a byte from the source
mov [rdx], bl ; store it in the destination
dec rax ; move to previous character in source
inc rdx ; move to next character in destination
dec rcx ; decrease counter
jnz copy_loop ; if counter not zero, continue loop
done:
mov byte [rdx], 0 ; null-terminate the destination string
leave
ret
print_reverse_string:
push rbp
mov rbp, rsp
[...]
IMPORTANT: When copying the
reverse_string()function into your program, remember that the function starts at thereverse_string()label and ends at theprint_reverse_stringlabel. Thecopy_loopanddonelabels are part of thereverse_string()function.
The reverse_string() function reverses a string and has the following signature: void reverse_string(const char *src, size_t len, char *dst);. This means that the first len characters of the src string are reversed into the dst string.
Reverse the mystring string into a new string and display that new string.
NOTE: To define a new string, we recommend using the following construction in the data section:
store_string times 64 db 0This creates a string of 64 zero bytes, enough to store the reverse of the string. The equivalent C function call is
reverse_string(mystring, rcx, store_string);. We assume that the length of the string is calculated and stored in thercxregister.You cannot directly use the value of
rcxin its current form. After theprintf()function call for displaying the length, the value ofrcxis not preserved. To retain it, you have two options:
- Store the value of the
rcxregister on the stack beforehand (usingpush rcxbefore theprintfcall) and decrease the value ofrspby8in order to align the stack and then increase the value ofrspby8and restore it after theprintfcall (usingpop rcx).- Store the value of the
rcxregister in a global variable, which you define in the.datasection.You cannot use another register because there is a high chance that even that register will be modified by the
printfcall to display the length of the string.
After you consider your implementation complete, it is recommended to first run it manually in order to assess its correctness. In order to do so, enter the support/ directory and run:
make
If your code successfully compiled, you can then run the binary like so:
./print_reverse_string
To fully test the implementation, enter the tests/ directory and run:
make check
In case of a correct solution, you will get an output such as:
./run_all_tests.sh
test_reverse_simple ........................ passed ... 33
test_reverse_special ........................ passed ... 33
test_reverse_long ........................ passed ... 34
Total: 100/100
If you’re having trouble solving this exercise, go through this reading material.