I'm testing to see if an entered string is a palindrome by taking the string, moving it into a character array and comparing first and last elements of the char array to each other to test. I can get the first element of the array to find the second character easily, but to find the last acceptable value and decrement that, it doesn't find the next character in the array. So if the corrected/cleaned char array looks like:
['A']['B']['C']['D']['A']
ebx will go from 'A' -> 'B' but edi will not change from 'A' -> 'D'
Why will ebx change characters but edi only subtracts 1 from it's register value? What can I do to have edi change character value? Thanks!
C++ code: (just in case)
#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] = { '\0' };
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 code:
.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
I haven't tested your code, but looking at it I noticed some possible problems.
Why will ebx change characters
It seems that way, but it's not what you tried to reach. You commented out the lines reading the characters from memory/the array after the initial phase (see below). So in fact, you did change the character in EBX, but not the way you expected (and supposedly wanted). With INC EBX
you increased the char-value from 'A'(65dec) to 'B'(66dec). That 'B' is also the second char of the string is merely a coincidence. Try changing the string from ABCDA to ARRCD or something and you'd still get a 'B' on the second round. So EBX does indeed change.
...
;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?
Yes. That's what your code does and it's correct. Uncomment the above line containing [edi]
and the char pointed at by EDI will be loaded into the lower byte of EDX = DL.
The problem with your code is that you are using EBX both as a pointer and (char)value. Loading the next char into EBX will destroy the pointer and your programm is likely to crash with ACCESS_VIOLATION in the next iteration or show random behaviour which would be hard to debug.
Separate pointers from values like you have done with EDI/EDX (EDI=pointer to char, EDX(DL)=char value.
Another problem is: your code will only work for strings with an odd length.
testNext:
dec edi ; !!!
inc ebx ; !!!
cmp ebx, edi ; checks if elements are equal because that has tested all elements
je allDone
So you are increasing and decreasing the (should be) pointers and then comparing them. Now consider this case of an even-length-string:
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))
...
=> Problem! Won't terminate, condition EBX=EDI will never be met* Possible solution: Add an A(Above = Greater for unsigned values) to the jump
...
cmp ebx, edi
jae allDone