260 likes | 531 Views
แฟล็กและคำสั่งคณิตศาสตร์. ธนาวินท์ รักธรรมานนท์ fengtwr@ku.ac.th. หัวข้อการเรียน. แฟล็ก คำสั่งคณิตศาสตร์ คำสั่งเกี่ยวกับการบวกและลบ คำสั่งเกี่ยวกับการคูณและหาร ผลของคำสั่งคณิตศาสตร์ต่อการเปลี่ยนแปลงของแฟล็ก การคำนวณสมการคณิตศาสตร์อย่างง่าย. แฟล็กรีจิสเตอร์.
E N D
แฟล็กและคำสั่งคณิตศาสตร์แฟล็กและคำสั่งคณิตศาสตร์ ธนาวินท์ รักธรรมานนท์ fengtwr@ku.ac.th
หัวข้อการเรียน • แฟล็ก • คำสั่งคณิตศาสตร์ • คำสั่งเกี่ยวกับการบวกและลบ • คำสั่งเกี่ยวกับการคูณและหาร • ผลของคำสั่งคณิตศาสตร์ต่อการเปลี่ยนแปลงของแฟล็ก • การคำนวณสมการคณิตศาสตร์อย่างง่าย
แฟล็กรีจิสเตอร์ • แฟล็ก คือรีจิสเตอร์ที่ใช้เก็บสถานะของระบบ • แฟล็กของ 8086 มีขนาด 16 บิต โดยแต่ละบิตจะแทนสถานะต่างๆ ของระบบ • แฟล็กจะเปลี่ยนแปลงตามผลลัพธ์ของคำสั่งทางคณิตศาสตร์ การคัดลอกข้อมูลจะไม่ทำให้แฟล็กเปลี่ยนแปลงค่า
แฟล็กรีจิสเตอร์ • แฟล็กทด (Carry flag) จะมีค่า 1 หากมีการทดบิตหรือขอยืมค่า • แฟล็กพาริตี้ (Parity flag) จะมีค่า 1 ถ้าผลลัพธ์ที่ได้จากคำสั่งคำนวณมีจำนวนบิตที่เท่ากับ 1 เป็นเลขคู่ • แฟล็กช่วย (Auxiliary flag) จะมีค่า 1 หาก 4 บิตขวามือของผลลัพธ์มีการทดหรือขอยืมค่า • แฟล็กศูนย์ (Zero flag) จะมีค่า 1 หากผลลัพธ์การคำนวณมีค่าเท่ากับศูนย์ • แฟล็กเครื่องหมาย (Sign flag) จะมีค่า 1 หากผลลัพธ์การคำนวณเป็นเลขลบ • แฟล็กกับดัก (Trap flag) หากมีค่าเป็น 1 จะบังคับให้ไมโครโปรเซสเซอร์ปฏิบัติงานใน ภาวะคำสั่งขั้นเดียว (single step) ซึ่งใช้ในการดีบักโปรแกรม • แฟล็กอินเตอร์รัพต์ (Interrupt Enable flag) หากมีค่าเป็น 1 จะทำให้ซีพียูรับการอินเตอร์รัพต์แบบมาส์ก • แฟล็กทิศทาง (Direction flag) หากมีค่าเป็น 1 จะบังคับให้คำสั่งถ่ายโอนข้อมูลเป็นกลุ่มทำงานจากแอดเดรสค่าน้อยไปหาค่ามาก หากมีค่าเป็น 0 จะบังคับมีการถ่ายโอนจากแอดเดรสค่ามากไปหาค่าน้อย • แฟล็กค่าล้นหลัก (Overflow flag) ใช้สำหรับเลขแบบคิดเครื่องหมาย หากมีค่าเป็น 1 หมายถึงผลลัพธ์ของการคำนวณเป็นเลขที่มีค่ามากหรือน้อยกว่าขอบเขตที่กำหนด
แฟล็กศูนย์ (Zero-flag) • จะมีค่าเป็น 1 เมื่อผลลัพธ์มีค่าเท่ากับศูนย์ • นอกจากกรณีนี้จะมีค่าเป็น 0 MOV AL,10h ADD AL,E0h ADD AL,20h SUB AL,10h SUB AL,10h Z=? Z=1 Z=0 Z=0 Z=1 AL=0 AL=20h AL=10h AL=0
พาริตี้แฟล็ก (Parity-flag) • จะมีค่าเป็น 1 เมื่อผลลัพธ์มีจำนวนบิตที่มีค่าเป็นหนึ่งเป็นเลขคู่ MOV AL,14h ADD AL,20h ADD AL,10h SUB AL,8h SUB AL,10h P=? P=0 P=1 P=1 P=0 AL=34h AL=44h AL=3Ch AL=2Ch
แฟล็กทด (Carry-flag) • จะมีค่าเป็น 1 เมื่อมีการทดหรือการยืมในการคำนวณ • พิจารณาตัวเลขแบบไม่คิดเครื่องหมาย MOV AL,77h ADD AL,50h ADD AL,50h SUB AL,A0h ADD AL,27h C=? C=0 C=1 C=1 C=0 AL=C7h AL=17h AL=77h AL=9Eh
แฟล็กเครื่องหมาย (Sign-flag) • จะมีค่าเป็น 1 เมื่อผลลัพธ์มีค่าลบ • พิจารณาตัวเลขแบบคิดเครื่องหมาย MOV AL,77h ADD AL,50h ADD AL,50h SUB AL,A0h ADD AL,27h S=? S=1 S=0 S=0 S=1 AL=C7h AL=17h AL=77h AL=9Eh
โอเวอร์โฟล์แฟล็ก (Overflow-flag) • จะมีค่าเป็น 1 เมื่อผลลัพธ์มีความผิดพลาดเนื่องจากเลขล้นหลัก • พิจารณาตัวเลขแบบคิดเครื่องหมาย • การล้นหลักจะเกิดขึ้นเฉพาะจำนวนบวกรวมกันหรือจำนวนลบรวมกันเท่านั้น จะไม่เกิดการล้นหลักสำหรับจำนวนบวกรวมกับจำนวนลบ MOV AL,77h ADD AL,50h ADD AL,50h SUB AL,A0h ADD AL,27h O=? O=1 O=0 O=0 O=1 AL=C7h AL=17h AL=77h AL=9Eh
แฟล็กอื่น ๆ • แฟล็กเสริม (Auxiliary-flag) • จะมีค่าเป็น 1 เมื่อผลลัพธ์ต้องมีการปรับค่าของการเก็บตัวเลขแบบ BCD • แฟล็กทิศทาง (Direction-flag) • ใช้สำหรับกำหนดทิศทางของการปรับค่าในคำสั่งเกี่ยวกับสายข้อมูล. • แทรปแฟล็ก (Trap-flag) • ใช้สำหรับการตรวจสอบการทำงานของโปรแกรม โดยจะทำให้เกิดการขัดจังหวะทุกครั้งหลังการทำงานของคำสั่งต่างๆ • อินเตอร์รัพท์แฟล็ก (Interrupt-flag) • ใช้สำหรับกำหนดว่าหน่วยประมวลผลจะตอบสนองการขัดจังหวะจากฮาร์ดแวร์บางประเภทหรือไม่
Flag Clear Set Carry-flag Direction-flag Interrupt-flag CLC CLD CLI STC STD STI คำสั่งสำหรับกำหนดค่าของแฟล็ก • แฟล็กบางแฟล็กสามารถกำหนดค่าได้ เนื่องจากมีหน้าที่ในการระบุสถานะบางประการ • เราจะเรียกแฟล็กที่มีค่าเป็น 1 ว่าแฟล็กนั้นเซ็ต (flag set) และเรียกแฟล็กที่มีค่าเป็น 0 ว่าแฟล็กนั้นเคลียร์ (flag cleared) • แฟล็กที่สามารถกำหนดค่าได้ และคำสั่งในการกำหนดค่า
คำสั่งคณิตศาสตร์ • คำสั่งเพิ่มและลดค่า : INC และ DEC • คำสั่งบวก : ADD และ ADC • คำสั่งลบ : SUB และ SBB • คำสั่งเปรียบเทียบ : CMP • คำสั่งกลับเครื่องหมาย : NEG • คำสั่งคูณ : MUL และ IMUL • คำสั่งหาร : DIV และ IDIV • คำสั่งปรับขนาดข้อมูล : CBW และ CWD
INC register INC memory DEC register DEC memory ไม่เปลี่ยน C-flag คำสั่งเพิ่มค่า INC และคำสั่งลดค่า DEC • การเพิ่มและลดค่าในหน่วยความจำจะต้องระบุขนาดของข้อมูลด้วย • มีผลกระทบกับแฟล็กทางคณิตศาสตร์ทั้งหมด ยกเว้นแฟล็กทด MOV AL,1 DEC AL DEC AL MOV BX,200h MOV [BX],AL INC BYTE PTR [BX] AL=0h AL=FFh [200h]=FFh [200h]=00h
คำสั่งการบวก ADD และ ADC (add with carry) ADD regs,regs ADD regs,mem ADD mem,regs ADD regs,imm ADD mem,imm ADC regs,regs ADC regs,mem ADC mem,regs ADC regs,imm ADC mem,imm • ผลลัพธ์ของการบวกจะเก็บไว้ในโอเปอร์แลนด์ตัวหน้าเสมอ • คำสั่ง ADD และ ADC มีผลกระทบถึงแฟล็กทางคณิตศาสตร์ทุกตัว • เรานิยมใช้คำสั่ง ADC ในการบวกเลขที่ต้องการรวมตัวทดจากการคำนวณที่ผ่านมา ยกตัวอย่างเช่น การบวกเลขที่อยู่ในรีจิสเตอร์หลายตัวต่อเนื่องกัน
คำสั่งการลบ SUB และ SBB (sub with borrow) • คำสั่ง SUB จะลบค่าในโอเปอร์แรนด์ตัวหลังออกจากตัวหน้า และนำไปเก็บในโอเปอร์แรนด์ตัวหน้า • คำสั่ง SBB ก็จะทำเช่นเดียวกัน แต่จะมีการรวมตัวยืมซึ่งเก็บอยู่ใน Carry-flag ด้วย (คล้าย ADC) • คำสั่ง SUB และ SBB มีผลกระทบถึงแฟล็กทางคณิตศาสตร์ทุกตัว SUB regs,regs SUB regs,mem SUB mem,regs SUB regs,imm SUB mem,imm SBB regs,regs SBB regs,mem SBB mem,regs SBB regs,imm SBB mem,imm
MOV AX,1115h MOV DX,34DAh ADD AX,BX ADC DX,CX SUB AL,BL SBB AH,0 ตัวอย่างการใช้คำสั่งบวกและลบ • การบวกเลข 32 บิต 34DA 1115h เข้ากับตัวเลข 32 บิตที่เก็บในคู่รีจิสเตอร์ CX,BX นำ 34DA 115h เก็บในDX,AX บวก 16 บิตล่าง บวก 16 บิตบนพร้อมตัวทด การลบเลข 16 บิต ในรีจิสเตอร์ AX ด้วยเลข 8 บิตในรีจิสเตอร์ BL ลบ 8 บิตล่าง ลบ 8 บิตบนพร้อมตัวยืม
คำสั่งเปรียบเทียบ CMP • คำสั่ง CMP จะทำงานเหมือนคำสั่ง SUB แต่จะไม่มีการเปลี่ยนแปลงค่าในโอเปอร์แรนด์ทั้งสอง แต่จะมีการเปลี่ยนแปลงค่าใน Flag • การเปลี่ยนแปลง flag ของคำสั่ง CMP จะเหมือนกับคำสั่ง SUB • โดยปกติเราจะใช้คำสั่ง CMP ในการเปรียบเทียบ และตัดสินใจ MOV AX,10h CMP AX,100h MOV BL,10h CMP AL,BL Z-flag = 0, C-flag = 1, O-flag = 0, S-flag = 1. Z-flag = 1, C-flag = 0, O-flag = 0, S-flag = 0.
คำสั่งกลับเครื่องหมาย NEG NEG regsNEG mem • คำสั่ง NEG จะกลับค่าของโอเปอร์แรนด์ให้เป็นค่าลบ • การแปลงเป็นค่าลบใช้วิธีแบบ 2’s complement • คำสั่ง NEG จะมีผลกระทบกับแฟล็กทางคณิตศาสตร์ทั้งหมด แต่สำหรับ แฟล็กทดจะมีค่าเป็นหนึ่งเสมอหลังการทำงานของคำสั่งนี้
AL=70h ? ? ? ? ? AL=90h 0 0 1 1 1 AL=00h 1 1 1 0 0 AL=FFh 0 1* 1 1 0 AL=04h 0 1 0 0 0 AL=34h 0 0 0 0 0 AL=F4h 0 1 0 1 0 AL=75h 0 0 0 0 1 AL=8Bh 0 1** 1 1 0 AL=ABh 0 0 0 1 0 ตัวอย่างการเปลี่ยนค่าแฟล็ก
คำสั่งคูณ MUL และ IMUL IMUL regs IMUL mem • ในการใช้คำสั่งคูณ เราจะระบุเฉพาะตัวคูณเท่านั้น สำหรับตัวตั้งและผลลัพธ์จะอยู่ในรีจิสเตอร์ที่กำหนดไว้แล้ว โดยจะขึ้นกับขนาดของการคูณ • การคูณ 8 บิต ตัวตั้ง : AL ผลลัพธ์ : AX • การคูณ 16 บิต ตัวตั้ง : AX ผลลัพธ์ : DX,AX • คำสั่ง MUL จะคูณแบบไม่คิดเครื่องหมาย • คำสั่ง IMUL จะคูณแบบคิดเครื่องหมาย • คำสั่งทั้งสองจะมีผลกระทบกับ แฟล็กทดและโอเวอร์โฟล์แฟล็กเท่านั้น MUL regs MUL mem
การคูณค่าในหน่วยความจำขนาด 16 บิตที่offset 200h ด้วย ค่าใน AX จากนั้นนำผลลัพธ์ที่ได้มาบวกด้วยค่าในBX MUL WORD PTR[200h] ADD AX,BX ADC DX,0 คูณ AX กับค่าใน [200h] จากนั้นนำ BX มารวมกับผลลัพธ์ ตัวอย่างการใช้คำสั่งคูณ • การคูณค่า 12h ด้วย ค่าใน BL ตั้งค่าให้กับตัวตั้ง คูณด้วย BL ผลลัพธ์อยู่ใน AX MOV AL,12h MUL BL
คำสั่งคูณ DIV และ IDIV IDIV regs IDIV mem DIV regs DIV mem • เช่นเดียวกับการใช้คำสั่งคูณ เราจะระบุเฉพาะตัวหารเท่านั้น ตัวตั้งและผลลัพธ์จะอยู่ในรีจิสเตอร์ที่กำหนดไว้แล้ว โดยจะขึ้นกับขนาดของการหาร • การหาร 8 บิต ตัวตั้ง : AX ผลลัพธ์ : AL เศษ : AH • การหาร 16 บิต ตัวตั้ง : DX, AX ผลลัพธ์ : AX เศษ : DX • คำสั่ง DIV จะหารแบบไม่คิดเครื่องหมาย • คำสั่ง IDIV จะหารแบบคิดเครื่องหมาย • คำสั่งทั้งสองจะไม่มีผลกระทบกับแฟล็กทางคณิตศาสตร์.
ตัวอย่าง การหารค่าใน AL ด้วย BL CBW IDIV BL คำสั่งปรับขนาดข้อมูล • ข้อมูลแบบไม่คิดเครื่องหมาย เราสามารถที่จะกำหนดค่า 0 ให้กับข้อมูลนัยสำคัญสูงที่ขยายเพิ่มขึ้นมาได้ เพื่อให้ขนาดใหญ่ขึ้นและมีค่าคงเดิม • แต่ถ้าข้อมูลเป็นตัวเลขคิดเครื่องหมายเราจะต้องใช้การปรับค่าแบบอื่น มิเช่นนั้นค่าอาจผิดเพี้ยนไปได้ • คำสั่ง CBW จะขยายขนาดข้อมูลแบบคิดเครื่องหมายใน AL ให้มีขนาด 16 บิตใน AX • คำสั่ง CWD จะขยายขนาดข้อมูลแบบคิดเครื่องหมายใน AX ให้มีขนาด 32 บิตใน DX,AX ขยาย AL -> AX. หารด้วย BL ผลลัพธ์อยู่ใน AL
MUL AL MOV CX, AX MOV AL, BL MUL BL ADD AX, CX ตัวอย่างการแก้สมการทางคณิตศาสตร์ 1. คำนวณค่า AL2 + BL2 คิดตัวเลขแบบไม่คิดเครื่องหมายโดยให้ผลลัพธ์เป็นเลข 16 บิต เก็บที่ รีจิสเตอร์ AX หาค่า AL*AL นำไปเก็บไว้ที่ CX เนื่องจาก AL ต้องใช้ในการคำนวณ คูณ BL กับ BL แล้วเก็บผลลัพธ์ไว้ที่ AX ได้ผลลัพธ์แล้วนำค่า AL*AL ที่เก็บใน CX มาบวก 2. คำนวณค่า (CL*BL+DX)/SI โดยคิดเป็นเลขคิดเครื่องหมาย
MOV AL,CL MUL BL ADD AX,DX CWD IDIV SI ตัวอย่างการแก้สมการทางคณิตศาสตร์ 2. คำนวณค่า (CL*BL+DX)/SI โดยคิดเป็นเลขคิดเครื่องหมาย หาค่า CL*BL บวกกับ DX. ขยายขนาดเป็น 32 บิต หารด้วย SI ผลอยู่ที่ AX เศษที่ DX