我正在ASM中对ASCII到十进制转换器进行编程,并且在编辑后,它没有添加到rax
中,这导致了无限循环。 GDB表示rax
不接受任何数字,即使从内存和其他寄存器中移出也是如此。
我尝试使用rax
将事物移至mov
,并且还尝试了inc
操作。
这是asciiToDec函数,它的注释很好,我将ASCII数字的位置压入堆栈,然后将其数量压入堆栈,然后调用此函数。
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
我希望它可以将dec数压入堆栈,以便稍后弹出,但是rax
永远不会高于0
,即使在执行加法运算和mov rax,[power10]
之后也会导致无限循环,因为rax
从未到达[amount]
编辑:GDB输出:
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
答案 0 :(得分:2)
您的
/\
注释使NASM感到困惑,并且忽略了这些行。请删除这些注释。 *实际上,反斜杠是连续的行,因此nasm认为以下几行是您的评论的其余部分-Jester
使用\
删除注释可解决此问题,因为NASM认为下一行是注释。 VIM NASM语法突出显示不遵循此规则。
根据NASM手册,3.1 Layout of a NASM Source Line:
NASM使用反斜杠(
\
)作为换行符; 如果一行以反斜杠结尾,则下一行被视为反斜杠结尾的行的一部分。
答案 1 :(得分:1)
仅需注意,您可以使用xor eax, eax
代替xor rax, rax
。前者也将64位高半部分清零,但编码时间短了1个字节。 mov eax, 1
与mov rax, 1
的情况相同。
通常,32位操作数会生成32位结果,并将其零扩展到目标通用寄存器中的64位结果(否则32位操作将依赖于64位高半部分寄存器)。有关更多详细信息,请参见x86-64 Tour of Intel Manuals。