विधानसभा में x / 2 + 100 * (a + b) - 3 / (c + d) + e * e
इसके लिए एक एल्गोरिथ्म लिखें: 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
क्या मैंने इसे अनावश्यक रूप से जटिल बना दिया है?
जवाब
इसके लिए एक एल्गोरिथ्म लिखें: 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]"