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>