دستورات ضرب و تقسيم
استفاده از دستورات ضرب و تقسيم کمی پيچيده تر از دستورات ديگر است. زيرا بسته به اندازه و نوع عملوند (بدون علامت و علامتدار) متفاوت از هم هستند. در اين دستورات يک عملوند هميشه ثبات انباشتگر (AL/AX) است.
MUL
IMUL
DIV
IDIV
MUL
دستورالعمل (multiply) mul عمل ضرب بدون علامت را انجام می دهد. فرم کلی دستور به شکل زير است:
mul src
دستور دارای يک عملوند است درحاليکه عمل ضرب به دو مقدار نياز دارد. عملوند ديگر هميشه ثبات انباشتگر (AL/AX) درنظر می گرفته می شود.
حاصل ضرب 8 بيت در 8 بيت به بيش از يک بايت و 16 بيت در 16 بيت به بيش از دو بايت احتياج دارد.
دستور ضرب بسته به اندازه تک عملوند خود به دو صورت ممکن است عمل کند:
• اگر عملوند يک بايتی باشد؛ عملوند را در AL ضرب کرده نتيجه را در AX ذخيره می کند.
AX=AL*src(8)
• اگر عملوند دوبايتی باشد؛ عملوند را در AX ضرب کرده نتيجه را در ثبات DX:AX قرار می دهد.
DX:AX=AX*src(16)
دستور mul به صورت های زير می تواند باشد:
mul register
mul memory
توجه کنيد که عملوند دستور mul نمی تواند يک داده فوری باشد.
دستور mul روی فلگ های Carry و Overflow را تاثير می گذارد. بعد از اجرای دستور اگر نيمه بالای حاصلضرب برابر با صفر باشد فلگ های Carry و Overflow صفر می شوند در غير اينصورت يک می شوند.
بقيه فلگ ها وضعيت نامعينی دارند خصوصا فلگ های Sign و Zero مقدار معنی داری ندارند. برای بررسی علامت و نتيجه صفر می توان فلگ های Carry و Overflow را بررسی کرد.
IMUL
دستور (integer multiply) imul مشابه دستور mul است با اين تفاوت که عمل ضرب علامتدار را انجام می دهد و روی عملوندهای علامتدار عمل می کند. علامت حاصل ضرب با توجه به بيت علامت عملگرها تنظيم می شود.
مثال. دستورات زير حاصل عبارت (J*7 + K) * 6 را محاسبه می کند. نتيجه در DX:AX قرار می گيرد.
mov AL,7
mov BL,J
imul BL
add AX, K
mov BX,AX
mov AX,6
imul BX
DIV
دستورالعمل (division) div برای تقسيم اعداد بدون علامت استفاده می شود. شکل کلی دستور به صورت زير است:
div src
تک عملوند دستورالعمل div مقسوم عليه تقسيم است، مقسوم بستگی به سايز عملوند يکی از دو حالت زير ممکن است باشد:
• اگر عملوند 8بيتی باشد ثبات AX بر عملوند تقسيم می شود. خارج قسمت تقسيم در AL و باقيمانده در AH قرار می گيرند.
• اگر عملوند 16بيتی باشد مقدار 32بيتی DX:AX بر عملوند تقسيم می شود. خارج قسمت تقسيم در AX و باقيمانده در DX ذخيره می شوند.
برای تقسيم بدون علامت يک عدد 8بيتی بر يک عدد 8بيتی ديگر مقسوم بايد گسترش داده شده 16 بيتی شود. برای اين کار مقسوم را در ثبات AL و مقدار صفر را در ثبات AH ذخيره کنيد. سپس دستور div را بنويسيد.
برای تقسيم بدون علامت يک عدد 16بيتی بر يک عدد 16بيتی ديگر بايد مقسوم در ثبات AX و مقدار صفر در ثبات DX ذخيره شود.
دستور div به يکی از دو صورت زير می تواند باشد. تقسيم بر عملوند فوری امکان ندارد و داده فوری بايد در يکی از ثبات ها قرار گيرد.
div register
div memory
فلگ های Carry، Auxiliary carry، Overflow، Parity، Sign و Zero نامعين هستند.
نکته. اگر مقسوم عليه صفر باشد يا خارج قسمت بزرگتر از مقصد باشد خطا اتفاق می افتد و برنامه سقط می شود. معمولا پيغام "division by zero" يا "divide error" صادر می شود.
مثال. دستورات زير حاصل عبارت J=K/M را محاسبه می کند. متغيرها 8 بيتی و بدون علامت هستند.
mov AL, K
mov AH, 0
div M
mov J, AX
IDIV
دستورالعمل (integer division) idiv مشابه دستورالعمل div است با اين تفاوت که تقسيم علامتدار را انجام می دهد.
قبل از عمل تقسيم مقدار مقسوم (AL يا AX) در صورت لزوم به طور رياضی بايد گسترش داده شوند. اينکار توسط دستورات cbw و cwd انجام می پذيرد.
مثال. دستورات زير حاصل عبارت J := (K*M)/P را محاسبه می کنند. متغيرها 16بيتی و علامتدار درنظرگرفته شده اند.
mov AX, K
imul M
idiv P
mov J, AX
جدول زير به طور خلاصه کاربرد دستورات گسترش در عمليات ضرب و تقسيم را نشان می دهد.
ضرب |
تقسيم |
mov AL, byte1 imul byte2 |
mov AX, word1 idiv byte1 |
mov AX, word1 imul word2 |
mov AL, byte1 cbw idiv byte2 |
mov AL,byte1 cbw imul word1 |
mov AX, word1 cwd idiv word2 |
برنامه محاسبه ضرب و تقسيم دو عدد صحيح علامتدار توسط دستورات اسمبلی در محيط C++ تحت ويندوز
|