|
แอสสิมบลีมาแล้วจ้าเพื่อนๆพี่ๆน้องๆ
โพสต์เมื่อ:
10:54 วันที่ 18 ก.พ. 2549 ชมแล้ว:
3,189
ตอบแล้ว:
39
แอสสิมบลีมาแล้วจ้า เขียนง่าย สบายๆเนื้อหาไม่หนัก ตามแบบฉบับคนเพิ่งเรียนนะเจ้าเอ๋ย
อาทิตย์เดียวเอง ลองอ่านดูกันนะเจ้าคะ จำนวน 25 ความเห็น, หน้า่ | -1- 2| ความเห็นเพิ่มเติมที่ 1 18 ก.พ. 2549 (10:56) ความเป็นมาของภาษาแอสสิมบลี คำสั่งที่เราสั่งเรียกว่าภาษาคน เครื่องเข้าใจในรูปของภาษาเครื่อง คือไบนารีหรือสถานะไฟฟ้าแบบดิจิตอลคือเปิดกับปิด เช่น 0100 0011 1000 0001 เป็นการย้ายข้อมูล 81H ไปเก็บที่รีจิสเตอร์ที่ชื่อว่า A1 ต่อไปเราจะมาพูดถึงเรื่องของโปรแกรมภาษาเครื่องกันบ้าง ถ้าเราจะเทียบ สามารถเทียบได้ว่า opcode(คำสั่งหนึ่ง) = ประโยคหนึ่งๆ ถ้าเรานำ opcode หรือประโยคนั้นๆมาเรียงต่อกันเรียกว่า program นั่นเอง จากตัวอย่างที่พูดไปจะเห็นได้ว่า การใช้ภาษาเครื่อง มีปัญหาในทางปฏิบัติ เพราะต้องจำว่ารหัสอะไรมีความหมายอะไรอีกทั้งยากต่อการตรวจสอบหรือแก้ไขโปรแกรมที่ป้อนเข้าไปว่ามีที่ผิดตรงไหนบ้าง รวมทั้งการอ่านและเขียนมีโอกาสผิดพลาดมาก ในระยะต่อมาได้มีแนวคิดที่จะทำให้การอ่านรหัสข้อมูลเหล่านี้ง่ายขึ้น โดยการแทนรหัสไบนารีเหล่านี้ด้วยรหัสฐาน 16 โดยพิจารณาทีละ 4 bit จะเห็นได้ว่ารหัสฐาน 16 ตัวเดียว สามารถแทนรหัสไบนารีได้ 4 ตัวเช่น 0000 แทนค่า 0 0101 แทนค่า 5 1010 แทนค่า A หรือ 10 ในเลขฐาน 10 1111 แทนค่า F 1101 แทนค่า D 0011 แทนค่า 3 ความเห็นเพิ่มเติมที่ 2 18 ก.พ. 2549 (10:56) เหมือนเดิมน้า จัดหน้ากันเองเน้อ ความเห็นเพิ่มเติมที่ 3 18 ก.พ. 2549 (10:57) ดังนั้นโปรแกรมเลขฐาน 2 จึงสามารถเขียนในรูปรหัสฐาน 16 ได้ดังตัวอย่าง 0100 0011 ในรหัสเลขฐาน 2 = 43H ในรหัสเลขฐาน 16 รหัสฐาน 16 นี้ทำให้โปรแกรมอ่านง่าย กะทัดรัดแต่ไม่สื่อความหมายกับการทำงานเลยต้องใช้ความจำอย่างเดียวว่ารหัสใดทำงานใด หากก็ยังดีกว่าการใช้รหัสฐาน 2 ที่มีโอกาสผิดพลาดได้มากกว่า ดังนั้นจึงมีการคิดคำย่อสั้นๆที่เรียกว่ารหัสนีโมนิค ซึ่งเกิดจากการพยาสยามในการลดรูปคำสั่งภาษามนุษย์ให้สั้นกระชับแต่สื่อความหมายได้ง่าย รูปแบบของการเขียนไม่เยิ่นเย่อเกินไป ภาษาชนิดนี้หากคิดเป็น level แล้วเรียกว่าภาษาระดับต่ำ หรือภาษาแอสสิมบลีนั่นเอง เช่น คำสั่ง INC A1 มาจาก INCrease register A1 with 1 หรือ คำสั่ง MOV A1A2 มาจาก MOVe data from register A1 to A2 หรือ คำสั่ง CPA ที่มาจาก ComPlement register A นั่นเอง ความเห็นเพิ่มเติมที่ 4 18 ก.พ. 2549 (10:57) ภาษาแอสสิมบลีจะแตกต่างไปตามเครื่องต่างๆ ซึ่งผู้ผลิตไมโครโปรเซสเซอร์แต่ละเบอร์มักใช้คำสั่งที่แตกต่างกันออกไป ปัญหา : 1. ยากต่อการทำความเข้าใจ เพราะเหตุผล 2 ข้อ 1. คือการใช้คำย่อ เช่น Substance ใช้ว่า Sub บางท่านอาจคิดว่า Subroutine ได้ 2. ก็คือในรูปแบบการเขียนแอสสิมบลีนั้น แม่จะใช้ซูโดโคด หรือโฟลว์ชาตเดียวกันก็มีรูปแบบการเขียนไม่เหมือนกับภาษา C หรือภาษาชั้นสูงทั่วไป 2. ต้องใช้ผู้เขียนที่ทราบถึงรายละเอียดการทำงานของเครื่องคอมพิวเตอร์เป็นอย่างดีและลึกซึ้ง 3. แม้จะใช้ไมโครโปรเซสเซอร์เบอร์เดียวกันก็ตาม จะนำโปรแกรมไปทำงานบนเครื่องอื่นไม่ได้ยกเว้นแต่ Computer System นั้นออกแบบมาให้มี Compatible หรือความคล้ายคลึงกันอย่างมาก และข้อ 4 4. แอสสิมบลีมีประสิทธิภาพในการ Transportable หรือเคลื่อนย้ายต่ำ ความเห็นเพิ่มเติมที่ 5 18 ก.พ. 2549 (10:58) ต่อไปจากที่เราทราบเรื่องของความเป็นมาตลอดจนปัญหาแล้วลองมาดู Source Code กันบ้างดีกว่า ภาษาแอสสิมบลีคล้ายภาษา C และทุกภาษาคือมีคำสั่งหรือฟังก์ชั่นการทำงานมากมาย วันนี้เราจะมาเรียนรู้ถึงฟังก์ชั่นหรือคำสั่งในการรับข้อมูลจากแป้นพิมพ์ค่ะ เราจะสามารถรับข้อมูลจากแป้นพิมพ์ได้โดยการ interrupt ซึ่งในการ interrupt แต่ละครั้งจะมีหมายเลขการ interrupt โดยสำหรับการรับข้อมูลจากแป้นพิมพ์จะใช้ interrupt หมายเลข 16H หรือ keyboard_IO ซึ่งท่านสามารถเลือกฟังก์ชั่นการทำงานโดยค่า AH ดังนี้ ความเห็นเพิ่มเติมที่ 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 ขึ้นก่อนจ้า |
ขอบคุณผู้สนับสนุนHot Links |
Copyright© 2000-2007, Vcharkarn.Com. All rights reserved.
|
คลิ๊กเพื่อดูสถิติ รับรองและสนับสนุนโดย |
![]() สสวท. |
![]() มูลนิธิ พสวท. |
![]() พสวท. |