I am a beginner in Assembly and i have a simple question. This is my code :
BITS 64 ; 64−bit mode
global strchr ; Export 'strchr'
SECTION .text ; Code section
strchr:
mov rcx, -1
.loop:
inc rcx
cmp byte [rdi rcx], 0
je exit_null
cmp byte [rdi rcx], sil
jne .loop
mov rax, [rdi rcx]
ret
exit_null:
mov rax, 0
ret
This compile but doesn't work. I want to reproduce the function strchr as you can see. When I test my function with a printf it crashed ( the problem isn't the test ). I know I can INC rdi directly to move into the rdi argument and return it at the position I want. But I just want to know if there is a way to return rdi at the position rcx to fix my code and probably improve it.
CodePudding user response:
Your function strchr
seems to expect two parameters:
- pointer to a string in
RDI
, and - pointer to a character in
RSI
.
Register rcx
is used as index inside the string? In this case you should use al
instead of cl
. Be aware that you don't limit the search size. When the character refered by RSI
is not found in the string, it will probably trigger an exception. Perhaps you should test al
loaded from [rdi rcx]
and quit further searching when al=0
.
If you want it to return pointer to the first occurence of character
inside the string, just
replace mov rax,[rdi rcx]
with lea rax,[rdi rcx]
.
CodePudding user response:
Your code does the following:
char* strchr ( char *p, char x ) {
int i = -1;
while ( p[i] != '\0' ) {
i ;
if ( p[i] == x )
return p[i];
}
return null;
}
As @vitsoft says, your intention is to return a pointer, but in the first return statement are returning a single character.
It is unusual to increment in the middle of the loop. It is also odd to start the index at -1. On the first iteration, the loop continue condition looks at p[-1]
, which is not a good idea, since that's not part of the string you're being asked to search. If that byte happens to be the nul character, it'll stop the search right there.
If you waited to increment until both tests are performed, then you would not be referencing p[-1], and you could also start the index at 0, which would be more usual.
You might consider suggest capturing the character into a register instead of using a complex addressing mode three times.
Further, you could advance the pointer in rdi
and forgo the index variable altogether.
Here's that in C:
char* strchr ( char *p, char x ) {
for(;;) {
char c = *p;
if ( c == '\0' )
break;
if ( c == x )
return p;
p ;
}
return null;
}
CodePudding user response:
Thanks to your help, I finally did it ! Thanks to the answer of Erik, i fixed a stupid mistake. I was comparing str[-1] to NULL so it was making an error. And with the answer of vitsoft i switched mov to lea and it worked ! There is my code :
strchr:
mov rcx, -1
.loop:
inc rcx
cmp byte [rdi rcx], 0
je exit_null
cmp byte [rdi rcx], sil
jne .loop
lea rax, [rdi rcx]
ret
exit_null:
mov rax, 0
ret