我想弄清楚为什么这个 ID 回文的 x86 汇编代码认为一切都是回文

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

。在这一点上我已经做了几天了,尽管浏览了这个网站上对这个确切问题的所有其他回复,我还是无法弄清楚我做错了什么。谁能给我一些帮助?出于某种原因,当我分别使用 [esi] 和 [edi] 将每个字符串的值移动到 al 和 dl 中时。当最终比较这些值时,无论值是否相等,它们总是设置零标志

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

看起来您对用于初始输入的反转字符串使用了相同的缓冲区。 string1 持有与 string2 相同的指针。所以他们当然比较相等;至少这是一个好兆头,表明您的其余代码可能正在运行。

When these vals are eventually compared they always set the zero flag, irrespective of whether or not the values are equal

如果 al 和 dl` 中的值不同,

cmp al,dl 肯定不会设置 ZF。如果您认为这种情况正在发生,那么您使用的调试器是错误的。它应该让您在单步执行代码时检查寄存器/内存。理想情况下,甚至突出显示最后一条指令更改了哪些寄存器。


如果你使用一个单独的缓冲区,如果没有任何其他错误,你的笨拙低效算法看起来会起作用。

效率低下,因为它循环一次将字符串扩展到堆栈上每个字符 4 个字节,然后再次循环以存储在缓冲区中,然后再次循环 以检查是否相等。

标准算法是从指向 head/tail 的指针开始,循环直到它们在中间相遇,O(n) 时间,O(1) 额外 space,最佳情况 O (1) 运行时,如果 first/last 字节不同。 (在进行一次比较之前,先反转要花费 O(n) 时间和额外的 space)。在 x86 上,您甚至可以使用 bswappshufb 一次检查 4 或 16 个字节,以对整数或 XMM 寄存器进行字节反转,从而进一步减少常数因子。 (但将短字符串作为特例。)


顺便说一句,您的比较循环也可以优化:

请注意,如果 al != 0,您可以捕获 dl == 0 字符串结尾的情况作为 al != dl 的一部分。 strcmp 实现只需要相互检查字符串和 一个 字符串的终止零。