विधानसभा में x / 2 + 100 * (a + b) - 3 / (c + d) + e * e

Oct 21 2020

इसके लिए एक एल्गोरिथ्म लिखें: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e यह जानकर कि: a, c - word, b, d - byte, e - doubleword, x - qword

    mov eax, dword [x]
    mov edx, dword [x + 4] ; edx:eax = x
    mov ebx, 2
    idiv ebx ; eax = edx:eax / ebx = x / 2
    mov ebx, eax ; save the result in ebx so we can do the other operations
    mov al, [b]
    cbw ; ax = b
    add ax, [a] ; ax = a + b
    mov dx, 100
    imul dx ; dx:ax = ax * dx = 100 * (a + b)
    push dx
    push ax
    pop eax ; 100 * (a + b)
    add ebx, eax ; ebx = x / 2 + 100 * (a + b)
    mov al, [d] ; al = d
    cbw ; ax = d
    add ax, word [c] ; ax = c + d
    mov cx, ax ; cx = c + d
    mov ax, 3
    cwd
    idiv cx ; ax = dx:ax / cx 
    cwd
    push dx
    push ax
    pop eax ; eax = 3 / (c + d)
    sub ebx, eax
    mov eax, ebx
    cdq ; edx:eax = x / 2 + 100 * (a + b) - 3 / (c + d)
    mov ebx, eax
    mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)
    mov eax, [e]
    imul dword [e] ; edx:eax = e * e
    add eax, ebx
    adc edx, ecx
    mov dword [result + 0], eax 
    mov dword [result + 4], edx

क्या मैंने इसे अनावश्यक रूप से जटिल बना दिया है?

जवाब

6 SepRoland Oct 22 2020 at 03:52

इसके लिए एक एल्गोरिथ्म लिखें: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e

a, c - word,
b, d - byte,
e - doubleword,
x - qword

क्योंकि आपकी सबसे बड़ी संख्या 64 बिट्स है ( x एक qword है), आपके अंतिम परिणाम के लिए 64 बिट्स भी होंगे!

आपका पहला ऑपरेशन 2 से qword को x में विभाजित करना था । आप उम्मीद करते हैं कि यह परिणाम सिर्फ एक ही ड्राफ्ट में फिट होगा क्योंकि आपने EBXरजिस्टर में भागफल को स्थानांतरित कर दिया है । आप इस धारणा को नहीं बना सकते हैं और यदि विभाजन 32 बिट्स में फिट नहीं होता है तो विभाजन आसानी से एक विभाजन अपवाद पैदा कर सकता है।
समाधान के लिए आपको पता होना चाहिए कि 2 से विभाजित करना वास्तव में दाईं ओर एक बदलाव है।

mov   ebx, [x]
mov   ebp, [x + 4] ; EBP:EBX is x
sar   ebp, 1
rcr   ebx, 1       ; EBP:EBX is x / 2

इसका मतलब है कि आपको अन्य गणनाओं को भी स्केल करना होगा ताकि उन्हें EBP:EBXउपयोग करने के लिए जोड़ा जा सके :

add   ebx, ...
adc   ebp, ...

क्योंकि जोड़ सहयोगी है, आप ई * ई भाग की गणना करके शुरू कर सकते हैं । आपने अभिव्यक्ति को पुनर्व्यवस्थित नहीं किया और अंत में कुछ और रजिस्टरों के लिए आगे बढ़ना पड़ा। कोई बड़ी बात नहीं है, लेकिन मेरा तरीका अच्छा है:

mov   eax, [e]
imul  eax
add   ebx, eax
adc   ebp, edx

फिर 100 * (ए + बी) आता है :

movsx eax, word [a]
movsx edx, byte [b]
add   eax, edx       ; eax = a + b
mov   edx, 100
imul  edx            ; edx:eax = 100 * (a + b)
add   ebx, eax
adc   ebp, edx

मैं आपके लिए 3 / (c + d) छोड़ूंगा ...

... और अंत में होगा अंत:

sub   ebx, eax
sbb   ebp, edx
mov   [result + 0], ebx 
mov   [result + 4], ebp

क्या मैंने इसे अनावश्यक रूप से जटिल बना दिया है?

  • अपने कार्यक्रम को पढ़ना थोड़ा कठिन था क्योंकि आपने विभिन्न कार्यों के बीच कुछ रिक्त लाइनें नहीं डाली थीं।

  • यदि आपको पहले से शामिल रजिस्टर का आकार नापना है, तो आपको एक आकार टैग (बाइट, वर्ड, डॉर्ड) लिखने की आवश्यकता नहीं है। में mov dword [result + 0], eaxDWORD टैग अनावश्यक है।

  • कार्यक्रम में सबसे अच्छी टिप्पणी एक दूसरे के ऊपर गठबंधन की है।

  • टाइपो से बचने के लिए ध्यान से फिर से पढ़ना:

      mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)
    

    होना चाहिए ECX:EBX।

  • एक वर्ग की गणना करने के लिए: एक बार जब आप रजिस्टर में संख्या लोड कर लेते हैं, तो आप उसी रजिस्टर से गुणा कर सकते हैं और दूसरी बार मेमोरी में नहीं बदल सकते हैं जैसे आपने किया था:

      mov   eax, [e]
      imul  eax        ; Don't write "imul dword [e]"