assembly - 我试图弄清楚为什么这个 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
解决方案
看起来您对用于初始输入的反转字符串使用相同的缓冲区。string1 拥有与 string2 相同的指针。所以他们当然比较平等;至少这是一个好兆头,表明您的其余代码可能正在运行。
当最终比较这些 val 时,无论值是否相等,它们总是设置零标志
cmp al,dl
al
如果和 dl`中的值不同,肯定不会设置 ZF 。如果您认为这种情况正在发生,那么您使用的调试器是错误的。它应该让您在单步执行代码时检查寄存器/内存。理想情况下,甚至突出显示最后一条指令更改了哪些寄存器。
如果您使用单独的缓冲区,如果没有任何其他错误,您笨拙的低效算法看起来会起作用。
效率低下,因为它循环一次以将字符串扩展为堆栈上每个字符 4 个字节,然后再次循环遍历它以存储在缓冲区中,然后再次循环遍历它以检查是否相等。
标准算法是从指向头/尾的指针开始并循环直到它们在中间相遇,O(n) 时间,O(1) 额外空间,如果第一个/最后一个字节不同,则最佳情况 O(1) 运行时间. (在进行一次比较之前,首先反转会花费 O(n) 时间和额外空间)。在 x86 上,您甚至可以使用整数或 XMM 寄存器一次检查 4 或 16 个字节,bswap
或pshufb
对整数或 XMM 寄存器进行字节反转,从而进一步降低常数因子。(但使短字符串成为特例。)
顺便说一句,您的比较循环也可以优化:
请注意,如果al != 0
,您可以将dl == 0
字符串结尾的情况作为al != dl
. 一个strcmp
实现只需要检查字符串之间的相互关系以及终止零的字符串之一。
推荐阅读
- java - 无法配置数据源:将数据库连接到 Spring 应用程序时出现 Intellij 错误
- html - Perfect app 中 webroot 的位置(用于 css 文件)
- python - 如何使用 python 抓取业务电子邮件联系人?
- html - 如何覆盖 Internet Explorer 字体真棒图标的拉右宽度?
- cryptography - 使用加密构建的 yaws 无法启动
- ftp - TidFTP 下载不同大小
- c++ - 在 C++ 中覆盖或更改 ExitProcess 函数
- javascript - JavaScript 中 Uint8Array 到 Short int 的转换导致负数
- c# - 如何 ILEmit 来自另一个 DLL 的函数?
- sql - Sql查询与“列表”表连接的表的ID