非递归NASM阶乘程序问题:仅输出提示语未显示结果120
NASM非递归阶乘程序的错误排查
我编写了一段非递归的NASM汇编程序用于计算数字阶乘,代码如下:
section .data result_msg db 'Factorial: ', 0 newline db 10 section .text global _start _start: ; Constants mov eax, 5 ; Number for which factorial is to be calculated ; Initialize result to 1 mov ebx, 1 ; Result ; Loop to calculate factorial fact_loop: cmp eax, 1 jle print_result ; Multiply current result by the current number imul ebx, eax ; Decrement the number dec eax jmp fact_loop print_result: ; Print "Factorial: " mov eax, 4 mov ebx, 1 mov ecx, result_msg mov edx, 10 ; Updated to the correct length of the message int 0x80 ; Convert the result to ASCII and display it add ebx, '0' ; Convert the result to ASCII mov eax, 4 mov ecx, ebx ; Use ebx directly as the result mov edx, 1 int 0x80 ; Print newline mov eax, 4 mov ebx, 1 lea ecx, [newline] mov edx, 1 int 0x80 ; Exit program mov eax, 1 xor ebx, ebx int 0x80
运行该程序时,仅能打印出提示语“Factorial: ”,无法输出正确的阶乘结果120。请问程序中存在哪些缺失或错误?
核心错误点
- 多位数ASCII转换逻辑缺失:
add ebx, '0'仅适用于0-9的单个数字,120是三位数,直接加'0'会得到120+48=168,这是超出可打印数字范围的ASCII值,无法正确显示。必须实现多位数转ASCII字符串的逻辑(比如通过循环取余、逆序存储字符)。 - Write系统调用参数错误:Linux的
int 0x80write调用(eax=4)要求ecx指向内存中的字符串地址,但代码中直接将寄存器ebx的值传给ecx,系统调用会读取错误的内存区域,导致无法输出有效内容。 - 提示语长度错误:
result_msg的实际长度是11('Factorial: '包含11个字符),但代码中mov edx,10设置的长度不对,虽然不影响提示语显示,但属于细节错误。
修正思路示例
- 在
.data段添加缓冲区用于存储转换后的ASCII字符串:section .data result_msg db 'Factorial: ', 0 newline db 10 buffer resb 10 ; 预留足够空间存储多位数ASCII - 重写
print_result部分,实现多位数转ASCII并正确输出:print_result: ; 打印提示语,修正长度为11 mov eax, 4 mov ebx, 1 mov ecx, result_msg mov edx, 11 int 0x80 ; 保存阶乘结果,准备转换 mov ecx, ebx ; ecx = 120 mov ebx, buffer ; ebx指向缓冲区起始地址 mov edi, 0 ; 记录数字位数 ; 循环取余,将数字转为逆序ASCII字符 convert_loop: xor edx, edx ; 清空edx,div指令会使用edx:eax mov eax, ecx mov esi, 10 div esi ; eax=商,edx=余数 add dl, '0' ; 余数转ASCII mov [ebx+edi], dl ; 存入缓冲区 inc edi cmp eax, 0 jne convert_loop ; 调整指针到最后一个有效字符,准备逆序输出 dec edi add ebx, edi ; 逐个打印数字字符 mov eax, 4 mov edx, 1 print_digit: int 0x80 dec ebx dec edi jns print_digit ; 直到所有字符打印完毕 ; 打印换行 mov eax, 4 mov ebx, 1 mov ecx, newline mov edx, 1 int 0x80 ; 退出程序 mov eax, 1 xor ebx, ebx int 0x80
内容的提问来源于stack exchange,提问作者Little
相关产品推荐
相关产品推荐

