I'm trying to work out if a string is a palindrome or not in Assembly. Essentially I attempt to copy the bytes backwards from string 'my_string' to 'tmp_str'. Then I attempt to compare both strings use repe and cmpsb.
The problem I'm facing is that the program randomly hangs or throws SIGILL's OR SIGSEV's when setting breakpoints in GDB. The behaviour is truly random, or random enough that I can't the source of the error to a single line. I am incredibly confused and would appreciate some insight in what may be causing these errors. Note, if I set no break points or some others such as line 25, 27, 28, it works fine.
I have checked, and the for loop does iterate the correct number of times, with the right values. The initial strings are also in the format I expect.
Example errors:
Hangs <- if break point is set to line 30
Program received signal SIGILL, Illegal instruction. _start.for_1.end () at 4.asm:32 32 jmp .for_1.start <- when break point was set to line 28 (bug isn't reproducible but it did happen)
Program received signal SIGSEGV, Segmentation fault. 0x0000000000400feb in ?? () <- when break point was set to line 31
;; Write an assembly program to determine if a string stored in memory is a palindrome
;; (A palindrome is a string which is the same after being reversed, like "refer")
;; Use at least one repeat instruction
segment .data
my_string db "bob", 0
segment .bss
tmp_str resb 4
segment .text
global _start
_start:
;/* Copy initial string BACKWARDS */
xor rcx, rcx ; have to use manual for loop
.for_1.start:
cmp ecx, 4
je .for_1.end
mov al, byte [my_string+ecx] ; get character from original string from i'th place
mov rbx, tmp_str+2 ; go to end of tmp_str (writing my_string to tmp_str backwards)
sub rbx, rcx ; we can't minus from address expression thingy, so just deduct from register stored above
mov [rbx], byte al ; copy byte in ebx into mem address stored atueax
inc ecx ; increment counter
jmp .for_1.start ; unconditional start to stop (for loops check and do conditional jumps at top)
.for_1.end:
;/* Compare strings */
mov rsi, my_string ; now we want to compare strings (remember, pointer in reg moves in movsb)
mov rdi, tmp_str ; rdi, set to tmp_str address
mov rcx, 2 ; since rcx was modified by rep, we need to reset that though
repe cmpsb ; compare strings whilst each val (byte) is equal
; now, if rcx is NOT 0, the bytes do not match and is not a palindrome!
;/* EOP */
mov eax, 1
xor ebx, ebx
int 0x80
If anybody could offer some advice I would be greatly appreciative.
Compile commands: yasm -f elf64 -g dwarf2 <file>.asm ; ld <file>.o -o <file>