I was programming an ASCII to decimal converter in ASM and after an edit, it just didn't add to rax
, this caused an infinite loop. GDB says that rax
wasn't accepting ANY numbers, even when moved from memory and other registers.
I have tried moving things into rax
with mov
and I have also tried the inc
operation.
Here is the asciiToDec function, well commented, I push the location of the ASCII numbers then the amount of them onto the stack then call this function.
asciiToDec: ; Converts a number in ASCII to decimal that the computer can understand
pop rax ; Remove the ret pointer so that it isnt popped off later when the other values are popped
pop qword[amount] ; Remove the amount of characters from the stack
pop qword[location] ; Remove the location from the stack
push rax ; Push the ret pointer back onto the stack
mov rax,1 ; Move 1 into rax since 0*x==0 so 1*x==10 where x=10
mov rbx,10 ; Move 10 into rbx
mov rcx,[amount] ; Move the amount of stuff into rcx
sub rcx,1 ; Subtract one since the one's digit needs to be multiplied by 1 not 10
;-----------------------------------;
loop1: ; Stage 1: Counts the power of 10 that is needed for the first number, highest digit
mul rbx ; Multiply rax by rbx, rax*10
sub rcx,1 ; Subtract 1 from rcx
cmp rcx,0 ; Test if rcx==0
jne loop1 ; Repeat if rcx>0
mov [power10],rax ; Move the power of ten into the power10 variable
xor rax,rax ; Set rax to 0 via xoring the bits to 0
mov rbx,[location] ; Move the location of the ASCII into rbx
;-----------------------------------;
loop2: ; Stage 2: Actually converts the ASCII to decimal by subtracting ASCII '0'
xor rcx,rcx ; Remove previous data
mov cl,byte[rbx+rax] ; Copy new data into the low byte of rcx
cmp cl,10 ; Next 4 lines: test for newlines and carrige returns, shouldn't have any but just making sure
je loop2 ; /\
cmp cl,13 ; /\
je loop2 ; /\
add rax,1 ; INC rax so we have the next byte
sub cl,'0' ; Make it decimal and not ASCII
cmp cl,9 ; Test if the value in cl is equal to 9
jg failFun ; If greater than 9 then the ASCII value in this index was not 0-9
push rax ; Get the data in rax out of the way so we can do some calculations with rax
mov al,cl ; Move the byte in cl to al, 0-9
mul qword[power10] ; Multiply rax (al is the lowest 8 bits of rax) by the power of 10
mov rcx,rax ; Move the val in rax back to rcx for later use
mov rax,[power10] ; Move the power of 10 to rax
push rbx ; Get the data in rbx out of the way, like rax
mov rbx,10 ; Move 10 into rbx
div rbx ; Divide rax (power of ten) by rbx (10) to get the next lower digit's power
pop rbx ; Get back the data that was in rbx
mov [power10],rax ; Move the power of 10 back into the `power10` variable from rax
pop rax ; Get rax's data back
add [total],rcx ; Add rcx to the total
cmp rax,[amount] ; Compare rax to the amount of characters
jne loop2 ; If we haven't gone through all the characters, loop again
pop rax ; Get the ret pointer out of the stack so I can have it on the top later
push qword[total] ; Move the total into the stack
push rax ; and push the ret pointer back on top
jmp clean ; Jump to clean
;-----------------------------------;
failFun: ; Stage 3: An option for the function to go through if stage 2 fails
push qword fail
push qword failLen
call print
pop rax
push qword 0
push rax
jmp clean
I expect it to push the dec number onto the stack for popping later but instead, rax
is never above 0
even after the add operation and the mov rax,[power10]
which results in an infinite loop because rax
never reaches [amount]
EDIT: GDB output:
Starting program: /path/to/executable/a.out
1234
Breakpoint 1, loop2 () at common.asm:114
114 xor rcx,rcx ; Remove previous data
(gdb) info reg rax
rax 0x0 0
(gdb) nexti
115 mov cl,byte[rbx+rax] ; Copy new data into the low byte of rcx
(gdb)
116 cmp cl,10 ; Next 4 lines: test for newlines and carrige returns, shouldn't have any but just making sure
(gdb)
120 add rax,1 ; INC rax so we have the next byte
(gdb)
121 sub cl,'0' ; Make it decimal and not ASCII
(gdb) info reg rax
rax 0x0 0