; =========================================================
; Subroutine to check for a palindrome
;
; d0.w = length of string minus 1
; a0.l = starting RAM address of string (must be 8 bits per character)
; returns with ZERO flag set if the string is a palindrome, clear otherwise
; =========================================================
 
CheckPalin:
	andi.l	#$0000FFFF,d0		;allow using d0 as long
	tst.w	d0			;is string 1 character long?
	beq.b	CheckPalin_Return	;if so, return with ZERO flag set
	movea.l	a0,a1
	adda.l	d0,a1			;set a1 to address of last character
	subi.w	#1,d0			;get whole length
	lsr.w	#1,d0			;get half the length
 
CheckPalin_Loop:
	move.b	(a0),d1			;get character from start of string
	cmp.b	(a1),d1			;compare with character from end of string
	bne.b	CheckPalin_Return	;if unequal, return with ZERO flag unset
	adda.l	#1,a0			;increase offset from start of string
	suba.l	#1,a1			;decrease offset from end of string
	dbf	d0,CheckPalin_Loop
	move.w	#0,d0			;set ZERO flag
 
CheckPalin_Return:
	rts

The credit for this goes to Rob (keiji.msk@googlemail.com).
I may hate some (if not most) of his coding practices, but you gotta admit, a guy who can write a palindrome checker using 4 temporary variables, in ASM, is fucking smart, despite the answer being logical as hell.