我想弄清楚为什么这个 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 上,您甚至可以使用 bswap
或 pshufb
一次检查 4 或 16 个字节,以对整数或 XMM 寄存器进行字节反转,从而进一步减少常数因子。 (但将短字符串作为特例。)
顺便说一句,您的比较循环也可以优化:
请注意,如果 al != 0
,您可以捕获 dl == 0
字符串结尾的情况作为 al != dl
的一部分。 strcmp
实现只需要相互检查字符串和 一个 字符串的终止零。
。在这一点上我已经做了几天了,尽管浏览了这个网站上对这个确切问题的所有其他回复,我还是无法弄清楚我做错了什么。谁能给我一些帮助?出于某种原因,当我分别使用 [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 上,您甚至可以使用 bswap
或 pshufb
一次检查 4 或 16 个字节,以对整数或 XMM 寄存器进行字节反转,从而进一步减少常数因子。 (但将短字符串作为特例。)
顺便说一句,您的比较循环也可以优化:
请注意,如果 al != 0
,您可以捕获 dl == 0
字符串结尾的情况作为 al != dl
的一部分。 strcmp
实现只需要相互检查字符串和 一个 字符串的终止零。