Difference between revisions of "Example 3"
Line 2: | Line 2: | ||
[[Category: Assembly Examples]] | [[Category: Assembly Examples]] | ||
<pre> | This example is the implementation of strchr() found in Storm.dll, called SStrChr() (Storm_571). | ||
Here is the prototype for this function: | |||
char *__stdcall SStrChr(const char *str, int c); | |||
And the summary of Linux's manpage for what strchr() does: | |||
<pre> | |||
The strchr() function locates the first occurrence of c (converted to a | |||
char) in the string pointed to by s. The terminating null character is | |||
considered part of the string; therefore if c is `\0', the functions | |||
locate the terminating `\0'. | |||
</pre> | |||
Below is the code, copied/pasted directly from IDA. The only thing different from IDA is that the addresses have been removed and the jump locations named. It would be a good exercise to use this opportunity to learn IDA a bit. Open "storm.dll" (any Blizzard game should have it) in IDA, go to the function list, and search for Storm_571. | |||
<pre> | |||
push ebp | |||
mov ebp, esp | mov ebp, esp | ||
mov eax, [ebp+arg_0] | mov eax, [ebp+arg_0] | ||
Line 39: | Line 54: | ||
</pre> | </pre> | ||
== Annotated Code == | |||
Please, try this yourself first! | |||
Here, comments have been added explaining each line a little bit. These comments are added in an attempt to understand what the code's doing. | |||
<pre> | |||
push ebp ; Preserve ebp. | |||
mov ebp, esp ; Set up the frame pointer. | |||
mov eax, [ebp+arg_0] ; Move the first argument (that IDA has helpfully named) into eax. Recall that the first . | |||
; argument is a pointer to the string. | |||
test eax, eax ; Check if the string is 0. | |||
jnz short loc_1 ; Jump over the next section if eax is non-zero (presumably, a valid string). | |||
push 57h ; dwErrCode = ERR_INVALID_PARAMETER. | |||
call ds:SetLastError ; This library function allows a program to set/retrieve the last error message. | |||
xor eax, eax ; Clear eax (for a return 0). | |||
pop ebp ; Restore ebp. | |||
retn 8 ; Return, removing both parameters from the stack. | |||
loc_1: | |||
mov cl, [eax] ; Recall that cl is a 1-byte value at the bottom of ecx. cl gets the character at [eax] | |||
test cl, cl ; Check if the character is '\0' (which indicates the end of the string). | |||
jz short loc_3 ; If it's zero, then the character hasn't been found. Note that this differs from the | |||
; actual strchr() command, since it won't detect the terminator '\0' if c is '\0'. | |||
mov dl, [ebp+arg_4] ; Move the second parameter (names arg_4 by IDA, since it's 4-bytes into the parameter list | |||
; list) into dl, which is the right-most byte of edx. . | |||
jmp short loc_2 ; Jump down to the next line (the compiler likely did something weird here, optimized | |||
; something out, perhaps). | |||
; --------------------------------------------------------------------------- | |||
loc_2: | |||
cmp cl, dl ; Compare cl (the current character) to dl (the character being searched for). | |||
jz short loc_4 ; If they're equal, jump down, returning eax (the remaining sub-string). | |||
mov cl, [eax+1] ; Move the next character into cl. | |||
inc eax ; Point ecx at the next character. | |||
test cl, cl ; Check if the string terminator has been found. | |||
jnz short loc_2 ; Go to the top of this loop as long as the end of the string hasn't been reached. | |||
loc_3: | |||
xor eax, eax ; Returns 0, indicating that the character was not found | |||
loc_4: | |||
pop ebp ; Restore ebp's previous value | |||
retn 8 ; Return, removing 8 bytes (2 32-bit values) from the stack (the two parameters) | |||
</pre> | |||
== C Code == | |||
== Cleaned up C Code == | |||
== Reduced C Code == | |||
== Finished Code == | |||
== Questions == | |||
== Questions == | == Questions == | ||
Feel free to edit this section and post questions, I'll do my best to answer them. But you may need to contact me to let me know that a question exists. | Feel free to edit this section and post questions, I'll do my best to answer them. But you may need to contact me to let me know that a question exists. |
Revision as of 21:27, 13 March 2007
Assembly Language Tutorial | |
---|---|
Please choose a tutorial page:
|
This example is the implementation of strchr() found in Storm.dll, called SStrChr() (Storm_571).
Here is the prototype for this function:
char *__stdcall SStrChr(const char *str, int c);
And the summary of Linux's manpage for what strchr() does:
The strchr() function locates the first occurrence of c (converted to a char) in the string pointed to by s. The terminating null character is considered part of the string; therefore if c is `\0', the functions locate the terminating `\0'.
Below is the code, copied/pasted directly from IDA. The only thing different from IDA is that the addresses have been removed and the jump locations named. It would be a good exercise to use this opportunity to learn IDA a bit. Open "storm.dll" (any Blizzard game should have it) in IDA, go to the function list, and search for Storm_571.
push ebp mov ebp, esp mov eax, [ebp+arg_0] test eax, eax jnz short loc_1 push 57h ; dwErrCode call ds:SetLastError xor eax, eax pop ebp retn 8 ; --------------------------------------------------------------------------- loc_1: mov cl, [eax] test cl, cl jz short loc_3 mov dl, [ebp+arg_4] jmp short loc_2 ; --------------------------------------------------------------------------- loc_2: cmp cl, dl jz short loc_4 mov cl, [eax+1] inc eax test cl, cl jnz short loc_2 loc_3: xor eax, eax loc_4: pop ebp retn 8
Annotated Code
Please, try this yourself first!
Here, comments have been added explaining each line a little bit. These comments are added in an attempt to understand what the code's doing.
push ebp ; Preserve ebp. mov ebp, esp ; Set up the frame pointer. mov eax, [ebp+arg_0] ; Move the first argument (that IDA has helpfully named) into eax. Recall that the first . ; argument is a pointer to the string. test eax, eax ; Check if the string is 0. jnz short loc_1 ; Jump over the next section if eax is non-zero (presumably, a valid string). push 57h ; dwErrCode = ERR_INVALID_PARAMETER. call ds:SetLastError ; This library function allows a program to set/retrieve the last error message. xor eax, eax ; Clear eax (for a return 0). pop ebp ; Restore ebp. retn 8 ; Return, removing both parameters from the stack. loc_1: mov cl, [eax] ; Recall that cl is a 1-byte value at the bottom of ecx. cl gets the character at [eax] test cl, cl ; Check if the character is '\0' (which indicates the end of the string). jz short loc_3 ; If it's zero, then the character hasn't been found. Note that this differs from the ; actual strchr() command, since it won't detect the terminator '\0' if c is '\0'. mov dl, [ebp+arg_4] ; Move the second parameter (names arg_4 by IDA, since it's 4-bytes into the parameter list ; list) into dl, which is the right-most byte of edx. . jmp short loc_2 ; Jump down to the next line (the compiler likely did something weird here, optimized ; something out, perhaps). ; --------------------------------------------------------------------------- loc_2: cmp cl, dl ; Compare cl (the current character) to dl (the character being searched for). jz short loc_4 ; If they're equal, jump down, returning eax (the remaining sub-string). mov cl, [eax+1] ; Move the next character into cl. inc eax ; Point ecx at the next character. test cl, cl ; Check if the string terminator has been found. jnz short loc_2 ; Go to the top of this loop as long as the end of the string hasn't been reached. loc_3: xor eax, eax ; Returns 0, indicating that the character was not found loc_4: pop ebp ; Restore ebp's previous value retn 8 ; Return, removing 8 bytes (2 32-bit values) from the stack (the two parameters)
C Code
Cleaned up C Code
Reduced C Code
Finished Code
Questions
Questions
Feel free to edit this section and post questions, I'll do my best to answer them. But you may need to contact me to let me know that a question exists.