دستورات شیفت يک رشته بیتی را به سمت راست يا چپ حرکت می دهند. توسط اين دستورات می توان روی بيت های داده کار کرد؛ داده را ادغام يا جدا کرد و عمليات محاسباتی را انجام داد. ريزپردازنده 8086 سه دستورالعمل شيفت (shl/sal، shr و sar) دارد. بخش زير هر يک از اين دستورالعمل ها را شرح می دهد.
SHL/SAL
SHR
SAR
کاربردهای شيفت
عمل شيفت بيت های داده را حرکت می دهد. حرکت بيت ها می تواند به سمت چپ (به سمت بيت های با ارزش) يا راست (به سمت بيت های کم ارزش) باشد. فلگ Carry معمولا آخرین بيت شیفت داده شده که از عملوند خارج می شود را می گيرد.
دو نوع شيفت وجود دارد: شيفت منطقی و شيفت رياضی. شيفت منطقی ساده ترين شيفت است که به طريق ساده ای بيت ها را شيفت می دهد. در شيفت رياضی علامت عدد حفظ می شود.
مثال. يک عدد شيفت داده شده يک بايتی نشان داده شده است.
توجه کنيد که بيت های جديدی که وارد می شوند هميشه صفر هستند.
SHL/SAL
دستورالعمل (shift left) shl يا (shift arithmetic left) sal بيت های داده را به سمت چپ حرکت می دهد. فرم کلی آنها به صورت زير است:
shl dest, count
sal dest, count
shl و sal معادل هستند و يک دستورالعمل را نشان می دهند يعنی کد يکسانی دارند. اين دستورالعمل ها هر بيت عملوند مقصد را به سمت چپ عدد به تعداد عملوند count حرکت می دهند. از سمت راست عدد 0 وارد عدد می شود و آخرين بيتی که از سمت چپ خارج می شود وارد فلگ carry می شود.
عملوند اول مقداری است که شيفت داده می شود و عملوند مقصد است. count تعداد شيفت ها را مشخص می کند و می تواند عدد 1 يا برای تعداد شيفت های بالاتر ثبات CL باشد. نوشتن تعداد شيفت بيشتر از 1 مستقيما در دستور غير مجاز است.
دستورالعمل shl/sal می تواند به صورت های زير بکار رود:
shl register, 1
shl memory, 1
shl register, CL
shl memory, CL
دستورالعمل shl/sal به صورت زير روی فلگ تاثير می گذارد:
• اگر تعداد شيفت صفر باشد فلگ ها تغييری نمی کنند.
• فلگ carry آخرين بيت خارج شده از سمت چپ عملوند را نگه می دارد.
• فلگ overflow در يک بيت شيفت يک می شود اگر دو بيت آخرعملوند متفاوت باشند. به عبارت ديگر بعد از عمل شيفت بيت علامت عدد تغيير کند. برای شيفت های بيشتر از يکبار نامعين است.
• فلگ zero، sign و parity با توجه به نتيجه تغيير می کنند.
• فلگ Auxilury Carry نامعين است.
مثال.
mov AX, 4123h
shl AX, 1 ; shift 1 bit to left, ax = 8246H, CF = 0
SHR
دستورالعمل (shift right) shr بيت های داده را به سمت راست حرکت می دهد. فرم کلی آنها به صورت زير است:
shr dest, count
دستورالعمل shr کليه بيت های عملوند مقصد را به تعداد count به سمت راست شيفت منطقی می دهد. از سمت چپ صفر وارد عملوند می شود و آخرين بيتی که از سمت راست خارج می شود وارد فلگ Carry می شود.
دستورالعمل shr مانند shl استفاده می شود؛ عملوند آن می تواند ثبات يا مکانی از حافظه باشد و تعداد شيفت ها می تواند عدد 1 يا ثبات CL باشد.
دستورالعمل shr فلگ ها را به صورت زير تنظيم می کند:
• اگر تعداد شيفت صفر باشد فلگ ها تغييری نمی کنند.
• فلگ carry آخرين بيت خارج شده از سمت راست عملوند را نگه می دارد.
• در يک بيت شيفت فلگ overflow يک می شود اگر دو بيت آخرعملوند متفاوت باشند. به عبارت ديگر اگر بعد از عمل شيفت بيت علامت عدد تغيير کند. برای شيفت های بيشتر از يکبار نامعين است.
• فلگ zero، sign و parity با توجه به نتيجه تغيير می کنند.
• فلگ Auxilury Carry نامعين است.
مثال.
mov AX, C1A5h
mov CL,3
shr AX, CL ; shift 3 bit to right, ax = 1834h, CF = 1
SAR
دستورالعمل (shift arithmetic right) sar مانند دستورالعمل shr است با اين تفاوت که علامت عملوند تغيير را نمی دهد. فرم کلی آن به صورت زير است:
sar dest, count
اين شيفت برای اعداد علامتدار طراحی شده است و بيت های عملوند مقصد را به سمت راست شيفت رياضی می دهد و بيت علامت را در خودش کپی می کند.
دستورالعمل sar مشابه دستورالعمل shr بکار می رود و به همان صورت روی فلگ ها تاثير می گذارد.
مثال.
mov AX, C1A5h
sar AX, 1 ; shift 1 bit to right, ax = E0D2h, CF = 1
کاربردهای شيفت
مثال. فرض کنيد می خواهيد دو نيبل پائينی ثبات های AL و AH را با هم به صورت زير ترکيب کنيد. کد زير اين کار را انجام می دهد.
mov CL, 4
shl AH, CL
and AL, 0Fh
or AL, AH
مثال. فرض کنيد می خواهيد دو نيبل ثبات AL را از هم جدا کرده و نيمه سمت چپ را در ثبات AH و نيمه سمت راست را در ثبات AL به صورت زير قرار دهيد. کدهای زير اين عمل را انجام می دهد.
mov AH, AL
mov CL, 4
shr AH, CL
and AL, 0Fh
مثال. هر شيفت به چپ باعث دو برابر شدن عملوند می شود که سرعت بيشتری نسبت به عمل mul دارد. دستورالعمل های shl/sal برای ضرب مقادير علامت دار يا بدون علامت در توان های 2 استفاده می شود. دستور زير مقدار ثبات AX را در عدد 4 ضرب می کند.
mov CL,2
shl AX, CL
مثال. برای محاسبه 10×AX می توانيد به روش زير از دستورشيفت چپ استفاده کنيد (با توجه به اينکه 10×AX=8×AX + 2×AX).
shl AX, 1
mov BX, AX
shl AX, 1
shl AX, 1
add AX, BX
مثال. کدهای زير حاصلضرب AX×7 را محاسبه می کنند (با توجه به اينکه ax×7 = (ax×8)-ax ).
mov BX, AX
shl AX, 1
shl AX, 1
shl AX, 1
sub AX, BX
مثال. چون يک شيفت منطقی به سمت راست مقدار يک عدد صحيح بدون علامت را نصف می کند می توان برای تقسيم بر توان های 2 از آن استفاده کرد. دستورات زير خارج قسمت مقدار ثبات AX بر 8 را محاسبه می کنند.
mov CL,3
shr AX, CL
مثال. برای انجام تقسيم علامتدار بر توان های 2 از شيفت رياضی راست استفاده می شود. دستور زير مقدار ثبات AX را بر عدد 32 تقسيم می کند.
mov CL,5
sar AX, CL
مثال. توجه کنيد اگر عملوند منفی باشد نتيجه دو دستور sar و idiv متفاوت می شود. به دستورات زير دقت کنيد.
mov ax, -15
cwd
mov bx, 2
idiv ;خارج قسمت 7- مي شود
mov ax, -15
sar ax, 1 ;خارج قسمت 8- مي شود
مثال. از شيفت رياضی راست می توانيد برای گسترش رياضی یک عدد علامتدار استفاده کنيد. به کدهای زير دقت کنيد.
; CBW معادل دستور:
mov AH, AL
mov CL, 7
sar AH, CL
; CWD معادل دستور:
mov DX, AX
mov CL, 15
sar DX, CL
البته وقتی يک دستور cbw يا cwd برای گسترش وجود دارد کسی از دو دستور استفاده نمی کند، ولی دستور شيفت اجازه می دهد که مقدار يک ثبات را در هر ثبات ديگرهم اندازه ای به طور رياضی گسترش دهيد:
; DX:BX به BX گسترش رياضی:
mov DX, BX
mov CL, 15
sar DX, CL