कैसे निम्नलिखित है, जो एक छोटे से परीक्षण में मेरे लिए काम करने लगता है के बारे में:
int sbcas(uint64_t* ptr, uint64_t oldval, uint64_t newval)
{
int changed = 0;
__asm__ (
"push %%ebx\n\t" // -fPIC uses ebx, so save it
"mov %5, %%ebx\n\t" // load ebx with needed value
"lock\n\t"
"cmpxchg8b %0\n\t" // perform CAS operation
"setz %%al\n\t" // eax potentially modified anyway
"movzx %%al, %1\n\t" // store result of comparison in 'changed'
"pop %%ebx\n\t" // restore ebx
: "+m" (*ptr), "=r" (changed)
: "d" ((uint32_t)(oldval >> 32)), "a" ((uint32_t)(oldval & 0xffffffff)), "c" ((uint32_t)(newval >> 32)), "r" ((uint32_t)(newval & 0xffffffff))
: "flags", "memory"
);
return changed;
}
यह भी miscompiled हो जाता है आप एक छोटा स्निपेट है कि इस व्यवहार से चलाता शामिल करें सकता है?
बोनस प्रश्न के संबंध में मुझे नहीं लगता कि cmpxchg8b
निर्देश से स्थिति कोड का उपयोग करके असेंबलर ब्लॉक के बाद शाखा करना संभव है (जब तक आप asm goto
या इसी तरह की कार्यक्षमता का उपयोग नहीं करते)।GNU C Language Extensions से:
असेंबलर निर्देश द्वारा छोड़े गए शर्त कोड तक पहुंच प्रदान करने का एक तरीका ढूंढना एक प्राकृतिक विचार है। हालांकि, जब हमने इसे लागू करने का प्रयास किया, तो हमें इसे विश्वसनीय तरीके से काम करने का कोई रास्ता नहीं मिला। समस्या यह है कि आउटपुट ऑपरेटरों को पुनः लोड करने की आवश्यकता हो सकती है, जिसके परिणामस्वरूप अतिरिक्त "स्टोर" निर्देशों का परिणाम होगा। अधिकांश मशीनों पर, इन निर्देशों का परीक्षण करने के लिए समय होने से पहले हालत कोड बदल जाएगा। यह समस्या साधारण "परीक्षण" और "तुलना" निर्देशों के लिए उत्पन्न नहीं होती है क्योंकि उनके पास कोई आउटपुट ऑपरेंड नहीं है।
संपादित करें: मैं किसी भी स्रोत है कि एक ही रास्ता या अन्य चाहे वह करते हुए भी %N
इनपुट मानों का उपयोग करके स्टैक को संशोधित करने के लिए ठीक है निर्दिष्ट करता नहीं खोजा जा सका (This प्राचीन लिंक कहते हैं, "तुम भी पर अपने रजिस्टरों धक्का कर सकते हैं ढेर, उनका उपयोग करें, और उन्हें वापस रखो। "लेकिन उदाहरण में इनपुट नहीं है)।
लेकिन यह अन्य रजिस्टरों को मान फिक्सिंग से बिना ऐसा करना संभव होना चाहिए:
int sbcas(uint64_t* ptr, uint64_t oldval, uint64_t newval)
{
int changed = 0;
__asm__ (
"push %%ebx\n\t" // -fPIC uses ebx
"mov %%edi, %%ebx\n\t" // load ebx with needed value
"lock\n\t"
"cmpxchg8b (%%esi)\n\t"
"setz %%al\n\t" // eax potentially modified anyway
"movzx %%al, %1\n\t"
"pop %%ebx\n\t"
: "+S" (ptr), "=a" (changed)
: "0" (ptr), "d" ((uint32_t)(oldval >> 32)), "a" ((uint32_t)(oldval & 0xffffffff)), "c" ((uint32_t)(newval >> 32)), "D" ((uint32_t)(newval & 0xffffffff))
: "flags", "memory"
);
return changed;
}
तथ्य यह है कि संकलक आंतरिक -fPIC साथ काम नहीं करता सिर्फ एक खुले दिल से संकलक बग है: http: //gcc.gnu.org/bugzilla/show_bug.cgi?id=37651 जब आप टूटे हुए कंपाइलर के आसपास काम करना चाहते हैं तो यह बेकार हो जाता है, ताकि आप स्वयं को उस बग के लिए सीसी सूची में रखना चाहें। – Crashworks
आप आईए 32 पर '-fPIC' का उपयोग करते हैं? मैं उत्सुक हूँ क्यों। – Gabe
@Gabe - साझा लाइब्रेरी ऑब्जेक्ट्स लिखते समय यह सबसे महत्वपूर्ण है। Ulrich Drepper इस विषय पर एक अच्छा पेपर है: http://www.akkadia.org/drepper/dsohowto.pdf – Crashworks