
@@:
mov al, byte ptr [esi + ebx]
mov byte ptr[edi], al
inc edi
dec ebx
js Done
jmp @B
Look at that, simple right?Let's do something worthwhile with it and explain a bit. As usual, sample app and source is attached.
The full procedure I put it in:
ReverseText proc uses esi edi ebx
LOCAL hRev:DWORD
invoke SendMessage, hOriginal, WM_GETTEXTLENGTH, 0, 0
test eax, eax
jz NoText
inc eax
mov ebx, eax
invoke HeapAlloc, hHeap, HEAP_ZERO_MEMORY, eax
mov esi, eax
invoke SendMessage, hOriginal, WM_GETTEXT, ebx, esi
invoke HeapAlloc, hHeap, HEAP_ZERO_MEMORY, ebx
mov edi, eax
dec ebx
dec ebx
@@:
mov al, byte ptr [esi + ebx]
mov byte ptr[edi], al
inc edi
dec ebx
js NoMore
jmp @B
NoText:
invoke MessageBox, hMain, offset szNoText, NULL, MB_IConstop
ret
NoMore:
invoke SendMessage, hReverse, WM_SETTEXT, 0, hRev
invoke HeapFree, hHeap, 0, esi
invoke HeapFree, hHeap, 0, hRev
ret
ReverseText endp
invoke SendMessage, hOriginal, WM_GETTEXTLENGTH, 0, 0
test eax, eax
jz NoText
We check to see if we have text to reverse, if not then we notify and leave.
inc eax
mov ebx, eax
WM_GETTEXTLENGTH returns the count of characters in the edit control not including the NULL terminator. Since the value is returned in eax, we increase the count in eax by 1. Then we save the count to ebx since that register is preserved across calls.
invoke HeapAlloc, hHeap, HEAP_ZERO_MEMORY, eax
mov esi, eax
Here we create a buffer for the original text plus a NULL and save the returned pointer in esi
invoke SendMessage, hOriginal, WM_GETTEXT, ebx, esi
We tell the edit control to put its text into the buffer pointed to by esi and the count is in ebx
invoke HeapAlloc, hHeap, HEAP_ZERO_MEMORY, ebx
mov hRev, eax
mov edi, eax
Now we create another buffer for the reversed string, we save the pointer to hRev so we can free it later and then move the pointer into edi.
dec ebx
dec ebx
Now we decrease our counter by 2. Yes 2, why you say? Let's say you entered "abcd"
WM_GETTEXTLENGTH would return 4 then we added 1 to that count, so ebx == 5. So we decrease our count by 1 to skip the NULL, then since we want to start from the last character we decrease ebx by 1 more. BUT WAIT!!!! The letter "d" is at the 4 position in the string!!! So you say... Well, yes it is, but arrays are zero based - they start at 0. That trips up a lot of newcomers because they are used to arrays starting at 1.
a b c d 0 1 2 3
@@: is called an anonymous label. They come in handy when you don't want to think of a name for the label
@@:
mov al, byte ptr [esi + ebx]
mov byte ptr[edi], al
inc edi
dec ebx
js NoMore
jmp @B
So, taking our example of "abcd" and ebx == 3 when we first enter the loop, we are telling the CPU to move the byte at position 3 (in the buffer pointed to by esi which is "d") into the byte register al, then we take that byte in al and move it into the 0 slot of our "reverse" buffer pointed to by edi.
Then we increase the pointer in edi by 1, and decrease our counter by 1. We check to see if the sign flag is set (we are below 0 if it is) if it is set, we are done else jump to the beginning of the loop.
Now ebx == 2 and the character we grab will be "c" and add that to the 1st position in the buffer pointed to by edi.
NoMore:
invoke SendMessage, hReverse, WM_SETTEXT, 0, hRev
invoke HeapFree, hHeap, 0, esi
invoke HeapFree, hHeap, 0, edi
Here we display the "reversed" string in the other edit control - line 2
Free the "original" buffer - line 3
Then we free our "reversed" buffer.
Any questions?
Attached File(s)
-
Reverse.zip (7.51K)
Number of downloads: 175







MultiQuote


|