2010-06-29 17 views
13

इनलाइन असेंबलर [जीसीसी, इंटेल, सी] का उपयोग करके, यह जांचने के लिए कि कैर्री फ्लैग ऑपरेशन के बाद सेट किया गया है या नहीं?जांचें कि क्या लेयर फ्लैग सेट है

+0

आप इसे एएसएम के ब्लॉक में जांचना चाहते हैं या आप सी कोड में कुछ ले जाने के लिए लेयर फ्लैग की स्थिति को पास करना चाहते हैं जिसमें आपका एएसएम रेखांकित है? –

+0

एएसएम के एक ब्लॉक के भीतर परीक्षण प्रत्यय है। इसे पार करना मुश्किल नहीं होना चाहिए। – hans

उत्तर

10

सशर्त कूद के साथ jc (ले जाने पर कूदें) या jnc (कूदने पर कूदें)।

या आप झंडा कैरी स्टोर कर सकते हैं,

;; Intel syntax 
mov eax, 0 
adc eax, 0 ; add with carry 
+0

आह ठीक है, जेसी, जेएनसी, एडीसी कमांड नहीं पता था। Thx – hans

+2

वार्निन, जीसीसी एटी एंड टी वाक्यविन्यास का उपयोग करता है। यह इंटेल वाक्यविन्यास है ... –

+1

@Fififox, धन्यवाद। मैंने अपना जवाब संपादित किया। –

14

sbb %eax,%eax स्टोर करेगा -1 eax में यदि कैरी ध्वज सेट है, 0 यदि यह स्पष्ट है। 0 को ईएक्स को पूर्व-साफ़ करने की आवश्यकता नहीं है; अपने आप से ईएक्स घटाना आपके लिए करता है। यह तकनीक बहुत शक्तिशाली हो सकती है क्योंकि आप सशर्त कूदों के उपयोग के बजाय गणना के परिणामों को संशोधित करने के लिए बिटमैस्क के रूप में परिणाम का उपयोग कर सकते हैं।

आपको अवगत होना चाहिए कि यह केवल वाहक ध्वज का परीक्षण करने के लिए मान्य है अगर यह इनलाइन एएसएम ब्लॉक के अंदर अंकगणित प्रदर्शन द्वारा निर्धारित किया गया था। आप सी कोड में किए गए एक गणना के परीक्षण का परीक्षण नहीं कर सकते हैं क्योंकि कंपाइलर कैरी फ्लैग को पकड़ने वाली चीजों को अनुकूलित/पुन: व्यवस्थित कर सकता है।

5

हालांकि x86 असेंबलर hes तेज़ एसईटीसीसी नामक एएलयू ध्वज परीक्षण निर्देश जहां सीसी वांछित एएलयू ध्वज है। तो अगर आप लिख सकते हैं:

साथ
setc AL       //will set AL register to 1 or clear to 0 depend on carry flag 

or 

setc byte ptr [edx]    //will set memory byte on location edx depend on carry flag 

or even 

setc byte ptr [CarryFlagTestByte] //will set memory variable on location CarryFlagTestByte depend on carry flag 

SETcc अनुदेश आप कैरी, शून्य, हस्ताक्षर, अतिप्रवाह या समता की तरह झंडे परीक्षण कर सकते हैं, कुछ SETcc निर्देश एक बार में दो झंडे परीक्षण करने के लिए अनुमति देते हैं।

संपादित करें: जोड़ा साधारण परीक्षण डेल्फी में की गई अवधि के बारे में संदेह गायब हो जाने की तेजी

procedure TfrmTest.ButtonTestClick(Sender: TObject); 
    function GetCPUTimeStamp: int64; 
    asm 
    rdtsc 
    end; 
var 
ii, i: int64; 
begin 
    i := GetCPUTimeStamp; 
    asm 
    mov ecx, 1000000 
@repeat: 
    mov al, 0 
    adc al, 0 
    mov al, 0 
    adc al, 0 
    mov al, 0 
    adc al, 0 
    mov al, 0 
    adc al, 0 
    loop @repeat 
    end; 
    i := GetCPUTimeStamp - i; 

    ii := GetCPUTimeStamp; 
    asm 
    mov ecx, 1000000 
@repeat: 
    setc al 
    setc al 
    setc al 
    setc al 
    loop @repeat 
    end; 
    ii := GetCPUTimeStamp - ii; 
    caption := IntToStr(i) + ' ' + IntToStr(ii)); 
end; 

पाश (1M पुनरावृत्तियों) अनुदेश का उपयोग कर जो SETC से अधिक से अधिक 5 गुना तेजी से है एडीसी प्रेरणा के साथ लूप।

संपादित करें: पंजीकरण में संग्रहीत परीक्षा परिणाम में दूसरा परीक्षण जोड़ा गया है, रजिस्टर में एएल कॉम्युलेटिव सीएल अधिक यथार्थवादी मामला है। SETcc अनुदेश के साथ

procedure TfrmTestOtlContainers.Button1Click(Sender: TObject); 
    function GetCPUTimeStamp: int64; 
    asm 
    rdtsc 
    end; 

var 
ii, i: int64; 
begin 
    i := GetCPUTimeStamp; 
    asm 
    xor ecx, ecx 
    mov edx, $AAAAAAAA 

    shl edx, 1 
    mov al, 0 
    adc al, 0 
    add cl, al 

    shl edx, 1 
    mov al, 0 
    adc al, 0 
    add cl, al 

    shl edx, 1 
    mov al, 0 
    adc al, 0 
    add cl, al 

    shl edx, 1 
    mov al, 0 
    adc al, 0 
    add cl, al 

    shl edx, 1 
    mov al, 0 
    adc al, 0 
    add cl, al 

    shl edx, 1 
    mov al, 0 
    adc al, 0 
    add cl, al 

    shl edx, 1 
    mov al, 0 
    adc al, 0 
    add cl, al 

    shl edx, 1 
    mov al, 0 
    adc al, 0 
    add cl, al 

    end; 
    i := GetCPUTimeStamp - i; 

    ii := GetCPUTimeStamp; 
    asm 
    xor ecx, ecx 
    mov edx, $AAAAAAAA 

    shl edx, 1 
    setc al 
    add cl, al 

    shl edx, 1 
    setc al 
    add cl, al 

    shl edx, 1 
    setc al 
    add cl, al 

    shl edx, 1 
    setc al 
    add cl, al 

    shl edx, 1 
    setc al 
    add cl, al 

    shl edx, 1 
    setc al 
    add cl, al 

    shl edx, 1 
    setc al 
    add cl, al 

    shl edx, 1 
    setc al 
    add cl, al 

    end; 
    ii := GetCPUTimeStamp - ii; 
    caption := IntToStr(i) + ' ' + IntToStr(ii); 
end; 

Rutine हिस्सा अभी भी तेजी से लगभग 20% के लिए है।

+0

क्या आपके पास उन्हें तेजी से कॉल करने के लिए उद्धरण है? मैंने पिछले कुछ पीढ़ियों के लिए नवीनतम सीपीयू के साथ नहीं रखा है, लेकिन लंबे समय तक, इन्हें धीमी विरासत ऑपकोड माना जाता था। –

+0

@ आर .. इसमें कोई संदेह नहीं है: आप गलत हैं! ऊपरी परीक्षण की जांच करें! –

+1

@ आर .. हाँ एसईटीसीसी पुराना निर्देश है, लेकिन एडीसी से बहुत तेज़ है या जेसी या जेएनसी जैसे सिंडिशन कूदता है। –

2

पहला फ़ंक्शन हस्ताक्षरित अतिरिक्त प्रदर्शन करता है और फिर लेयर फ्लैग (सीएफ) का उपयोग करके अतिप्रवाह के लिए परीक्षण करता है। अस्थिर रहना चाहिए। अन्यथा अनुकूलक निर्देशों को पुनर्व्यवस्थित करेगा, जो कि गलत परिणाम सुनिश्चित करता है। मैंने देखा है कि ऑप्टिमाइज़र jnc को jae (जो सीएफ पर भी आधारित है) में बदल गया है।

/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */ 
int add_u32(uint32_t a, uint32_t b, uint32_t* r) 
{ 
    volatile int no_carry = 1; 
    volatile uint32_t result = a + b; 

    asm volatile 
    (
    "jnc 1f   ;" 
    "movl $0, %[xc] ;" 
    "1:    ;" 
    : [xc] "=m" (no_carry) 
    ); 

    if(r) 
     *r = result; 

    return no_carry; 
} 

अगला कार्य हस्ताक्षरित इंकों के लिए है। अस्थिरता का वही उपयोग लागू होता है। ध्यान दें कि हस्ताक्षर किए गए पूर्णांक गणित jno के माध्यम से ध्वज पर कूदता है। मैंने देखा है कि ऑप्टिमाइज़र इसे jnb (जो कि ओएस पर भी आधारित है) में बदल देता है।

/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */ 
int add_i32(int32_t a, int32_t b, int32_t* r) 
{ 
    volatile int no_overflow = 1; 
    volatile int32_t result = a + b; 

    asm volatile 
    (
    "jno 1f   ;" 
    "movl $0, %[xo] ;" 
    "1:    ;" 
    : [xo] "=m" (no_overflow) 
    ); 

    if(r) 
     *r = result; 

    return no_overflow; 
} 

बड़ी तस्वीर में, आप निम्नानुसार कार्यों का उपयोग कर सकते हैं।एक ही बड़ी तस्वीर में, कई लोगों को शायद अतिरिक्त काम और सौंदर्य गैर सौंदर्य तक एक अतिप्रवाह/रैप से pwn'd/अधःप्रवाह

int r, a, b; 
... 

if(!add_i32(a, b, &r)) 
    abort(); // Integer overflow!!! 

... 

इनलाइन जीसीसी विधानसभा जीसीसी में उपलब्ध है 3.1 और इसके बाद के संस्करण को अस्वीकार कर देंगे। Assembler Instructions with C Expression Operands देखें, या 'जीसीसी विस्तारित असेंबली' के लिए खोजें।

अंत में, दृश्य स्टूडियो में एक ही रूप में (कोड पीढ़ी में बहुत ज्यादा नहीं अंतर) इस प्रकार होगा, लेकिन वाक्य रचना बहुत आसान के बाद से MASM आप एक सी लेबल के लिए कूद करने की अनुमति देता है:

/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */ 
int add_i32(__int32 a, __int32 b, __int32* r) 
{ 
    volatile int no_overflow = 1; 
    volatile __int32 result = a + b; 

    __asm 
    { 
     jno NO_OVERFLOW; 
     mov no_overflow, 0; 
    NO_OVERFLOW: 
    } 

    if(r) 
     *r = result; 

    return no_overflow; 
} 

बुरा पर पक्ष, उपरोक्त एमएएसएम कोड केवल x86 असेंबली के लिए लागू है। X64 असेंबली के लिए, कोई इनलाइनिंग नहीं है, इसलिए आपको इसे असेंबली (एक अलग फ़ाइल में) में कोड करना होगा और संकलन के लिए MASM64 का उपयोग करना होगा।

+0

उदाहरण के लिए आप सी लेबल पर कूदने के लिए गोटो एक्सटेंशन का उपयोग कर सकते हैं एएसएम अस्थिर गोटो ("ja% एल [clabel]":: "स्मृति": clabel) ;, clabel सी लेबल –

+0

पढ़ना @R द्वारा जवाब bellow है जहां .. आपके समारोह रद्द करने के लिए लगता है। 'आपको अवगत होना चाहिए कि यह केवल लेयर फ्लैग का परीक्षण करने के लिए मान्य है अगर यह इनलाइन एएसएम ब्लॉक के अंदर अंकगणित प्रदर्शन द्वारा निर्धारित किया गया था।' क्या आप इसके बारे में निश्चित हैं? –

+0

@ डीआरबीको - हाँ, जीसीसी के लिए, यह निर्भर करता है। जीसीसी आपके ब्लॉक में निर्देशों की "निरंतरता" सुनिश्चित करेगा, लेकिन यह अपने निर्देशों को सम्मिलित/अंतःस्थापित कर सकता है। यदि जीसीसी निर्देश सीसी को संशोधित नहीं करते हैं, तो सब ठीक हो जाएगा। माइक्रोसॉफ्ट के इनलाइन असेंबलर जीसीसी की सीमाओं का सामना नहीं करते हैं। – jww

संबंधित मुद्दे