. I've been at this for a few days at this point and despite looking through all other responses to this exact problem on this site i am unable to figure out what im doing wrong. Can anyone provide me with some help? For some reason, when I move the values of each string using [esi] and [edi] into al and dl respectively. When these vals are eventually compared they always set the zero flag, irrespective of whether or not the values are equal
BufSize = 80
.data
msg BYTE "Input a string for reversal: ",0
msg1 BYTE "palindrome",0
msg2 BYTE "not palindrome",0
buffer BYTE BufSize DUP(?),0,0
bytesRead DWORD ?
string1 DWORD ?
string2 DWORD ?
TEMP1 DW 0
PALMESSAGE DB " THE PROVIDED STRING IS A PALINDROME $"
NOTPALMESSAGE DB " THE PROVIDED STRING IS NOT A PALINDROME $"
.CODE
main proc
; Wait for user input
mov edx, OFFSET buffer
mov ecx, SIZEOF buffer
call ReadString
mov bytesRead, eax
mov string1, edx
mov ecx, bytesread
mov esi,0
COMPARE:
MOVZX EAX, buffer[esi]
push eax
inc esi
LOOP COMPARE
mov ecx,bytesRead
mov esi,0
L2:
pop eax ; get character
mov buffer[esi],al ; store in string
inc esi
Loop L2
mov string2, offset buffer
mov ecx, bytesread
mov edx, string2
call writestring
mov ecx,bytesRead
mov esi,0
mov edi,0
;mov eax,0
;mov edx,0
mov esi, string1
mov edi, string2
L3:
mov al, [esi]
mov dl, [edi]
cmp al,0 ; end of string1?
jne L4 ; no
cmp dl,0 ; yes: end of string2?
jne L4 ; no
jmp pal ; yes, exit with ZF = 1
L4:
inc esi ; point to next
inc edi
cmp al,dl ; characters equal?
je L3 ; yes: continue loop
jmp notpal ; no: exit with flags set
PAL:
mov edx, OFFSET msg1
call WriteString
call crlf
JMP FIN
NOTPAL:
mov edx, OFFSET msg2
call WriteString
call crlf
FIN:
exit
main ENDP
END main
Looks like you use the same buffer for the reversed string that you used for the initial input. string1 holds the same pointer as string2. So of course they compare equal; at least that's a good sign that the rest of your code might be working.
When these vals are eventually compared they always set the zero flag, irrespective of whether or not the values are equal
cmp al,dl
will definitely not set ZF if the values in al
and dl` differ. If you think that's happening, you're using your debugger wrong. It should let you examine registers / memory while you single-step your code. Ideally even highlighting which registers were changed by the last instruction.
Your clunky inefficient algorithm looks like it would work if you used a separate buffer, if there aren't any other bugs.
Inefficient because it loops once to expand the string to 4 bytes per character on the stack, then loops over it again to store in a buffer, then loops over it again to check for equality.
The standard algorithm is to start with pointers to the head/tail and loop until they meet in the middle, O(n) time, O(1) extra space, and best case O(1) runtime if the first/last bytes differ. (Reversing first costs O(n) time and extra space before doing even one compare). On x86 you can even check 4 or 16 bytes at a time with bswap
or pshufb
to byte-reverse an integer or XMM register, reducing the constant factor even more. (But making short strings a special case.)
BTW, your compare loop could also be optimized:
Note that if al != 0
, you can catch the dl == 0
end-of-string case as part of al != dl
. A strcmp
implementation only needs to check the strings against each other and one of the strings for the terminating zero.