|
แอสสิมบลีมาแล้วจ้าเพื่อนๆพี่ๆน้องๆ
โพสต์เมื่อ:
10:54 วันที่ 18 ก.พ. 2549 ชมแล้ว:
2,848
ตอบแล้ว:
39
แอสสิมบลีมาแล้วจ้า เขียนง่าย สบายๆเนื้อหาไม่หนัก ตามแบบฉบับคนเพิ่งเรียนนะเจ้าเอ๋ย
อาทิตย์เดียวเอง ลองอ่านดูกันนะเจ้าคะ จำนวน 25 ความเห็น, หน้า่ | 1| -2- ความเห็นเพิ่มเติมที่ 6 18 ก.พ. 2549 (10:59) ถ้า AH = 0 จะอ่านอักษรไปไว้ที่บัฟเฟอร์แป้นพิมพ์ เนื่องจากคีย์บอร์ดเป็น 1 ในอุปกรณ์ peripural หรืออุปกรณ์ต่อพ่วงภายนอกจึงต้องมีบัฟเฟอร์เพื่อใช้ในการพักข้อข้อระหว่างการติดต่อกับ CPU ถ้าหากไม่มีการกดแป้นพิมพ์ จะรอจนกว่าจะมีการกดแป้นพิมพ์ ถ้ามีการกดแป้นพิมพ์ → นำตัวอักษรนั้นในรูปของรหัส ASCII ไปไว้ที่ AL → นำ Scan code ของคีย์บอร์ดไปไว้ที่ AH โดยที่การกดแป้นพิมพ์ใดๆจะได้ค่ามา 2 ค่า คือ ASCII Code มีค่าตั้งแต่ 0 255 รวม 256 ค่าและ Scan code ใช้ในเรื่องของฟังก์ชั่นพิเศษซึ่งจะให้ค่า ASCII เป็น 00 หรือ 0 นั่นเองซึ่ง Scan Code จะบ่งบอกถึงตำแหน่งของการกดคีย์บนแป้นพิมพ์ ความเห็นเพิ่มเติมที่ 7 18 ก.พ. 2549 (10:59) ถ้า AH = 1 จะตรวจสอบบัฟเฟอร์ของแป้นพิมพ์ว่าพบตัวอักษรจากการกดครั้งนั้นหรือไม่ ถ้าไม่มีอักษร Flag ZF จะมีค่า = 1 โดยไม่รอการกดแป้นพิมพ์ ถ้ามีอักษร Flag ZF จะมีค่า = 0 และนำอักษรไปเก็บไว้ที่ AL โดยไม่นำอักษรนั้นออกจากบัฟเฟอร์แป้นพิมพ์ นำScan Code ไว้ที่ AF หากจะนำอักษรออกจากบัฟเฟอร์แป้นพิมพ์ต้องใช้ฟังก์ชั่น 0 ความเห็นเพิ่มเติมที่ 8 18 ก.พ. 2549 (11:00) ถ้า AH = 2 จะตรวจสอบการกดแป้น Shift ซึ่งสถานะการกดแป้น Shift Alt ถูกเก็บไว้ใน AL ซึ่งแสดงในรูปของละบิตของ AL Ctrl โปรแกรมตัวอย่างต่อไปนี้จะใช้ตรวจสอบการกดคีย์ A ถ้ากดให้ไปทำงานที่โปรแกรมย่อยสำหรับหาค่า 1! 9! โดยโปรแกรมจะมีฟังก์ชั่นหรือโปรแกรมย่อย 2 โปรแกรมย่อยคือ Check_Press มีคำสั่งดังนี้ ความเห็นเพิ่มเติมที่ 9 18 ก.พ. 2549 (11:01) ดูซอสโค้ด กันทีหลังนะจ๊ะ อ่านกันไปก่อนครับ ความเห็นเพิ่มเติมที่ 10 18 ก.พ. 2549 (11:01) Mov AH,1 เป็นการเช็คว่าในบัฟเฟอร์เป็น Character หรือเปล่า โดยการโยนค่า 1 ให้ AH Int 16,H เป็นการ interrupt โดยการ interrupt นั้นใช้รีจีสเตอร์เก็บค่าก่อนและหลัง interrupt เป็นชนิด I+ JNZ Check_char แสดงว่าค่า ZF = 0 JMP Check_press แสดงว่าค่า ZF = 1 และให้เช็คต่อไปอีก ต่อไปคือฟังก์ชั่น Check_A เมื่อเข้าสู่ฟังก์ชั่นจะทำงานดังนี้ Mov AH,0 ทำการรับตัวอักษรเข้ามา Int 16,H ทำการ interrupt เหมือนคราวที่แล้ว CMP AL,A ตรวจสอบว่าใช่ค่า A หรือไม่ JNE Check_press ไปทำการรับค่ามาเช็คต่อ Call FACTO ให้ไปทำงานที่สับรูทีนในการหาค่า factorial ความเห็นเพิ่มเติมที่ 11 18 ก.พ. 2549 (11:01) สับรูทีนแฟคทอเรียลเป็นโปรแกรมย่อยชนิดเรียกตัวเอง หมายถึงโปรแกรมย่อยใดๆที่ CALL โปรแกรมย่อยที่มีชื่ออเหมือนตัวมันเองเช่น สับรูทีน RP1 ในสับรูทีนนี้มีคำสั่ง CALL RP1 สับรูทีน RP1 จะถือว่าเป็นโปรแกรมย่อยชนิดเรียกตัวเอง ใช้สำหรับโปรแกรมประเภท 1. โปรแกรมวิเคราะห์การเดินหมากรุก 2. การทำงานกับโครงสร้างข้อมูล (Data Structure) แบบทรี 3. การคำนวณหาค่าแฟคทอเรียล 4. หอคอยฮานอย ความเห็นเพิ่มเติมที่ 12 18 ก.พ. 2549 (11:09) ซึ่งการออกแบบโปรแกรมต้องมีการออกแบบให้มีจุดสิ้นสุดการทำงานที่ใดที่หนึ่ง ไม่เช่นนั้นจะเรียกใช้เรื่อยไปจนกว่า Stack จะล้น เช่นกรณีโปรแกรมหาค่าแฟกทอเรียล จะมีจุดสิ้นสุดเมื่อหาค่าแฟกทอเรียลของ 1 ณ จุดนี้จะไม่มีการเรียกใช้ตนเองอีก จะได้ผลลัพธ์คือ 1 และย้อนไปทำงานโปรแกรมที่สูงกว่าที่เรียกใช้เรื่อยไป การทำงานกับคำสั่ง CALL จะทำงานคู่กับ Stack โดยแสตกจะใช้ในการเก็บตำแหน่งของ opcode ถัดไปและ Data ที่เกี่ยวกับ opcode ที่มีการ interrupt ด้วยการ CALL โปรแกรมที่จะนำเสนอจะหาค่า 1! 9! ค่าแฟกทอเรียลได้มาจากการคูณตัวเลขจำเป็นต้องเป็น I และมี Signed bit เป็น + เข้ากับค่าของแฟกทอเรียลที่น้อยกว่า และ แฟกฯของ 1 ซึ่งก็คือ 1 การเขียนโปรแกรมย่อยสำหรับค่า N! ซึง N เป็น I+ และอยู่ในช่วงเปิด 1 9 ความเห็นเพิ่มเติมที่ 13 18 ก.พ. 2549 (11:09) ใช้วิธีส่งค่าพารามิเตอร์ผ่าน Stack ค่าของ N! ก็จะถูกส่งผ่าน Stack เช่นกัน โดยมีอัลกอริทึ่มดังนี้ If N = 1 Then factorial = 1 Else factorial = N * (factorial of N 1) โดยที่ N เป็น I+ และ factorial เป็นตัวแปรใดๆ ถ้า N = 1 ค่าแฟกทอเรียล = 1 ถ้า N !=1 ค่าแฟกทอเรียล = การคูณ N เข้ากับ factorial ของ N 1 ความเห็นเพิ่มเติมที่ 14 18 ก.พ. 2549 (11:09) โดยโปรแกรมย่อยที่เรียกมานี้จะเป็นโปรแกรมย่อายสำหรับค่าแฟกทอเรียลของเลข 1 9 โดยไม่ได้ตรวจสอบความผิดพลาดเมื่อใส่ตัวเลขเกิน โปรแกรมในตอนต้นจะกำหนดค่าต่างๆให้พร้อมสำหรับการทำงาน เช่น การกำหนดค่ารีจีสเตอร์ SS และให้ขนาด 200 ตำแหน่ง(เวิร์ด) ตำแหน่งแสต็กที่สูงที่สุดชื่อ STACK_TOP ส่วนการปรับค่าของ SP คือ Sub sp,04 คือการเลื่อน SP ลง 2 ตำแหน่ง เพื่อกันที่ไว้สำหรับเก็บค่าแฟกทอเรียลที่จะส่งกลับโปรแกรมหลัก ความเห็นเพิ่มเติมที่ 15 18 ก.พ. 2549 (11:10) โปรแกรมหลักต้องนำค่าที่ต้องการแฟกทอเรียลไปไว้ที่ AX แล้วเก็บลง Stack แล้วเรียกใช้โปรแกรมย่อยซึ่งมีชื่อว่า FACTO ซึ่งเป็นโปรแกรมย่อยแบบ NEAR คือ NEAR Memory โปรแกรมย่อยนี้เริ่มต้นด้วยการรักษาค่าของรีจิสเตอร์ที่ใช้ในโปรแกรมย่อยไปไว้ที่แสต็กก่อน พิจารณาจากภาพที่กลุ่มของท่านได้จะเห็นว่าตำแหน่งของ N อยู่สูงขึ้นไปอีก 10 ตำแหน่งจากที่ SP อยู่ ในโปรแกรมต้องการให้ BP ชี้ตำแหน่งของ N จึงต้องนำค่าของ SP มาใส่ B ดังนั้นตอนนี้ BP ก็จะระบุตำแหน่งบนสุดของแสต็กด้วยคำสั่ง MOV BP,SP แล้วอ้างถึงตำแหน่งที่ [BP + 10] เพื่ออ้างถึงตำแหน่ง N โดยใช้คำสั่ง MOV AX , [BP + 10] จากนั้น MOV WORD PTR [BP + 12] , 0001H และ MOV WORD PTR [BP + 14] , 0000H เพื่อให้ได้ผลลัพธ์ไปใส่ในแสต็ก ในตอนนี้ N เป็น 3 หรือ AX = 0003H นั่นเอง ต่อไป CMP AX , 0001H ตรวจสอบว่าค่าเป็น 1 หรือเปล่า และ JNE GO_ON ซึ่งทำให้กระโดดไปที่ GO_ON ทำคำสั่ง SUB SP , 04H ความเห็นเพิ่มเติมที่ 16 18 ก.พ. 2549 (11:11) เนื่องจากการหาค่าของ N! จะต้องรู้ค่าของ N-1! คำสั่งนี้จะลดค่าของ SP ลง 4 ตำแหน่ง เพื่อไว้เป็นที่เก็บข้อมูลของ N-1! หรือ (3-1!) แล้วลดค่าของ N ลง 1 เก็บค่าของ N-1 ไว้ในแสต็กให้โปรแกรมย่อย FACTO สามารถใช้ได้ เมื่อมีการเรียกใช้ FACTO อีกครั้งจะเป็นการหาค่าของ (N 1) ค่าของ N 1 จะห่างจาก BP 10 ตำแหน่งเหมือนที่เคยเป็นมาและสามารถอ้างถึงตำแหน่งนี้ได้ด้วยคำสั่ง MOV SP,BP และ MOV AX ,[BP+10] ถึงตอนนี้ตำแหน่ง [BP + 10] มีค่า = 2 ทำให้ CMP AX , 0001H และ JNE GO_ON จะกระโดดไปทำงานที่ GO_ON ทำคำสั่ง GO_ON : SUB SP,04 ความเห็นเพิ่มเติมที่ 17 18 ก.พ. 2549 (11:12) ขอโทษนะ จริงๆเรื่องแสตกอ่ะ มันมีตาราง แต่พอโพสต์แล้ว มันอ่านไม่ออกเลย ใช้จินตนาการก็แล้วกันนะ ความเห็นเพิ่มเติมที่ 18 18 ก.พ. 2549 (11:16) อินเทอรรัปนิดหนึ่ง ใครสนใจหอคอยฮานอยเชิญที่นี่ค่ะ http://www.vcharkarn.com/include/vcafe/showkratoo.php?Cid=108&Pid=35777 ส่วนนี่ของคุณ sigma โพสต์ไว้ http://www.vcharkarn.com/include/vcafe/showkratoo.php?Cid=105&Pid=16689 ลองทำเล่นดูนะคะ สนุกดี ความเห็นเพิ่มเติมที่ 19 18 ก.พ. 2549 (11:16) เพื่อเลื่อตัวชี้แสต็กลงมา 4 ตำหน่งสำหรับเก็บค่าของ (N 1) คือ (2-1)! และลดค่าของ N ลง 1 ตอนนี้ N มีค่าเป็น 1 แล้วเรียกใช้ FACTO อีกครั้ง หลังจากเก็บค่ารีจีสเตอร์ทั้งหมดแล้ว FACTO จะอ่านค่าของ N จากแสต็กอีกด้วย คำสั่งต่อไปเป็นคำสั่ง MOV AX , [BP + 10] ซึ่งคราวนี้ข้อมูลที่ถูกส่งมาคือ 1 เมื่อใช้คำสั่ง CMP AX , 0001H และเจอคำสั่ง JNE GO_ON ก็จะไม่กระโดดไป GO_ON แต่จะมาทำคำสั่งต่อไปนี้แทน MOV WORD PTR [BP + 12] , 0001H MOV WORD PTR [BP + 12] , 0001H นั่นคือใส่ค่า 1 ลงในแสต็ก ที่ตำแหน่งที่ใช้สำหรับเก็บค่าแฟกทอรียลของ 1 นั่นเอง และก็จบการทำงาน ความเห็นเพิ่มเติมที่ 20 18 ก.พ. 2549 (11:18) จบแล้วคร้าบ ต่อไปเป็น ซอสโค้ดล้วนๆ โดยเอาโปรแกรมเช็ค A ขึ้นก่อนจ้า ความเห็นเพิ่มเติมที่ 21 18 ก.พ. 2549 (11:29) CHECK_PRESS : MOV AH,1 ; check for char in buffer 1 tab ให้ตรงกับ Mov นะจ้ะ INT 16H ;GOTO KEYBOARD_IO tab เหมือนกันจ้ะ JNZ CHECK_CHAR ;ZF = 0 CHAR PRESENT tab JMP CHECK_PRESS ;ZF = 1 CONTINUE CHECK ขึ้นลาเบลใหม่ CHECK_A : MOV AH,0 ; get the character 1 tab ให้ตรงกับ Mov นะจ้ะ INT 16H ;GOTO KEYBOARD_IO tab เหมือนกันจ้ะ CMP AL,'A' ; is it ' a' Tab อีกที JNE CHECK_PRESS ; No continue check และบรรทัดสุดท้าย CALL FACTO ; yes do factorail ความเห็นเพิ่มเติมที่ 22 18 ก.พ. 2549 (11:30) ต่อไปนี้จะไม่บอก tab แล้วนะ เอาเป็นว่า ถ้าเยื่องบรรทัดเข้าไป แปลว่า tab ละกัน ความเห็นเพิ่มเติมที่ 23 18 ก.พ. 2549 (11:38) ; 8086 Program to find the factorail of a number between 1 - 9 ;PROCEDURE : FACTO STACK_HERBSEGMENT STACK DW 200 DUP(0) ;set aside 200 word for stack STACK_TOP LABEL WORD ; assign name to word above stack STACK_HERBENDS NUMBER EQU 03 CODE_HERE SEGMENT ความเห็นเพิ่มเติมที่ 24 18 ก.พ. 2549 (11:40) ; 8086 Program to find the factorail of a number between 1 - 9 ;PROCEDURE : FACTO STACK_HERBSEGMENT STACK DW 200 DUP(0) ;set aside 200 word for stack STACK_TOP LABEL WORD ; assign name to word above stack STACK_HERBENDS NUMBER EQU 03 CODE_HERE SEGMENT ความเห็นเพิ่มเติมที่ 25 12 มี.ค. 2549 (17:45) ผมข้อ ฝากตัวด้วยนะ ครับ มีอะไร มาแลก เปลียน กัน ผม เองไม่ได้เรียน ด้านนี้เลย แต่ คอมพิวเตอร์คือชีวิตผม ผมชอบ ผมชอบภาษานี้มาก จากที่ ศึกษา เอาไว้หาเงินได้ เมื่อก่อนผมเองรับจ้าง Crack โปรแกรมก็ ต้องใช่ภาษานี้ ดีแล้ว ที่เอามาฝากกัน ผมติ๊ก แล้วคุณๆ ละ change_love@hotmail.com (IP:203.118.88.10,10.128.220.249,) |