c++ - विधानसभा एडीसी(ले जाने के साथ जोड़ें) को सी++




assembly (4)

एडीसी एडीडी के समान है लेकिन प्रोसेसर का फ्लैग सेट होने पर अतिरिक्त 1 जोड़ता है।

एक विधानसभा अनुदेश ADC मैंने यह पाया है "ले जाने के साथ जोड़ें" लेकिन मुझे नहीं पता कि इसका मतलब क्या है। या सी ++ में इस अनुदेश को कैसे लिखना है और मुझे पता है कि यह ADD के समान नहीं है। तो एक सरल योग बनाना सही नहीं है।

जानकारी:
विंडोज में संकलित मैं 32-बिट विंडोज़ इंस्टॉलेशन का उपयोग कर रहा हूं। मेरा प्रोसेसर इंटेल से कोर 2 डुओ है


एडीसी के व्यवहार को सी और सी ++ दोनों में अनुकरण किया जा सकता है। निम्नलिखित उदाहरण दो नंबर जोड़ता है (अहस्ताक्षरित के arrays के रूप में संग्रहीत के रूप में वे एक ही अहस्ताक्षरित में फिट करने के लिए बहुत बड़ी हैं)

unsigned first[10];
unsigned second[10];
unsigned result[11];

....   /* first and second get defined */

unsigned carry = 0;
for (i = 0; i < 10; i++) {
    result[i] = first[i] + second[i] + carry;
    carry = (first[i] > result[i]);
}
result[10] = carry;

उम्मीद है की यह मदद करेगा।


यहां से (टूटी हुई) या यहाँ से

हालांकि, इंटेल प्रोसेसर का एडीसी नामक एक विशेष निर्देश है यह आदेश समान रूप से एडी कमांड के रूप में व्यवहार करता है। केवल एक अतिरिक्त बात यह है कि यह साथ में मूल्य वाला ध्वज भी जोड़ता है इसलिए, बड़े इंटिजर्स जोड़ने के लिए यह बहुत आसान हो सकता है मान लीजिए आप 16-बिट रजिस्टरों के साथ एक 32-बिट पूर्णांक जोड़ना चाहते हैं। हम वह कैसे कर सकते है? ठीक है, हम कहते हैं कि पहली पूर्णांक को रजिस्टर जोड़ी डीएक्स: एएक्स पर रखा जाता है, और दूसरा बीएक्स: सीएक्स पर है। इस तरह से:

add  ax, cx
adc  dx, bx

आह, पहले तो, कम 16-बिट जोड़ कुल्हाड़ी, सीएक्स द्वारा जोड़ा गया है। तब उच्च 16-बिट एडीसी ऐड के बजाय जोड़ दिया जाता है। ऐसा इसलिए है क्योंकि: यदि अतिप्रवाह हो, तो ले जाने वाला बिट स्वतः 16-बिट उच्चतर में जोड़ा जाता है तो, कोई बोझिल जांच नहीं। इस विधि को 64 बिट और इतने पर बढ़ाया जा सकता है ... ध्यान दें: अगर 32-बिट पूर्णांक अतिरिक्त 16-बिट उच्च पर भी ओवरफ्लो हो जाता है, तो परिणाम सही नहीं होगा और कैरी फ्लैग सेट किया जाता है, उदाहरण के लिए 5 अरब 5 अरब तक

यहां से सब कुछ, याद रखें कि यह क्रियान्वयन परिभाषित व्यवहार के क्षेत्र में बहुत अधिक है

यह एक छोटा सा नमूना है जो वीएस 2010 (32-बिट, विनएक्स) के लिए काम करता है

चेतावनी: $ 7.4 / 1- "एस्एम घोषणा सशर्त रूप से समर्थित है, इसका अर्थ कार्यान्वयन-परिभाषित है। [नोट: आमतौर पर इसका उपयोग एंबेबलर के कार्यान्वयन के माध्यम से जानकारी को पास करने के लिए किया जाता है।

int main(){
   bool carry = false;
   int x = 0xffffffff + 0xffffffff;
   __asm {
      jc setcarry
setcarry:
      mov carry, 1
   }
}

सी ++ भाषा में कैरिअर फ्लैग की कोई अवधारणा नहीं होती है, इसलिए ADC अनुदेश के आसपास एक आंतरिक फ़ंक्शन आवरण बनाने से क्लैन्की है। हालांकि, इंटेल ने इसे वैसे भी किया: unsigned char _addcarry_u32 (unsigned char c_in, unsigned a, unsigned b, unsigned * out); । आखिरी बार मैंने चेक किया, जीसीसी ने इस के साथ एक खराब काम किया (सीएफ में छोड़ने के बजाय, एक पूर्णांक रजिस्टर में ले जाने के परिणाम को सहेजने), लेकिन उम्मीद है कि इंटेल के स्वयं के कंपाइलर बेहतर काम करता है

विधानसभा दस्तावेज़ों के लिए x86 टैग विकी भी देखें।

संकलक आपके लिए एडीसी का उपयोग करेगा, जब एक एकल रजिस्टर की तुलना में पूर्णांक संख्या को जोड़ता है, उदाहरण के लिए int64_t कोड में int64_t जोड़ना, या 64 बिट कोड में __int128_t

#include <stdint.h>
#ifdef __x86_64__
__int128_t add128(__int128_t a, __int128_t b) { return a+b; }
#endif
    # clang 3.8 -O3  for x86-64, SystemV ABI.
    # __int128_t args passed in 2 regs each, and returned in rdx:rax
    add     rdi, rdx
    adc     rsi, rcx
    mov     rax, rdi
    mov     rdx, rsi
    ret

Godbolt संकलक एक्सप्लोरर से asm आउटपुट -fverbose-asm बहुत ही वज़ोष नहीं है, लेकिन जीसीसी 5.3 / 6.1 दो चलने वाले निर्देशों को बर्बाद करता है इसलिए यह कम पठनीय है।






assembly