Just for fun, here's a couple of simple storm functions:
.text:1503AA50 ; Returns the substring after the first occurance of the specific character in the string. Returns NULL if the character is not found.
.text:1503AA50
.text:1503AA50 ; char *__fastcall SStrChr(char *str,char c)
.text:1503AA50 public SStrChr
.text:1503AA50 SStrChr proc near ; CODE XREF: SBmpSaveImageEx+6Dp
.text:1503AA50 ; SBmpSaveImageEx+7Ap ...
.text:1503AA50 mov eax, ecx ; Move the string into eax
.text:1503AA52 test eax, eax ; Ensure that it's a valid character
.text:1503AA54 jnz short SStrChrValidString
.text:1503AA56 push ERROR_INVALID_PARAMETER ; dwErrCode
.text:1503AA58 call SErrSetLastError
.text:1503AA5D xor eax, eax
.text:1503AA5F retn
.text:1503AA60 ; ---------------------------------------------------------------------------
.text:1503AA60
.text:1503AA60 SStrChrValidString: ; CODE XREF: SStrChr+4j
.text:1503AA60 mov cl, [eax] ; Move the current character into ecx
.text:1503AA62 test cl, cl ; Check if it's null
.text:1503AA64 jz short SStrChrReturn0 ; If it's null, return 0
.text:1503AA66
.text:1503AA66 SStrChrTop: ; CODE XREF: SStrChr+20j
.text:1503AA66 cmp cl, dl ; Compare the current character to the character we're looking for
.text:1503AA68 jz short SStrChrReturn ; If they're equal, return the rest of the string
.text:1503AA6A mov cl, [eax+1] ; ecx gets the next character into the string
.text:1503AA6D inc eax ; eax goes to the next character
.text:1503AA6E test cl, cl ; Check if the character is null
.text:1503AA70 jnz short SStrChrTop
.text:1503AA72
.text:1503AA72 SStrChrReturn0: ; CODE XREF: SStrChr+14j
.text:1503AA72 xor eax, eax
.text:1503AA74
.text:1503AA74 SStrChrReturn: ; CODE XREF: SStrChr+18j
.text:1503AA74 retn
.text:1503AA74 SStrChr endp
.text:1503AA80 ; Exported entry 570.
.text:1503AA80 ; Exported entry 572.
.text:1503AA80
.text:1503AA80
.text:1503AA80 ; Returns the address of the final occurance of c within the string str. If it is not found, NULL is returned.
.text:1503AA80
.text:1503AA80 ; char *__fastcall SStrChrR(const char *str,char c)
.text:1503AA80 public SStrChrR
.text:1503AA80 SStrChrR proc near ; CODE XREF: sub_15001420+82p
.text:1503AA80 ; sub_150024C0+D3p ...
.text:1503AA80 test ecx, ecx ; Make sure we have a non-null string
.text:1503AA82 jnz short SStrChrValidParameter
.text:1503AA84 push ERROR_INVALID_PARAMETER ; dwErrCode
.text:1503AA86 call SErrSetLastError
.text:1503AA8B xor eax, eax ; return 0
.text:1503AA8D retn
.text:1503AA8E ; ---------------------------------------------------------------------------
.text:1503AA8E
.text:1503AA8E SStrChrValidParameter: ; CODE XREF: SStrChrR+2j
.text:1503AA8E push ebx
.text:1503AA8F mov bl, [ecx] ; Move the first character in ecx to bl
.text:1503AA91 push esi
.text:1503AA92 xor esi, esi ; Clear esi
.text:1503AA94 test bl, bl ; Check if the character is null
.text:1503AA96 jz short SStrChrReturnEsi
.text:1503AA98
.text:1503AA98 SStrChrTopLoop: ; CODE XREF: SStrChrR+24j
.text:1503AA98 cmp bl, dl ; Compare the character to the character we're searching for
.text:1503AA9A jnz short SStrChrNotEqual
.text:1503AA9C mov esi, ecx ; If they're equal, move the character here
.text:1503AA9E
.text:1503AA9E SStrChrNotEqual: ; CODE XREF: SStrChrR+1Aj
.text:1503AA9E mov bl, [ecx+1] ; Set the current character to the next character
.text:1503AAA1 inc ecx ; Go to the next character
.text:1503AAA2 test bl, bl ; Loop as long as we aren't at null
.text:1503AAA4 jnz short SStrChrTopLoop ; Compare the character to the character we're searching for
.text:1503AAA6
.text:1503AAA6 SStrChrReturnEsi: ; CODE XREF: SStrChrR+16j
.text:1503AAA6 mov eax, esi
.text:1503AAA8 pop esi
.text:1503AAA9 pop ebx
.text:1503AAAA retn
.text:1503AAAA SStrChrR endp
One question I have is, why do they each have 2 ords? Is there some reason for that?
I don't have a lot of experience doing this, but here's my go at converting it to C
char* __fastcall SStrChrR( const char* str, char c ) {
if ( str == NULL ) {
SSetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
char* found = NULL;
while ( *str != NULL ) {
if ( c == *str )
found = str;
}
return found;
}
char* __fastcall SStrChr( char* str, char c ) {
if ( str == NULL ) {
SSetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
while ( *str != c || *str != NULL ) ++str;
return str;
}
I believe your while loop in the SStrChr should be &&, not ||
Quote from: Eibro[yL] on May 14, 2004, 11:28 PM
I don't have a lot of experience doing this, but here's my go at converting it to C
char* __fastcall SStrChrR( const char* str, char c ) {
if ( str == NULL ) {
SSetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
char* found = NULL;
while ( *str != NULL ) {
if ( c == *str )
found = str;
}
return found;
}
char* __fastcall SStrChr( char* str, char c ) {
if ( str == NULL ) {
SSetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
while ( *str != c || *str != NULL ) ++str;
return str;
}
You missed the char* incrementation in your first function.
Here's what I got:
char * __fastcall SStrChr( char * str, char ch ) {
if (!str) {
//SErrSetLastError(ERROR_INVALID_PARAMETER);
return (NULL);
}
for (int i = 0; *str; i++, *str++)
if (*str == ch)
return (str);
return (NULL);
}
const char * __fastcall SStrChrR( const char * str, char ch ) {
if (!str) {
//SErrSetLastError(ERROR_INVALID_PARAMETER);
return (NULL);
}
int i;
const char * pRet = NULL;
for (i = 0; *str; i++, *str++)
if (*str == ch)
pRet = str;
return (pRet);
}
Edit: iago, are you SURE the second function isn't returning a const char*? It doesn't really make sense otherwise.
I don't see why a strchr function should return a const char* instead of a char*. Makes much more sense to return a char*.
The found variable going out of scope is not a problem.
I forgot that found was pointing to the parameter itself -- my bad. Anyways, SStrChrR should definitely be returning a const char * if the parameter is const char *. Otherwise, you'd need to const_cast<>() it at return, and that's dangerous.
Quote from: Moonshine on May 15, 2004, 04:32 PM
I forgot that found was pointing to the parameter itself -- my bad. Anyways, SStrChrR should definitely be returning a const char * if the parameter is const char *. Otherwise, you'd need to const_cast<>() it at return, and that's dangerous.
Ah. I got confused because you said the second function, and in the C++ post, it's the argument of the first function that is const char *. Either way; I think he put a const on it that shouldn't be there. It's very useful to have strchr and strrchr return a char *.
Quote from: Moonshine on May 15, 2004, 04:13 PM
You missed the char* incrementation in your first function.
Here's what I got:
char * __fastcall SStrChr( char * str, char ch ) {
if (!str) {
//SErrSetLastError(ERROR_INVALID_PARAMETER);
return (NULL);
}
for (int i = 0; *str; i++, *str++)
if (*str == ch)
return (str);
return (NULL);
}
const char * __fastcall SStrChrR( const char * str, char ch ) {
if (!str) {
//SErrSetLastError(ERROR_INVALID_PARAMETER);
return (NULL);
}
int i;
const char * pRet = NULL;
for (i = 0; *str; i++, *str++)
if (*str == ch)
pRet = str;
return (pRet);
}
Edit: iago, are you SURE the second function isn't returning a const char*? It doesn't really make sense otherwise.
More like
char * __fastcall SStrChr( char * str, char ch ) {
if (!str) {
//SErrSetLastError(ERROR_INVALID_PARAMETER);
return (NULL);
}
while(*str) {
if (*str == ch)
return (str);
str++;
}
return (NULL);
}