assemblyx86palindromeirvine32

im trying to figure out why this x86 assembly code to ID palindromes thinks everything is a palindrome


. 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

Solution

  • 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.