FoxyZ
FoxyZ

Reputation: 186

Assembly program to reverse a string terminates after printing one character

I'm trying to write an assembly program that takes in a string of length 5 and prints the reversed string. I tried to print the characters one by one in reverse order by using a loop with ecx = 5. To print the characters I calculate the reversed address and then use a subroutine to print that character.

But there seems to be a mistake in my code, it only outputs the first character.

For example for a given input 12345 I'm getting 1 as output but I expected it to print 54331

segment .bss
    INPT: resb 5

segment .text
        global  asm_main
asm_main:
    mov eax, 3              ; system call no (sys_read = 3)
    mov ebx, 1              ; std_in = 1
    mov ecx, INPT           ; ptr to location to store input (INPT)
    mov edx, 5              ; no of bytes to read
    int 0x80                ; issue a system call

    mov ecx, 5
swap:
    mov edx, -8
    imul edx, ecx
    add edx, 40
    add edx, INPT           ; address of next byte to print = [INPT + 5 * 8 - ecx * 8]
    call print
    loop swap
    jmp exit
print:
    push ecx
    mov eax, 4
    mov ebx, 1
    mov ecx, edx
    mov edx, 1 
    int 0x80
    pop ecx
    ret
exit:
    mov eax, 1
    xor ebx, ebx
    int 0x80

Upvotes: 1

Views: 131

Answers (1)

Sep Roland
Sep Roland

Reputation: 39166

INPT: resb 5

This reserves 5 bytes. But the calculation has next comment

; address of next byte to print = [INPT + 5 * 8 - ecx * 8]

expecting qword elements!

Even if you corrected the above via changing -8 to -1, you would still not reverse the input! A lea ecx, [INPT + ecx - 1] can do the trick.

Additionally note that STDIN = 0 and that sys_read returns a count that you should use instead of that fixed number 5.
Also don't use the slow LOOP instruction and why not call print with the address ready in the ECX register.
Lastly, you could loop using a register that is not clobbered by the calls that follow. This saves on pushing and popping.

To reverse the print use this:

asm_main:
  mov eax, 3              ; system call no (sys_read = 3)
  xor ebx, ebx            ; std_in = 0
  mov ecx, INPT           ; ptr to location to store input (INPT)
  mov edx, 5              ; no of bytes to read
  int 0x80                ; -> EAX

  mov edi, eax
swap:
  lea  ecx, [INPT + edi - 1]  ; address of next byte to print in reverse order
  call print
  dec  edi
  jnz  swap
  jmp  exit
print:
  mov eax, 4
  mov ebx, 1
  mov edx, 1 
  int 0x80
  ret
exit:
  mov eax, 1
  xor ebx, ebx
  int 0x80

Upvotes: 1

Related Questions