NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: nobody 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
-
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