linuxassemblyx86debiannasm

How to display "The reversed string is:" and the reversed string on the same line in assembly language?


I'm new to assembly language programming and currently working on a simple program that prompts the user to enter a string, then reverses and displays it. However, I'm struggling to figure out how to display the message "The reversed string is:" and the reversed string on the same line.

Here's my current code:

section .bss
    buffer resb 100
    reversed_buffer resb 100

section .data
    msg db "Please enter a string: ", 0
    msgLen equ $ - msg
    reverse_msg db "The reversed string is: ", 0
    reverse_msg_len equ $ - reverse_msg

section .text
    global _start

_start:
    mov eax, 4
    mov ebx, 1
    mov ecx, msg
    mov edx, msgLen
    int 0x80

    mov eax, 3
    mov ebx, 0
    mov ecx, buffer
    mov edx, 100
    int 0x80
    mov esi, eax

    mov ecx, esi
    dec ecx
    mov esi, buffer
    mov edi, reversed_buffer

reverse_loop:
    cmp ecx, 0
    jl end_reverse
    mov al, [esi + ecx]
    mov [edi], al
    inc edi
    dec ecx
    jmp reverse_loop

end_reverse:
    mov eax, 4
    mov ebx, 1
    mov ecx, reverse_msg
    mov edx, reverse_msg_len
    int 0x80

    mov eax, 4
    mov ebx, 1
    mov ecx, reversed_buffer
    mov edx, esi
    int 0x80

    mov eax, 1
    xor ebx, ebx
    int 0x80

Screenshot of the current output of my assembly program

Could someone guide me on how to modify this code so that the message "The reversed string is:" and the reversed string are displayed on the same line?

Thanks in advance for any help or suggestions!


Solution

  • mov eax, 4
    mov ebx, 1
    mov ecx, reversed_buffer
    mov edx, esi
    int 0x80
    

    By the time your program executes this code, the ESI register contains the address of the buffer, so very much not the length of reversed string. Are you sure that this is the code that produced that screenshot?


    sys_read reports about the number of characters in EAX and reading from the terminal (stdin) the count in EAX includes the linefeed (10) that ends input. So for an input of HelloEnter you'd receive EAX=6, and the memory at buffer would contain the 6 bytes: 72, 101, 108, 108, 111, 10.
    For the purpose of reversing, you don't want that newline byte to move to the front of the string.

    Code that tries to reverse a string should be able to deal with an empty string. And so that the system prompt could re-appear on the left side of the screen, it would be nice to add another newline to the reversed string:

        mov   eax, 3
        mov   ebx, 0
        mov   ecx, buffer
        mov   edx, 100
        int   0x80             ; -> EAX
    
        xor   EDI, EDI
        dec   eax              ; Removing the newline code
        jz    .done            ; Empty string
        lea   esi, [eax - 1]   ; Offset to last character
    .reverse:
        movzx eax, byte [buffer + esi]
        mov   [reversed_buffer + EDI], al
        inc   EDI
        dec   esi
        jns   .reverse
    .done:
        mov   byte [reversed_buffer + EDI], 10
        inc   EDI
    
        mov   eax, 4
        mov   ebx, 1
        mov   ecx, reverse_msg
        mov   edx, reverse_msg_len
        int   0x80
    
        mov   eax, 4
        mov   ebx, 1
        mov   ecx, reversed_buffer
        mov   edx, EDI
        int   0x80
    

    Even nicer without using two buffers

    This requires less memory and runs in fewer iterations. For a string shorter than 2 characters no changes are necessary, but else the loop has to run until both the offsets EBX and ECX meet each other in the middle of the string:

        mov   eax, 3
        mov   ebx, 0
        mov   ecx, buffer
        mov   edx, 100
        int   0x80             ; -> EAX
        mov   EDI, eax         ; (*)
    
        xor   ebx, ebx
        cmp   eax, 3
        jb    .done            ; Empty string or just the one character
        lea   ecx, [eax - 2]   ; Offset to last character
    .reverse:
        movzx eax, byte [buffer + ebx]
        movzx edx, byte [buffer + ecx]
        mov   [buffer + ebx], dl
        mov   [buffer + ecx], al
        inc   ebx
        dec   ecx
        cmp   ebx, ecx
        jb    .reverse
    .done:
    
        mov   eax, 4
        mov   ebx, 1
        mov   ecx, reverse_msg
        mov   edx, reverse_msg_len
        int   0x80
    
        mov   eax, 4
        mov   ebx, 1
        mov   ecx, buffer
        mov   edx, EDI         ; (*)
        int   0x80