汇编语言质数判断程序始终输出相同结果的问题排查
我正在学习汇编语言(ASM),这是我尝试解决的问题之一。该算法目标是判断一个数是否为质数,我逻辑推演认为代码应可行,但实际运行时无论输入数值如何,输出结果始终一致。若是其他编程语言,我可通过添加打印语句调试,但汇编语言无法如此操作,希望有人帮忙分析问题原因。我尝试修改循环条件,但仅改变了固定输出的内容,并未解决输出始终一致的问题。
我的代码如下:
section .data number db 15 ; answer db 1 ; 1 -> prime, 0 -> not prime prime_msg db 'Number is prime', 0x0a not_prime_msg db 'Number is NOT prime', 0x0a section .bss divisor resb 1 ; Reserve one byte for the divisor section .text global _start _start: mov al, [number] mov bl, 2 ; divisor = 2 while_loop: cmp bl, al jg end ;if number (al) is < divisor(bl) jump to end mov dl, al ; Move number into DL mov al, bl ; Move divisor into AL xor ah, ah ;clear remainder div bl ;div al by bl(divisor) cmp ah, 0 ;compare remainder to 0 je not_prime ;jump to not_prime if 0 inc bl jmp while_loop not_prime: mov byte [answer], 0 out_not: mov edx, 16 ; Length of prime_msg ('Number is prime\n') mov ecx, prime_msg ; Pointer to prime_msg mov ebx, 1 ; File descriptor for stdout mov eax, 4 ; sys_write system call int 0x80 ; Make the system call ; Exit the program mov eax, 1 ; sys_exit system call xor ebx, ebx ; Return code 0 int 0x80 ; Make the system call out_prime: mov edx, 20 ; Length of not_prime_msg mov ecx, not_prime_msg ; Pointer to not_prime_msg mov ebx, 1 ; File descriptor for stdout mov eax, 4 ; sys_write system call int 0x80 ; Make the system call ; Exit the program mov eax, 1 ; sys_exit system call xor ebx, ebx ; Return code 0 int 0x80 ; Make the system call end: cmp byte[answer], 0 je out_not ;if answer = 0 -> not prime jmp out_prime ;else prime
问题分析
你的代码存在几个关键错误,导致输出始终一致:
除法逻辑完全错误:
你原本想计算number ÷ divisor,但代码里先把al(存储number)移到dl,然后把bl(divisor)赋值给al,接着执行div bl——这相当于用divisor除以它自己,余数必然是0,所以每次循环都会触发je not_prime跳转,直接设置answer为0。
正确的做法是保留al中的number值,清空ah后执行div bl,这样才是用number除以divisor。循环条件被破坏:
你在循环里修改了al的值(mov al, bl),导致后续cmp bl, al的判断完全失效——此时al已经等于bl,循环条件永远不满足jg end,除非你手动修改,但这也会让逻辑彻底混乱。流程跳转与输出逻辑搞反:
在not_prime标签设置answer为0后,代码直接进入out_not执行输出,但out_not里输出的是prime_msg;同时end标签的判断中,je out_not指向的输出也是错误的——out_not输出质数消息,out_prime输出非质数消息,完全颠倒了逻辑。
修正后的代码示例
section .data number db 15 ; 测试用的数字 answer db 1 ; 1 -> 质数, 0 -> 非质数 prime_msg db 'Number is prime', 0x0a not_prime_msg db 'Number is NOT prime', 0x0a prime_len equ $ - prime_msg not_prime_len equ $ - not_prime_msg section .text global _start _start: mov al, [number] ; 处理特殊情况:小于2的数不是质数 cmp al, 2 jl set_not_prime mov bl, 2 ; 从2开始试除 while_loop: ; 优化:只需要试除到number/2即可,减少循环次数 mov cl, 2 mov al, [number] div cl cmp bl, al jg end_loop mov al, [number] xor ah, ah ; 清空ah,确保ax是完整的number值 div bl ; ax ÷ bl,余数存在ah中 cmp ah, 0 je set_not_prime ; 余数为0,说明不是质数 inc bl jmp while_loop set_not_prime: mov byte [answer], 0 end_loop: cmp byte [answer], 0 je print_not_prime print_prime: mov edx, prime_len mov ecx, prime_msg mov ebx, 1 mov eax, 4 int 0x80 jmp exit_program print_not_prime: mov edx, not_prime_len mov ecx, not_prime_msg mov ebx, 1 mov eax, 4 int 0x80 exit_program: mov eax, 1 xor ebx, ebx int 0x80
内容的提问来源于stack exchange,提问作者Caroline DesJardins

