Hi all,

i've found several x86 codes checking if the string is palindrome or not. but i need something different.

a procedure which receives the starting address of a text (in SI) stored in data segment and returns the number of palindrome words in the text into CX. Only word delimiters are space: 20H and fullstop: 2EH. Text is ended with character '$$'

thnx

Pretty straight forward. Without giving you the answer, her is a leg up!

Don't forget index can also contain a general purpose register offset. Also, you can use di as a general purpose counter and free up cx for offset tracking.

So scan forward with something like
xor dx,dx

PreScan:
mov al,[si+dx]
cmp al,'$'

cmp al,' '

cmp al,'.'


; Once delimiter found forward and reverse scan until
; bx is >= dx

mov al,[si+dx]
mov ah,[si+bx]
cmp al,ah

Another tip is by adding the pre-count to the post-count
dx = dx + bx
dx is indexing the delimiter.
And so si = si + dx
and now [si+0] is on the delimiter.

So no need to store the delimiter index anywhere or having to rescan the second half of the palindrome to find the delimiter again.

many thanks wildgoose.

here's the code after yr comments. i know it's very poor but i'm the newestbie :)

xor dx, dx
xor bx, bx

find_delimiter:
inc dx
mov al, [si+dx]
cmp al, 20H
je if_plndrm
cmp al, 2EH
je if_plndrm
cmp al, '$$'
je if_plndrm_last
loop find_delimiter


if_plndrm:
inc bx
dec dx
mov al, [si+dx]
mov ah, [si+bx]
cmp al, ah
jne not_plndrm
cmp bx, dx
jae is_plndrm
loop if_plndrm


not_plndrm:
add dx, bx
add si, dx
jmp find_delimiter


is_plndrm:
add dx, bx
add si, dx
in cx
jmp find_delimiter


if_plndrm_last
inc bx
dec dx
mov al, [si+dx]
mov ah, [si+bx]
cmp al, ah
jne not_plndrm_last
cmp bx, dx
jae is_plndrm_last
loop if_plndrm_last


not_plndrm_last
stop


is_plndrm_last
inc cx
stop

First of all a good start.

But heavily comment. It will make your code much easier to read, especially if you have to modify it six months from now. You'll have to figure what you were thinking when you wrote it the first time.

comment is always pre-scan and remove white space! A text word may not be the first character in the string! Or may be an empty string!

'$' not '$$'

and don't jump to if_plndrm
jump to a Length Check!
Even a terminator should jump to the terminator. There may be no whitespace delimiter after the last word!

If length is zero AND last character wasn't a double '$' '$' then exit.
You should also have an error condition that if you read a 00h value. (C code terminates ASCIIZ strings with a NULL terminator!

Also you may have more then one whitespace delimiter between words! That's why both the length and terminator check. And don't forget you're looking for a double '$' check, which has the implication that a single '$' is a whitespace delimiter!

I'd also recommend putting the ASCII characters being compared within quotes. And for reference put the hex code in a comment to the right of it!
cmp al,'.' ; 02eh

bx = 0 but you increment to bx+1 before the compare thus ignoring the first character of the palindrome.

Also you're okay here but make sure you use the correct comparison! Remember there is a signed and unsigned compare!
jae Jump Above or Equal to
jge Jump Greater or Equal to

I'll leave it to you to look up which is for signed numbers and which unsigned! And since you're using positive integers from {0...N} as an offset it should be unsigned!

Also you're stopping. Remember you should be adjusting si as the new base remove leading delimiters and then do another comparison. Only reaching the terminator should have you return.

But don't forget your error (out of range checking)! You may be comparing 8-bit ASCII and not 7-bit SBCS (Single Byte Character Sets) so you need to assume all ASCII characters are safe, but you need to check for invalid characters, especially (0). Otherwise bad data will crash your program!

And of course, don't forget to save bx, si, di (if used and) if called directly from a higher language! ax, cx, dx are considered scratch!

This article has been dead for over six months. Start a new discussion instead.