2012-05-18 39 views
1

C代碼:PC彙編語言(保羅·卡特) - Prime.Asm舉例說明關於喬和JE

#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並將其存儲在EDX:EAX中,如果它太大而不適合EAX,對吧? 然後程序檢查溢出。 所以當這個值太大而不適合EAX時,系統檢測到溢出並且設置OF = 1? 爲什麼?如果需要,該值不會同時存儲在EAX & EDX中?其次,JE指令。該評論解釋:如果!(猜測%因子!= 0)。

cmp edx,0 
je end_while_factor 

但如果跳是因爲溢出檢查的製作,或者如果(因素*因素< 0):當程序從那裏跳

那好嗎? 它會好嗎?正在比較哪些值?它只是檢查ZF? 但是不是因爲另一個原因(另一條指令)而被修改過。

在此先感謝您的幫助。

回答

2

是的,當EDX寄存器變爲非零時,MUL指令設置OF標誌。換句話說,當乘法產生的結果不再適合32位無符號整數。正在測試的表達式是factor*factor < guess,其中guess是一個32位無符號整數。因此,如果設置了溢出標誌,那麼代碼生成器會生成很好的代碼,不管guess的值如何,表達式總是會爲false。另一種方法更糟糕,如果有溢出,那麼表達式的結果可能是真的。

不幸的是,它然後弄亂了跳轉目標,英特爾手冊指定MUL離開ZF標誌未定義。因此,這看起來像一個代碼生成器的bug。目前還不清楚什麼編譯器生成了這個代碼,或者這只是C代碼的一個手工類型的替代。代碼生成器通常不會生成這樣的代碼,所以我很容易認爲這只是手型代碼中的一個錯誤。

+0

感謝您的回答! OF現在已經很清楚了。關於JE ...以前的指令是:cmp eax,[Limit]被執行。如果eax = [Limit] JMP沒有生成,while循環開始,所以ZF = 1,因爲cmp。如果現在發生溢出,並且程序跳轉到end_while_factor,則由於ZF保持1,所以不會打印該號碼? –

+0

呃,不,比較跳轉到end_while_limit。有幾個地方跳轉到end_while_factor。這只是錯誤的代碼。 –

+0

好的!感謝您的幫助! –