MASM 为什么递减寄存器不能找到数组中的下一个值?
MASM Why doesn't decrementing a register find the next value in an array?
我正在测试输入的字符串是否为回文,方法是将字符串移入字符数组并将字符数组的第一个和最后一个元素相互比较以进行测试。我可以得到数组的第一个元素来轻松找到第二个字符,但是要找到最后一个可接受的值并递减它,它找不到数组中的下一个字符。因此,如果 corrected/cleaned 字符数组如下所示:
['A']['B']['C']['D']['A']
ebx 将从 'A' -> 'B' 但 edi 不会从 'A' -> 'D'
改变
为什么ebx会改变字符而edi只从它的寄存器值中减去1?我该怎么做才能让 edi 更改字符值?谢谢!
C++代码:(以防万一)
#include <iostream>
#include <cstring>
#include <sstream>
using namespace std;
extern"C"
{
char stringClean(char *, int);
char isPalindrome(char *, int);
}
int main()
{
int pal = 0;
const int SIZE = 30;
string candidate = "";
char strArray[SIZE] = { '[=10=]' };
cout << "enter a string to be tested: ";
getline(cin, candidate);
int j = 0;
for (int i = 0; i < candidate.length(); i++) //getting rid of garbage before entering into array
{
if (candidate[i] <= 'Z' && candidate[i] >= 'A' || candidate[i] <= 'z' && candidate[i] >= 'a')
{
strArray[j] = candidate[i];
j++;
}
}
if (int pleaseWork = stringClean(strArray, SIZE) == 0)
pal = isPalindrome(strArray, SIZE);
if (pal == 1)
cout << "Your string is a palindrome!" << endl;
else
cout << "Your string is NOT a palindrome!" << endl;
system("pause");
return 0;
}
masm 代码:
.686
.model flat
.code
_isPalindrome PROC ; named _test because C automatically prepends an underscode, it is needed to interoperate
push ebp
mov ebp,esp ; stack pointer to ebp
mov ebx,[ebp+8] ; address of first array element
mov ecx,[ebp+12] ; number of elements in array
mov ebp,0
mov edx,0
mov eax,0
push edi ;save this
push ebx ;save this
mov edi, ebx ;make a copy of first element in array
add edi, 29 ;move SIZE-1 (30 - 1 = 29) elements down to, HOPEFULLY, the last element in array
mov bl, [ebx]
mov dl, [edi]
cmp dl, 0 ;checks if last element is null
je nextElement ;if null, find next
jne Comparison ;else, start comparing at Comparison:
nextElement:
dec edi ;finds next element
mov dl, [edi] ;move next element into lower edx
cmp dl, 0 ;checks if new element is mull
je nextElement ;if null, find next
jne Comparison ;else, start comparing at Comparison:
Comparison:
cmp bl,dl ;compares first element and last REAL element
je testNext ;jump to textNext: for further testing
mov eax,1 ;returns 1 (false) because the test failed
jne allDone ;jump to allDoneNo because it's not a palindrome
testNext:
dec edi ;finds last good element -1 --------THIS ISN'T DOING the right thing
inc ebx ;finds second element
cmp ebx, edi ;checks if elements are equal because that has tested all elements
je allDone
;mov bl,[ebx] ;move incremented ebx into bl
;mov dl,[edi] ;move decremented edi into dl
jmp Comparison ;compare newly acquired elements
allDone:
xor eax, eax
mov ebp, eax
pop edi
pop edx
pop ebp
ret
_isPalindrome ENDP
END
我没有测试过你的代码,但仔细观察我发现了一些可能的问题。
Why will ebx change characters
看起来是这样,但这不是你试图达到的。在初始阶段之后,您注释掉了从 memory/the 数组中读取字符的行(见下文)。所以实际上,您 确实更改了 EBX 中的角色,但不是您期望的(并且应该是想要的)方式。使用 INC EBX
,您将字符值从 'A'(65dec) 增加到 'B'(66dec)。 'B' 也是字符串的第二个字符只是巧合。尝试将字符串从 ABCDA 更改为 ARRCD 或其他内容,您仍然会在第二轮获得 'B'。所以EBX确实改变了。
...
;mov bl,[ebx] ;move incremented ebx into bl
;mov dl,[edi] ;move decremented edi into dl
jmp Comparison ;compare newly acquired elements
...
but edi only subtracts 1 from it's register value?
What can I do to have edi change character value?
是的。这就是您的代码所做的并且是正确的。取消注释上面包含 [edi]
的行,EDI 指向的字符将被加载到 EDX = DL.
的低字节
您的代码存在问题,您将 EBX 用作指针和 (char) 值。将下一个字符加载到 EBX 中会破坏指针,您的程序可能会在下一次迭代中因 ACCESS_VIOLATION 而崩溃,或者显示难以调试的随机行为。
将指针与值分开,就像您对 EDI/EDX 所做的那样(EDI=指向字符的指针,EDX(DL)=字符值。
另一个问题是:您的代码只适用于奇数长度的字符串。
testNext:
dec edi ; !!!
inc ebx ; !!!
cmp ebx, edi ; checks if elements are equal because that has tested all elements
je allDone
所以你正在增加和减少(应该是)指针,然后比较它们。现在考虑这种偶数长度字符串的情况:
ABBA
^ ^ (EBX(first) and EDI(second))
=> dec both =>
ABBA
^^ (EBX(first) and EDI(second))
=> dec both =>
ABBA
^^ (EDI(first) and EBX(second))
=> dec both =>
ABBA
^ ^ (EDI(first) and EBX(second))
=> dec both =>
ABBA
^ ^ (EDI(first) and EBX(second))
...
=> 问题!不会终止,永远不会满足条件 EBX=EDI*
可能的解决方案:在跳转
中添加一个 A(Above = Greater for unsigned values)
...
cmp ebx, edi
jae allDone
我正在测试输入的字符串是否为回文,方法是将字符串移入字符数组并将字符数组的第一个和最后一个元素相互比较以进行测试。我可以得到数组的第一个元素来轻松找到第二个字符,但是要找到最后一个可接受的值并递减它,它找不到数组中的下一个字符。因此,如果 corrected/cleaned 字符数组如下所示:
['A']['B']['C']['D']['A']
ebx 将从 'A' -> 'B' 但 edi 不会从 'A' -> 'D'
改变为什么ebx会改变字符而edi只从它的寄存器值中减去1?我该怎么做才能让 edi 更改字符值?谢谢!
C++代码:(以防万一)
#include <iostream>
#include <cstring>
#include <sstream>
using namespace std;
extern"C"
{
char stringClean(char *, int);
char isPalindrome(char *, int);
}
int main()
{
int pal = 0;
const int SIZE = 30;
string candidate = "";
char strArray[SIZE] = { '[=10=]' };
cout << "enter a string to be tested: ";
getline(cin, candidate);
int j = 0;
for (int i = 0; i < candidate.length(); i++) //getting rid of garbage before entering into array
{
if (candidate[i] <= 'Z' && candidate[i] >= 'A' || candidate[i] <= 'z' && candidate[i] >= 'a')
{
strArray[j] = candidate[i];
j++;
}
}
if (int pleaseWork = stringClean(strArray, SIZE) == 0)
pal = isPalindrome(strArray, SIZE);
if (pal == 1)
cout << "Your string is a palindrome!" << endl;
else
cout << "Your string is NOT a palindrome!" << endl;
system("pause");
return 0;
}
masm 代码:
.686
.model flat
.code
_isPalindrome PROC ; named _test because C automatically prepends an underscode, it is needed to interoperate
push ebp
mov ebp,esp ; stack pointer to ebp
mov ebx,[ebp+8] ; address of first array element
mov ecx,[ebp+12] ; number of elements in array
mov ebp,0
mov edx,0
mov eax,0
push edi ;save this
push ebx ;save this
mov edi, ebx ;make a copy of first element in array
add edi, 29 ;move SIZE-1 (30 - 1 = 29) elements down to, HOPEFULLY, the last element in array
mov bl, [ebx]
mov dl, [edi]
cmp dl, 0 ;checks if last element is null
je nextElement ;if null, find next
jne Comparison ;else, start comparing at Comparison:
nextElement:
dec edi ;finds next element
mov dl, [edi] ;move next element into lower edx
cmp dl, 0 ;checks if new element is mull
je nextElement ;if null, find next
jne Comparison ;else, start comparing at Comparison:
Comparison:
cmp bl,dl ;compares first element and last REAL element
je testNext ;jump to textNext: for further testing
mov eax,1 ;returns 1 (false) because the test failed
jne allDone ;jump to allDoneNo because it's not a palindrome
testNext:
dec edi ;finds last good element -1 --------THIS ISN'T DOING the right thing
inc ebx ;finds second element
cmp ebx, edi ;checks if elements are equal because that has tested all elements
je allDone
;mov bl,[ebx] ;move incremented ebx into bl
;mov dl,[edi] ;move decremented edi into dl
jmp Comparison ;compare newly acquired elements
allDone:
xor eax, eax
mov ebp, eax
pop edi
pop edx
pop ebp
ret
_isPalindrome ENDP
END
我没有测试过你的代码,但仔细观察我发现了一些可能的问题。
Why will ebx change characters
看起来是这样,但这不是你试图达到的。在初始阶段之后,您注释掉了从 memory/the 数组中读取字符的行(见下文)。所以实际上,您 确实更改了 EBX 中的角色,但不是您期望的(并且应该是想要的)方式。使用 INC EBX
,您将字符值从 'A'(65dec) 增加到 'B'(66dec)。 'B' 也是字符串的第二个字符只是巧合。尝试将字符串从 ABCDA 更改为 ARRCD 或其他内容,您仍然会在第二轮获得 'B'。所以EBX确实改变了。
...
;mov bl,[ebx] ;move incremented ebx into bl
;mov dl,[edi] ;move decremented edi into dl
jmp Comparison ;compare newly acquired elements
...
but edi only subtracts 1 from it's register value? What can I do to have edi change character value?
是的。这就是您的代码所做的并且是正确的。取消注释上面包含 [edi]
的行,EDI 指向的字符将被加载到 EDX = DL.
您的代码存在问题,您将 EBX 用作指针和 (char) 值。将下一个字符加载到 EBX 中会破坏指针,您的程序可能会在下一次迭代中因 ACCESS_VIOLATION 而崩溃,或者显示难以调试的随机行为。
将指针与值分开,就像您对 EDI/EDX 所做的那样(EDI=指向字符的指针,EDX(DL)=字符值。
另一个问题是:您的代码只适用于奇数长度的字符串。
testNext:
dec edi ; !!!
inc ebx ; !!!
cmp ebx, edi ; checks if elements are equal because that has tested all elements
je allDone
所以你正在增加和减少(应该是)指针,然后比较它们。现在考虑这种偶数长度字符串的情况:
ABBA
^ ^ (EBX(first) and EDI(second))
=> dec both =>
ABBA
^^ (EBX(first) and EDI(second))
=> dec both =>
ABBA
^^ (EDI(first) and EBX(second))
=> dec both =>
ABBA
^ ^ (EDI(first) and EBX(second))
=> dec both =>
ABBA
^ ^ (EDI(first) and EBX(second))
...
=> 问题!不会终止,永远不会满足条件 EBX=EDI* 可能的解决方案:在跳转
中添加一个 A(Above = Greater for unsigned values)...
cmp ebx, edi
jae allDone