我今天开始学习汇编,并编写了一个程序来打印数字的阶乘。它对于个位数阶乘非常有效,但当我对其进行一些更改以处理更大的数字时,我开始在阶乘的开头得到一个意外的字符。阶乘开头的字符会随着每个数字而变化。
这是我的代码:
section .data
msg db 'Enter a number: ',0 ;content of user prompt
lenmsg equ $ - msg ;length of user prompt
disp db 'Factorial: ',0 ;content of output
lendisp equ $ - disp ;length of output
newline db 0xa ;newline char
section .bss
num resb 3 ;2 bytes for number , 1 byte for newline
fac resb 12 ;12 bytes for Factorial
section .text
global _start
_start:
;Display User Prompt
mov edx,lenmsg ;number of bytes to write
mov ecx,msg ;content to write
mov ebx,1 ;file descriptor : stdout
mov eax,4 ;system call : sys_write
int 0x80 ;call kernel
;Accept User Input
mov edx,2 ;number of bytes to read
mov ecx,num ;input stored at num
mov ebx,0 ;file descriptor : stdin
mov eax,3 ;system call : sys_read
int 0x80 ;call kernel
mov byte [num+eax-1],0 ;replace newline with null
;Calculate Factorial
movzx eax, byte [num] ;move num to eax, replace leading places with zeroes
sub eax,'0' ;convert ascii to integer
mov ecx,eax ;transfer to ecx , acts as counter
mov eax,1 ;eax takes value of 1, acts as factorial
cmp ecx,0 ;checks if input is 0
jz output ;if input is 0 it goes directly to output
loop:
mul ecx ;multiply
dec ecx ;decrease counter
jnz loop ;if ecx > 0, loop through
output:
;Convert integer to ASCII
mov ebx,fac+11 ;fac is 12 bytes long, fac+11 goes to end of fac
mov byte [ebx],0 ;add null character
xor ecx,ecx ;clear ecx , acts as counter
convert:
xor edx,edx ;clear edx
mov ecx,10 ;divisor
div ecx ;eax /= ecx, edx contains remainder
add dl,'0' ;last 8 bits of edx contains the digit, convert it into a string by adding ascii number of '0'
dec ebx ;move buffer pointer, we save each digit in a different position
mov [ebx],dl ;store character
inc ecx ;ecx works as a general purpose register AND as a counter at the SAME TIME
test eax,eax ;works like bitwise AND
mov [fac],bl ;store result to fac
jnz convert ;if eax != 0, continue looping
;Display Output Message
mov edx,lendisp ;length of output message
mov ecx,disp ;content of output message
mov ebx,1 ;file descriptor : stdout
mov eax,4 ;system call : sys_write
int 0x80 ;call kernel
;Display Factorial
mov edx,ecx ;length of factorial
mov ecx,fac ;content of factorial
mov ebx,1 ;file descriptor : stdout
mov eax,4 ;system call : sys_write
int 0x80 ;call kernel
;Display Newline
mov edx,1 ;length of newline
mov ecx,newline ;content of newline
mov ebx,1 ;file descriptor : stdout
mov eax,4 ;system call : sys_write
int 0x80 ;call kernel
;Exit Code
mov eax,1 ;system call : sys_exit
int 0x80 ;call kernel
这是我得到的输出:
输入一个数字:2
阶乘:-2
输入一个数字:3
阶乘:-6
输入一个数字:4
阶乘:,24
输入一个数字:5
阶乘:+120
输入一个数字:6
阶乘:+720
输入一个数字:7
阶乘:*5040
输入一个数字:8
阶乘:)40320
输入一个数字:9
阶乘:(362880
我在 Ubuntu 24.04.1 LTS 上使用 NASM 版本 2.16.01。
请帮我。
当您准备显示阶乘时,您目前首先会显示一条消息。这会破坏您认为在转换循环期间已在 ECX 中建立的计数
。 转换循环也有一些无意义的内容!
这是你所需要的:
请注意,通过将消息放在转换之前,您可以更自由地使用寄存器。
你的阶乘循环不应该乘以 1
由于 0! 和 1! 均为 1,因此立即将两者分开。然后提前停止循环: