C代码:
#include <stdio.h>
int main()
{
unsigned guess; /* current guess for prime */
unsigned factor; /* possible factor of guess */
unsigned limit; /* find primes up to this value */
printf("Find primes up to: ");
scanf("%u", &limit);
printf("2\n"); /* treat first two primes as special case */
printf("3\n");
guess = 5; /* initial guess */
while ( guess <= limit ) {
/* look for a factor of guess */
factor = 3;
while ( factor*factor < guess && guess % factor != 0 )
factor += 2;
if ( guess % factor != 0 )
printf("%d\n", guess);
guess += 2; /* only look at odd numbers */
}
return 0;
}
汇编代码(NASM):
%include "asm_io.inc"
segment .data
Message db "Find primes up to: ", 0
segment .bss
Limit resd 1 ; find primes up to this limit
Guess resd 1 ; the current guess for prime
segment .text
global _asm_main
_asm_main:
enter 0,0 ; setup routine
pusha
mov eax, Message
call print_string
call read_int ; scanf("%u", & limit );
mov [Limit], eax
mov eax, 2 ; printf("2\n");
call print_int
call print_nl
mov eax, 3 ; printf("3\n");
call print_int
call print_nl
mov dword [Guess], 5 ; Guess = 5;
while_limit: ; while ( Guess <= Limit )
mov eax,[Guess]
cmp eax, [Limit]
jnbe end_while_limit ; use jnbe since numbers are unsigned
mov ebx, 3 ; ebx is factor = 3;
while_factor:
mov eax,ebx
mul eax ; edx:eax = eax*eax
**jo end_while_factor ; if answer won't fit in eax alone**
cmp eax, [Guess]
jnb end_while_factor ; if !(factor*factor < guess)
mov eax,[Guess]
mov edx,0
div ebx ; edx = edx:eax % ebx
cmp edx, 0
je end_while_factor ; if !(guess % factor != 0)
add ebx,2 ; factor += 2;
jmp while_factor
end_while_factor:
**je end_if ; if !(guess % factor != 0)**
mov eax,[Guess] ; printf("%u\n")
call print_int
call print_nl
end_if:
mov eax,[Guess]
add eax, 2
mov [Guess], eax ; guess += 2
jmp while_limit
end_while_limit:
popa
mov eax, 0 ; return back to C
leave
ret
如您所见,我已经标记了**两条指令。
首先,MUL指令将EAX * EAX与EX * EAX相乘并存储在EDX:EAX中,如果它太大而不适合EAX,对吧? 然后程序检查溢出。 因此,当该值太大而不适合EAX时,系统会检测到溢出并设置OF = 1? 为什么?该值不应存储在EAX和EAX中。 EDX,如果需要?
其次,JE指令。评论解释说:if!(猜测%factor!= 0)。
当程序从那里跳过时,这很好:
cmp edx,0
je end_while_factor
但是如果跳转是因为溢出检查,或者是!(因素*因素&lt; 0)? 会没事吗?正在比较哪些值?它只是检查ZF? 但是之前是否因为其他原因(另一条指令)而修改了它。
提前感谢您的帮助。
答案 0 :(得分:2)
是,当EDX寄存器变为非零时,MUL指令设置OF标志。换句话说,当乘法产生的结果不再适合32位无符号整数时。正在测试的表达式是factor*factor < guess
,其中guess
是32位无符号整数。所以代码生成器生成了很好的代码,如果设置了溢出标志,那么无论guess的值如何,表达式都将始终为false。替代方案更糟糕,如果存在溢出,则表达式的结果可能为真。
不幸的是它然后摸索了跳转目标,英特尔手册指定MUL保留未定义的ZF标志。所以这看起来像是一个代码生成器错误。目前尚不清楚编译器生成此代码的是什么,或者这只是C代码的手工替代方案。代码生成器通常不会生成这样的代码,所以我很容易认为它只是手动类型代码中的一个错误。