Author Topic: Need help with sample code  (Read 5844 times)

nobody

  • Guest
Need help with sample code
« on: October 13, 2005, 07:04:38 PM »
Hello,

I'm having trouble with asm code under Linux, wondering if you can help out. The program is supposed to output the reverse of the string (ie) ABCD = DCBA. However, I'm getting strange results.

If I input "architecture" I instead get "aerutcetihcr"

Here's the code:

segment .data
        msg     db      'Enter your line input: '
        len       equ     $ - msg
        msg2    db      'The reversed string is: '
        len2      db      $ - msg2

segment .bss
        buffer1 resb    128

segment .text
        global _start

_start:
        mov     eax,    4               ;syscall to print
        mov     ebx,    1               ;fd (stdout)
        mov     ecx,    msg           ;output string msg
        mov     edx,    len             ;length of string
        int       0x80                    ;call kern

mov     eax,    3               ;syscall to read
        mov     ebx,    0               ;fd (stdin)
        mov     ecx,    buffer1        ;store input string
        int       0x80                      ;call kern
        mov     ebx,    ecx             ;ebx point to buffer1
        mov     esi,    ecx             ;so does esi
        mov     ecx,    edx            ;

again:
        cmp     esi,    0h              ;check if esi = null
        je      found
        inc     esi
        loop    again

found:  dec     esi                     ;esi points to last char

swap:
        cmp     ebx, esi
        je         reverse
        mov     ax,     [ebx]
        mov     dx,     [esi]
        mov     [esi],  ax
        mov     [ebx],  dx
        inc      ebx
        dec     esi
        loop    swap

reverse:
        mov     eax,    4
        mov     ebx,    1
        mov     ecx,    msg2
        mov     edx,    len2
        int       0x80

mov     ecx,    esi
        mov     edx,    0
        int       0x80

exit:
        mov     eax,    1               ;syscall to exit
        mov     ebx,    0
        int     0x80


Thank you for your help,
Shoshy

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Need help with sample code
« Reply #1 on: October 13, 2005, 08:51:06 PM »
Shoshy wrote:
> Here's the code:
>
> segment .data
>         msg     db      'Enter your line input: '
>         len       equ     $ - msg
>         msg2    db      'The reversed string is: '
>         len2      db      $ - msg2
>
> segment .bss
>         buffer1 resb    128
>
> segment .text
>         global _start
>
> _start:
>         mov     eax,    4               ;syscall to print
>         mov     ebx,    1               ;fd (stdout)
>         mov     ecx,    msg           ;output string msg
>         mov     edx,    len             ;length of string
>         int       0x80                    ;call kern
>
>         mov     eax,    3               ;syscall to read
>         mov     ebx,    0               ;fd (stdin)
>         mov     ecx,    buffer1        ;store input string

edx? You want edx to indicate the maximum number of bytes to accept - 128 (might be good to "%define" "BUFSIZ" to 128, and use "BUFSIZ" in both the "resb" line for the buffer, and here, to avoid possible buffer overruns). Your edx still holds the length of the first prompt.

>         int       0x80                      ;call kern

Now eax should be the number of bytes actually read. This will help you find the end of the input string.

>         mov     ebx,    ecx             ;ebx point to buffer1
>         mov     esi,    ecx             ;so does esi
>         mov     ecx,    edx            ;
>
> again:
>         cmp     esi,    0h              ;check if esi = null
>         je      found
>         inc     esi
>         loop    again

What??? esi isn't going to be 0 until you've looped around past 4G! I guess what you intend is "cmp [esi], byte 0". This would work if we had a zero-terminated string, but we don't! The string would be terminated with a newline, but we don't need to do a bytescan to find it, since the sys_read call returns the number of characters read.

> found:  dec     esi                     ;esi points to last char
>
> swap:
>         cmp     ebx, esi
>         je         reverse
>         mov     ax,     [ebx]
>         mov     dx,     [esi]
>         mov     [esi],  ax
>         mov     [ebx],  dx
>         inc      ebx
>         dec     esi
>         loop    swap

Here you're swapping two characters at once. You want 8-bit registers - al and dl (or al and ah, to trash just one register). Or you could use "xchg" (one register and memory, not mem2mem, of course!). Better the way you've got it, probably, but with 8-bit registers.

> reverse:
>         mov     eax,    4
>         mov     ebx,    1
>         mov     ecx,    msg2
>         mov     edx,    len2
>         int       0x80
>
>         mov     ecx,    esi

If your "find the end" and "swap" loops above had worked, esi would be pointed to the middle of your string... And eax would be the number of bytes written, not still sys_write (4)...

>         mov     edx,    0

And with edx = 0, no bytes are going to be written...

>         int       0x80

... so I don't understand how you're getting even the garbled output you show. (beginner's luck? :)

> exit:
>         mov     eax,    1               ;syscall to exit
>         mov     ebx,    0
>         int     0x80
>
>
> Thank you for your help,

You're welcome, Shoshy. Ignore the whinging from pissants who don't have the balls to sign their name! :)

Best,
Frank