2008-09-17 11 views
7

मैं के बारे में कैसे जाना होगा ...x86 असेंबली भाषा का उपयोग करके मैं दो 64-बिट संख्याओं को कैसे गुणा कर सकता हूं?

  • दो 64-बिट संख्या

  • गुणा दो 16 अंकों हेक्साडेसिमल संख्याओं

... का उपयोग कर विधानसभा भाषा गुणा।

मुझे केवल रजिस्ट्रार% eax,% ebx,% ecx,% edx, और स्टैक का उपयोग करने की अनुमति है।

संपादित करें: ओह, मैं ATT सिंटेक्स उपयोग कर रहा हूँ 86
EDIT2 पर: विधानसभा में डिकंपाइल करने के लिए अनुमति नहीं ...

+0

क्या यह आपका होमवर्क है? – tgamblin

+7

होमवर्क सवालों के साथ क्या मामला है? उनके पास एक वैध प्रोग्रामिंग प्रश्न है और यह प्रोग्रामिंग प्रश्न पूछने का एक स्थान है। –

+2

एफएक्यू से: http://stackoverflow.com/questions/40219/what-is-the-policy-here-on-homework –

उत्तर

12

संभवतः अपनी पाठ्यक्रम पाठ्यपुस्तक, रैंडल हाइड की "असेंबली भाषा की कला" का उपयोग करना चाहिए।

4.2.4 - Extended Precision Multiplication

हालांकि एक 8x8, 16x16, 32x32 या गुणा आमतौर पर पर्याप्त है देखें, बार जब आप बड़े मान एक साथ गुणा कर सकते हैं कर रहे हैं। आप .. बढ़ाया परिशुद्धता गुणन के लिए 86 एकल संकार्य एमयूएल और IMUL निर्देश का उपयोग करेगा

शायद याद करने के लिए सबसे महत्वपूर्ण बात यह है जब प्रदर्शन कर एक विस्तारित परिशुद्धता गुणा है कि आप भी एक ही समय पर एक से अधिक परिशुद्धता इसके अलावा प्रदर्शन करना है । सभी आंशिक उत्पादों को जोड़ने के लिए कई जोड़ों की आवश्यकता होती है जो परिणाम उत्पन्न करेंगे। निम्नलिखित सूची एक 32 बिट प्रोसेसर पर दो 64 बिट मूल्यों गुणा करने के लिए उचित तरीके से ..

(पूर्ण विधानसभा सूची और चित्रों के लिए लिंक देखें।)

+0

पर संपादन बटन के लिए लगता है मुझे लगता है कि यह स्पष्टीकरण अच्छी तरह से करेगा। बहुत बहुत धन्यवाद, मैं निश्चित रूप से इस बहुत सावधानी से देख सकता हूं – Kawarazu

+0

लिंक काम नहीं कर रहा है। – user35443

+0

नया यूआरएल: http: // www।बागान-productions.com/Webster/www.artofasm.com/Windows/HTML/AdvancedArithmetica2.html#1007619 – msiemens

0

आप क्या विधानसभा आप उपयोग कर रहे निर्दिष्ट करने के लिए कर सकते हैं। सामान्य तकनीकें पार-लागू होती हैं (आमतौर पर), लेकिन प्लेटफार्मों के बीच निमोनिक्स लगभग हमेशा अलग होते हैं। :-)

+0

ओह, x86 के लिए एटीटी सिंटेक्स? मुझे उस जानकारी को जोड़ने के लिए खेद है ... * शीर्षक * – Kawarazu

0

यह निर्भर करता है कि आप किस भाषा का उपयोग कर रहे हैं। एमआईपीएस असेंबली सीखने से मुझे जो याद है, उससे हाई कमांड से एक मूव और लो कमांड, या एमएफएलओ और एमएफआई से एक मूव है। एमएफआई शीर्ष 64 बिट्स स्टोर करता है जबकि एमएफएलओ कुल संख्या के 64 बिट्स को स्टोर करता है।

0

आह विधानसभा को दर्शाता है, थोड़ा समय हो गया जब से i ' मैंने इसका इस्तेमाल किया इसलिए मुझे लगता है कि असली समस्या यह है कि माइक्रोकंट्रोलर (जो भी मैं असेंबली में कोड लिखता था) आप काम कर रहे हैं 64 बिट रजिस्ट्रार नहीं है? यदि ऐसा है, तो आप उन संख्याओं को तोड़ने जा रहे हैं जिनके साथ आप अलग-अलग काम कर रहे हैं और टुकड़ों के साथ कई गुणा प्रदर्शन करते हैं।

इस लगता है जिस तरह से आप यह शब्दों में किया है से एक होमवर्क असाइनमेंट है जैसे, तो मैं यह बहुत आगे नहीं जादू बाहर जा रहा हूँ: पी

1

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

+1

मुझे लगता है कि उच्च * उच्च भाग अनदेखा है क्योंकि इससे कोई फर्क नहीं पड़ता कि – BCS

0

बस सामान्य लंबी गुणा करें, जैसे कि आप 2 अंकों की संख्या की एक जोड़ी गुणा कर रहे थे, सिवाय इसके कि प्रत्येक "अंक" वास्तव में 32-बिट पूर्णांक है। आप पते एक्स और वाई में दो नंबर गुणा और जेड में परिणाम भंडारण कर रहे हैं तो क्या आप (स्यूडोकोड में) क्या करना चाहते है:

Z[0..3] = X[0..3] * Y[0..3] 
Z[4..7] = X[0..3] * Y[4..7] + X[4..7] * Y[0..3]

ध्यान दें कि हम के ऊपरी 64 बिट्स को त्यागकर रहे हैं नतीजा (64-बिट संख्या 64-बिट संख्या 128-बिट संख्या के बाद से)। यह भी ध्यान रखें कि यह थोड़ा-अंतराल मान रहा है। साथ ही, एक हस्ताक्षरित गुणा के हस्ताक्षर किए गए हस्ताक्षर के बारे में सावधान रहें।

+0

यह पहले भाग – BCS

+0

से उच्च बिट्स गायब है रुको, आपने मुझे भ्रमित कर दिया है - आपने आगे बढ़ने और परिणाम के ऊपरी 64 बिट्स से छुटकारा पाने के लिए कहा है? वह क्यों होगा ... अच्छा, तर्कसंगत ...? – Kawarazu

0

एक सी संकलक ढूंढें जो 64 बिट (जीसीसी आईआईआरसी करता है) का समर्थन करता है जो एक प्रोग्राम को संकलित करता है जो बस करता है, फिर डिस्सेप्लर प्राप्त करें। जीसीसी इसे अपने आप थूक सकता है और आप इसे सही टूल के साथ ऑब्जेक्ट फ़ाइल से बाहर निकाल सकते हैं।

OTOH उनके एक 32bX32b = 64b 86 पर सेशन

a:b * c:d = e:f 
// goes to 
e:f = b*d; 
x:y = a*d; e += x; 
x:y = b*c; e += x; 

सब कुछ किसी और overflows

(untested)

संपादित अहस्ताक्षरित केवल

+0

यह धोखाधड़ी है, इसे इस तरह से नहीं कर सकता [और निश्चित रूप से मैं ...] लेकिन धन्यवाद, सामान्य परिस्थितियों में जो – Kawarazu

+0

काम करेगा, यह धोखाधड़ी कैसे करेगा? – BCS

+4

कंपाइलर से पूछना धोखा दे रहा है लेकिन StackOverflow पूछना नहीं है? –

-1

मैं तुम्हें दांव लगा रहा हूँ 'है एक छात्र फिर से देखें, तो देखें कि क्या आप यह काम कर सकते हैं: इसे शब्द से शब्द करें, और बिट बदलावों का उपयोग करें। सबसे कुशल समाधान सोचो। साइन बिट से सावधान रहें।

+0

आप वास्तव में सही हैं, और मेरी इच्छा है कि मेरे पास ऐसा करने का समय हो - अगली बार मैं निश्चित रूप से इस बारे में अधिक बुद्धिमान होगा और इस असाइनमेंट के बारे में सोचने के लिए सही समय निकाल दूंगा – Kawarazu

+0

अंत में, बिट बदलाव नहीं होंगे गुणा निर्देशों से अधिक कुशल बनें - कम से कम x86 पर नहीं और 32-बिट मानों के साथ नहीं। प्रोसेसर गुणा करने के लिए क्या करता है इसकी मूल बातें सीखने के लिए हालांकि यह एक अच्छा अभ्यास है। –

+0

-1: मैं एक छात्र नहीं हूं, और यह मेरे लिए एक उपयोगी जवाब नहीं है। यह ओपी पर एक टिप्पणी होनी चाहिए थी। –

2

यदि यह 64x86 था,

function(x, y, *lower, *higher) 
movq %rx,%rax  #Store x into %rax 
mulq %y   #multiplies %y to %rax 
#mulq stores high and low values into rax and rdx. 
movq %rax,(%r8) #Move low into &lower 
movq %rdx,(%r9) #Move high answer into &higher 
1

इस कोड को समझती है कि आप 86 चाहते हैं (नहीं 64 कोड), कि आप शायद ही एक 64 बिट उत्पाद चाहते हैं, और आप अतिप्रवाह या हस्ताक्षर किए संख्या के बारे में परवाह नहीं है कि । (एक हस्ताक्षरित संस्करण समान है)।

MUL64_MEMORY: 
    mov edi, val1high 
    mov esi, val1low 
    mov ecx, val2high 
    mov ebx, val2low 
MUL64_EDIESI_ECXEBX: 
    mov eax, edi 
    mul ebx 
    xch eax, ebx ; partial product top 32 bits 
    mul esi 
    xch esi, eax ; partial product lower 32 bits 
    add ebx, edx 
    mul ecx 
    add ebx, eax ; final upper 32 bits 
; answer here in EBX:ESI 

इस ओपी की सटीक रजिस्टर बाधाओं का सम्मान नहीं करता है, लेकिन परिणाम 86 द्वारा की पेशकश की रजिस्टरों में पूरी तरह से फिट बैठता है। (यह कोड अवांछित है, लेकिन मुझे लगता है कि यह सही है)।

[नोट: मैंने इस उत्तर को दूसरे प्रश्न से स्थानांतरित कर दिया है, क्योंकि बंद हो गया है, क्योंकि अन्य "उत्तरों" में से कोई भी सीधे प्रश्न का उत्तर नहीं देता है]।

+0

आधा 'add' से कैर-आउट को संभालने के लिए, आपको' adc' की आवश्यकता होगी। –

+0

@ पीटरकॉर्डस: क्या आप निश्चित हैं? निचले 32 बिट्स से "कैरी" एडैक्स में 32 बिट्स "ईबीएक्स एडक्स" निर्देश पर है। –

+0

ओह ठीक है, हम केवल 64x64 => 64 बिट्स कर रहे हैं, और परिणाम के निम्न 32 बिट्स को 'lo1 * lo2' => 64 बिट्स के निम्न आधे से पूरी तरह से निर्धारित किया गया है, जिसमें कोई अतिरिक्त नहीं है जो उच्च में ले जा सकता है 'lo1 * hi2' => 32 बिट्स और' lo2 * hi1' => 32 बिट्स का आधा परिणाम। तो उन अंतिम 2 को 'xchg' और' mul' के बजाय 2-ऑपरेंड 'imul ecx, esi'/'imul edi, ebx' के साथ किया जा सकता है, क्योंकि आप केवल 64-बिट परिणाम चाहते हैं, 96 या 128 नहीं। –

-3

आप 128 मोड इस कोशिश चाहते हैं ...

__uint128_t AES::XMULTX(__uint128_t TA,__uint128_t TB) 
{ 
    union 
    { 
     __uint128_t WHOLE; 
     struct 
     { 
      unsigned long long int LWORDS[2]; 
     } SPLIT; 
    } KEY; 
    register unsigned long long int __XRBX,__XRCX,__XRSI,__XRDI; 
    __uint128_t RESULT; 

    KEY.WHOLE=TA; 
    __XRSI=KEY.SPLIT.LWORDS[0]; 
    __XRDI=KEY.SPLIT.LWORDS[1]; 
    KEY.WHOLE=TB; 
    __XRBX=KEY.SPLIT.LWORDS[0]; 
    __XRCX=KEY.SPLIT.LWORDS[1]; 
    __asm__ __volatile__(
       "movq   %0,    %%rsi   \n\t"  
       "movq   %1,    %%rdi   \n\t" 
       "movq   %2,    %%rbx   \n\t" 
       "movq   %3,    %%rcx   \n\t" 
       "movq   %%rdi,   %%rax   \n\t" 
       "mulq   %%rbx       \n\t" 
       "xchgq   %%rbx,   %%rax   \n\t" 
       "mulq   %%rsi       \n\t" 
       "xchgq   %%rax,   %%rsi   \n\t" 
       "addq   %%rdx,   %%rbx   \n\t" 
       "mulq   %%rcx       \n\t" 
       "addq   %%rax,   %%rbx   \n\t" 
       "movq   %%rsi,   %0    \n\t" 
       "movq   %%rbx,   %1    \n\t" 
       : "=m" (__XRSI), "=m" (__XRBX) 
       : "m" (__XRSI), "m" (__XRDI), "m" (__XRBX), "m" (__XRCX) 
       : "rax","rbx","rcx","rdx","rsi","rdi" 
       ); 
    KEY.SPLIT.LWORDS[0]=__XRSI; 
    KEY.SPLIT.LWORDS[1]=__XRBX; 
    RESULT=KEY.WHOLE; 
    return RESULT; 
} 
+1

यदि आवश्यक हो तो जीसीसी लोड करने की बजाए, आपको इनपुट और आउटपुट को मेमोरी में क्यों होना चाहिए? आप '__uint128_t' का उपयोग करके और जीसीसी को ऐसा करने से बेहतर एएसएम प्राप्त करेंगे। इसके अलावा, यह बहुत ही ईरा बैक्सटर के जवाब की प्रतिलिपि बनाता है। यदि यह * अच्छा * इनलाइन एएसएम था, तो यह एक उपयोगी जोड़ हो सकता है, लेकिन ऐसा नहीं है। बहुत से निश्चित रजिस्टरों का उपयोग करना, और मेमोरी ऑपरेंड की आवश्यकता इष्टतम के पास कहीं भी नहीं है। आपको 2 इनपुट और 2 आउटपुट के साथ दो अलग 'एएसएम' कथनों का उपयोग करके 64x64 -> 128 'mul' निर्देशों को छोड़कर जीसीसी को सबकुछ संभालना चाहिए। और यह 'अस्थिर' –

+0

नहीं होना चाहिए क्योंकि मैं असेंबलर में सी को इंटरफेस कर रहा हूं और मेरे पास जीसीसी का उपयोग करने वाले libs के लिए स्रोत कोड नहीं है और मैं विस्थापन का उपयोग नहीं करना चाहता क्योंकि यह उत्तर को खराब कर देगा। मैं देख रहा हूं और मैं कोड के एक टुकड़े को तेज़ करना चाहता हूं जो एन^पी मॉड एन ओके उठाता है। – user80998

+0

आपको 'asm ("mulq% [src]": "= a" (lo64_result), "= d" (hi64_result): "a" (KEY.SPLIT.LWORDS [1]), [src] जैसे कोड का उपयोग करना चाहिए ] "आरएम" (KEY.SPLIT.LWORDS [0])); और फिर दूसरे गुणा के लिए एक दूसरा समान ASM कथन। जीसीसी सभी 'mov' निर्देशों को करेगा। आप बस इसे बताएं कि चीजें कहाँ होनी चाहिए, और परिणाम कहां दिखाई देंगे। जीसीसी लाइब्रेरी कोड के स्रोत के पास कुछ भी करने के लिए कुछ भी नहीं है, और न ही स्मृति विस्थापन। इनलाइन एएसएम लिखने के बारे में लिंक के लिए [टैग: x86] टैग विकी देखें जो भयानक नहीं है। यह संकलित करता है: http://goo.gl/izSfMi –

-2

आप 128 बिट गुणा चाहते हैं तो इस काम करना चाहिए इस पर & टी प्रारूप में है।

__uint128_t FASTMUL128(const __uint128_t TA,const __uint128_t TB) 
{ 
    union 
    { 
     __uint128_t WHOLE; 
     struct 
     { 
      unsigned long long int LWORDS[2]; 
     } SPLIT; 
    } KEY; 
    register unsigned long long int __RAX,__RDX,__RSI,__RDI; 
    __uint128_t RESULT; 

KEY.WHOLE=TA; 
__RAX=KEY.SPLIT.LWORDS[0]; 
__RDX=KEY.SPLIT.LWORDS[1]; 
KEY.WHOLE=TB; 
__RSI=KEY.SPLIT.LWORDS[0]; 
__RDI=KEY.SPLIT.LWORDS[1]; 
__asm__ __volatile__(
    "movq   %0,        %%rax     \n\t" 
    "movq   %1,        %%rdx     \n\t" 
    "movq   %2,        %%rsi     \n\t" 
    "movq   %3,        %%rdi     \n\t" 
    "movq   %%rsi,       %%rbx     \n\t" 
    "movq   %%rdi,       %%rcx     \n\t" 
    "movq   %%rax,       %%rsi     \n\t" 
    "movq   %%rdx,       %%rdi     \n\t" 
    "xorq   %%rax,       %%rax     \n\t" 
    "xorq   %%rdx,       %%rdx     \n\t" 
    "movq   %%rdi,       %%rax     \n\t" 
    "mulq   %%rbx             \n\t" 
    "xchgq   %%rbx,       %%rax     \n\t" 
    "mulq   %%rsi             \n\t" 
    "xchgq   %%rax,       %%rsi     \n\t" 
    "addq   %%rdx,       %%rbx     \n\t" 
    "mulq   %%rcx             \n\t" 
    "addq   %%rax,       %%rbx     \n\t" 
    "movq   %%rsi,       %%rax     \n\t" 
    "movq   %%rbx,       %%rdx     \n\t" 
    "movq   %%rax,       %0      \n\t" 
    "movq   %%rdx,       %1      \n\t" 
    "movq   %%rsi,       %2      \n\t" 
    "movq   %%rdi,       %3      \n\t" 
    : "=m"(__RAX),"=m"(__RDX),"=m"(__RSI),"=m"(__RDI) 
    : "m"(__RAX), "m"(__RDX), "m"(__RSI), "m"(__RDI) 
    : "rax","rbx","ecx","rdx","rsi","rdi" 
); 
KEY.SPLIT.LWORDS[0]=__RAX; 
KEY.SPLIT.LWORDS[1]=__RDX; 
RESULT=KEY.WHOLE; 
return RESULT; 
} 
+0

का उपयोग करके प्रतिलिपि नहीं बना रहा हूं यह एक ही उपयोगकर्ता के [[इस प्रश्न पर अक्षम और कठोर उत्तर] का एक repost है (https : //stackoverflow.com/a/35813111/224132)। वहां मेरी टिप्पणियां देखें। ऐसा मत करो। यदि आपके पास परिवर्तन हैं तो अपना पहला संपादित करें। –

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