首页 > 解决方案 > 我试图弄清楚为什么这个 ID 回文的 x86 汇编代码认为一切都是回文

问题描述

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

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

标签: assemblyx86palindromeirvine32

解决方案


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

当最终比较这些 val 时,无论值是否相等,它们总是设置零标志

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


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

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

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


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

请注意,如果al != 0,您可以将dl == 0字符串结尾的情况作为al != dl. 一个strcmp实现只需要检查字符串之间的相互关系以及终止零的字符串之一


推荐阅读