Here is what I need to do.

I have a very small C program that takes user input and passes argv to a function written in GNU assembly language that will then count the number of characters in the string.

The function seems to work fine when I enter a string as a variable directly in the program, but when I try to pass it from C, it gives me an incorrect count.

Here is my C code:

#include <stdio.h>
#include <stdlib.h>

extern int my_strlen(char*);

main(int argc, char *argv[])
{
        printf("\nThe number of characters is %i\n\n.", my_strlen(argv[1]));

        return 0;
}

Here is my assembly code. Please note that I need to keep this as a loop.

.globl my_strlen          
.type my_strlen, @function

my_strlen:             

pushl %ebp             
movl %esp, %ebp        

movl 8(%ebp), %ebx
movl $0, %eax          

loop:                  

incl %ebx              

cmpl $0, (%ebx)        

je end_loop            

incl %eax              

jmp loop               

end_loop:              

cmpl $0, %eax          

je empty               

jmp not_empty          

not_empty:             
decl %eax              

empty:                 

movl %ebp, %esp       
popl %ebp              

ret

If I run the application "./test test", it gives me a character count of 1188. It should be 4...

Thanks.

Hi,
I give you an advice:
If your string is of type char (1 byte), why are you comparing double words (cmpl), may be you need cmpb (byte).
Another one:
You increment ebx before comparing the first character.
I hope that this can be useful.

Hi,
Look at:
http://www.scalprum.eu/cdecl_and_stdcall_calling_conventions.html
or look at:
http://en.wikipedia.org/wiki/X86_calling_conventions
or at:
http://www.hackcraft.net/cpp/MSCallingConventions/
Who is wrong?.
Another comment is that string opcodes are slower than a well optimized algoritm. Which is not the reference code.
The problem of restoring ebx can be solved using another register, maybe edx.

Cheers.

Edited 5 Years Ago by untio: n/a

Comments
Yes, I was incorrect

Hi,
I doubt between two options, but I put the shortest one. Try the next code:

.global _my_strlen

_my_strlen:

pushl %ebp
movl %esp, %ebp

movl 8(%ebp), %edx
movl $0xFFFFFFFF, %eax

loop:

inc %eax
cmpb $0, (%edx , %eax)

jne loop

movl %ebp, %esp
popl %ebp
ret

The other solution is increment edx and not to use eax in the comparison. It can be timed, but I think this code is not so important.

Cheers.

Hi,
A correction to my code:
You can erase:
movl %ebp, %esp
We are not using stack local space. esp is not modified.

Cheers.

This article has been dead for over six months. Start a new discussion instead.