แฮ็กคอมพิวเตอร์
บทความนี้เป็นบทความโดดเดี่ยวเนื่องจากไม่มีบทความอื่นเชื่อมโยงถึงโปรดเพิ่มลิงก์ไปยังหน้านี้จากบทความ ที่เกี่ยวข้อง( มีนาคม 2569 ) |
คอมพิวเตอร์Hackเป็นการ ออกแบบ คอมพิวเตอร์ เชิงทฤษฎี ที่สร้างขึ้นโดย Noam Nisan และ Shimon Schocken และอธิบายไว้ในหนังสือของพวกเขาThe Elements of Computing Systems: Building a Modern Computer from First Principles [ 1 ]ในการใช้คำว่า “ทันสมัย” ผู้เขียนหมายถึงเครื่องจักรดิจิทัลไบนารีที่มีรูปแบบตามแบบจำลองสถาปัตยกรรมของ von Neumann
คอมพิวเตอร์ Hack มีจุดประสงค์เพื่อการสร้างเสมือนจริงแบบลงมือปฏิบัติจริงในแอปพลิเคชันจำลองฮาร์ดแวร์ ซึ่งเป็นส่วนหนึ่งของหลักสูตรพื้นฐานแต่ครอบคลุมในด้านการจัดระเบียบและสถาปัตยกรรมคอมพิวเตอร์ [ 2 ] หลักสูตรดังกล่าวซึ่งสร้างโดยผู้เขียนและนำเสนอเป็นสองส่วน สามารถเข้าถึงได้ฟรีในรูปแบบหลักสูตรออนไลน์แบบเปิดขนาดใหญ่ (MOOC) ที่ชื่อว่าสร้างคอมพิวเตอร์สมัยใหม่จากหลักการพื้นฐาน: จาก NAND ถึง Tetris [ 3 ] ในโครงการทั้งสิบสองโครงการที่รวมอยู่ในหลักสูตร ผู้เรียนจะเริ่มต้นด้วยเกต NAND สองอินพุต และจบลงด้วยคอมพิวเตอร์เสมือนจริงที่ใช้งานได้อย่างสมบูรณ์ รวมถึงทั้งฮาร์ดแวร์ (หน่วยความจำและ CPU) และซอฟต์แวร์ (แอสเซมเบลอร์, VM, ภาษาโปรแกรมคล้าย Java และระบบปฏิบัติการ) นอกจากโปรแกรมจำลองฮาร์ดแวร์ที่ใช้สำหรับการใช้งานฮาร์ดแวร์คอมพิวเตอร์ในขั้นต้นแล้ว โปรแกรมจำลองคอมพิวเตอร์ Hack ที่สมบูรณ์และแอสเซมเบลอร์ที่สนับสนุนโครงการที่อธิบายไว้ในหนังสือและหลักสูตรออนไลน์ยังมีให้ใช้งานที่เว็บไซต์ของผู้เขียนอีกด้วย[ 4 ]
สถาปัตยกรรมฮาร์ดแวร์

ฮาร์ดแวร์ของคอมพิวเตอร์ Hack ประกอบด้วยองค์ประกอบพื้นฐานสามส่วน ดังแสดงในแผนภาพบล็อก ได้แก่ หน่วย ความจำ 16 บิต สองหน่วยแยกกันและหน่วยประมวลผลกลาง (CPU) เนื่องจากข้อมูลถูกเคลื่อนย้ายและประมวลผลโดยคอมพิวเตอร์ในรูปแบบคำ 16 บิต คอมพิวเตอร์ Hack จึงถูกจัดอยู่ในประเภทสถาปัตยกรรม 16บิต
หน่วยความจำคำสั่ง (Instruction Memory) ซึ่งในมุมมองของคอมพิวเตอร์เรียกว่าหน่วยความจำแบบอ่านอย่างเดียว (Read-Only Memory หรือ ROM) จะเก็บรหัสโปรแกรมไบนารีที่ประกอบเสร็จแล้วเพื่อรอการประมวลผล หน่วยความจำ เข้าถึงแบบสุ่ม (Random Access Memory หรือ RAM) ทำหน้าที่จัดเก็บข้อมูลของโปรแกรมที่กำลังทำงานอยู่ และให้บริการและพื้นที่จัดเก็บข้อมูลสำหรับกลไกการรับส่งข้อมูลแบบแมปหน่วยความ จำ (Memory-Mapped I/O mechanism) ของคอมพิวเตอร์การประมวลผลข้อมูลและการจัดการควบคุมโปรแกรมจะดำเนินการโดย CPU
หน่วยทั้งสามเชื่อมต่อกันด้วยบัสแบบขนาน บัสแอดเดรส (15 บิต) รวมถึงบัสข้อมูลและบัสคำสั่ง (16 บิต) สำหรับหน่วย ROM และ RAM นั้นเป็นอิสระต่อกันอย่างสมบูรณ์ ดังนั้น การออกแบบของ Hack จึงเป็นไปตาม แบบจำลอง สถาปัตยกรรม Harvardในส่วนของการสื่อสารผ่านบัสระหว่างหน่วยความจำและ CPU หน่วยความจำทั้งหมดสามารถเข้าถึงได้ด้วยแอดเดรส แบบเวิร์ด เท่านั้น
หน่วยความจำอ่านอย่างเดียว (ROM)
โมดูล ROM ของคอมพิวเตอร์ Hack ถูกนำเสนอในรูปแบบของอาร์เรย์เชิงเส้นของรีจิสเตอร์หน่วยความจำ 16 บิตแบบเรียง ลำดับ ที่สามารถเข้าถึง แต่ละแอดเดรสได้ โดยแอดเดรสเริ่มต้นที่ 0 ( 0x0000 ) เนื่องจากองค์ประกอบหน่วยความจำเป็นอุปกรณ์แบบเรียงลำดับสัญญาณนาฬิกา ระบบ จึงถูกส่งมาจากแอปพลิเคชันจำลองและ แอปพลิ เคชันอีมูเลเตอร์ คอมพิวเตอร์ บัสแอดเดรส ROM มีความกว้าง 15 บิต ดังนั้นจึงมีคำ (word) ทั้งหมด 32,768 คำที่พร้อมใช้งานสำหรับคำสั่งโปรแกรม แอดเดรสของคำที่ใช้งานอยู่ในปัจจุบันจะถูกส่งมาจาก รีจิสเตอร์ ตัวนับโปรแกรมภายใน CPU (ดูด้านล่าง) ค่าในรีจิสเตอร์หน่วยความจำ ROM ที่ระบุโดยแอดเดรสที่วางอยู่บนบัสแอดเดรสคำสั่งในรอบนาฬิกาหนึ่งๆ จะพร้อมใช้งานเป็นคำสั่ง "ปัจจุบัน" ในตอนเริ่มต้นของรอบถัดไป ไม่มีรีจิสเตอร์คำสั่งคำสั่งจะถูกถอดรหัสในแต่ละรอบจากรีจิสเตอร์ ROM ที่ใช้งานอยู่ในปัจจุบัน
หน่วยความจำเข้าถึงแบบสุ่ม (RAM)
แม้ว่าโมดูล RAM จะถูกมองว่าเป็นอาร์เรย์เชิงเส้นต่อเนื่องของรีจิสเตอร์หน่วยความจำแบบอ่าน-เขียน 16 บิตที่สามารถเข้าถึงได้ทีละตัว แต่ในทางฟังก์ชันแล้ว มันถูกจัดระเบียบตามช่วงแอดเดรสออกเป็นสามส่วน แอดเดรส 0 ( 0x000 ) ถึง 16383 ( 0x3FFF ) ประกอบด้วยรีจิสเตอร์แบบอ่าน-เขียน 16 บิตทั่วไป และมีจุดประสงค์เพื่อใช้เป็นที่เก็บข้อมูลโปรแกรมอเนกประสงค์
รีจิสเตอร์ที่แอดเดรส 16384 ( 0x4000 ) ถึง 24575 ( 0x5FFF ) นั้นโดยพื้นฐานแล้วคล้ายกับหน่วยความจำข้อมูล (Data RAM) แต่ยังถูกกำหนดให้ใช้งานโดยระบบย่อยอินพุต/เอาต์พุตหน้าจอ (Screen I/O) ในตัวด้วย ข้อมูลที่เขียนไปยังแอดเดรสในช่วงนี้จะมีผลข้างเคียงคือทำให้เกิดเอาต์พุตบนหน้าจอเสมือนขนาด 256 x 512 ของคอมพิวเตอร์ (ดู I/O) หากโปรแกรมไม่ต้องการเอาต์พุตบนหน้าจอ รีจิสเตอร์ในช่วงนี้อาจใช้สำหรับข้อมูลโปรแกรมทั่วไปได้
ตำแหน่งสุดท้ายในพื้นที่แอดเดรสของ RAM ที่ 24576 ( 0x6000 ) ประกอบด้วยรีจิสเตอร์ขนาดหนึ่งเวิร์ดเพียงตัวเดียว ซึ่งค่าปัจจุบันถูกควบคุมโดยเอาต์พุตของแป้นพิมพ์ที่เชื่อมต่อกับคอมพิวเตอร์ที่รันโปรแกรมจำลอง Hack รี จิสเตอร์แผนที่หน่วย ความจำ แป้นพิมพ์นี้ เป็นแบบอ่านอย่างเดียว (ดู I/O)
ที่อยู่หน่วยความจำข้อมูลในช่วง 24577 ( 0x6001 ) ถึง 32767 ( 0x7FFF ) ไม่ถูกต้อง การเปลี่ยนสถานะของรีจิสเตอร์หน่วยความจำ RAM ที่เลือกไว้จะถูกประสานงานโดยสัญญาณนาฬิการะบบด้วย
หน่วยประมวลผลกลาง (CPU)

ดังแสดงในแผนภาพประกอบหน่วยประมวลผลกลาง (CPU) ของคอมพิวเตอร์ Hack เป็นหน่วยตรรกะแบบรวมที่มีโครงสร้างภายใน มันทำหน้าที่หลายอย่างเหมือนกับ CPU ทั่วไปที่มีจำหน่ายในท้องตลาด ส่วนประกอบที่ซับซ้อนที่สุดของ CPU คือหน่วยคำนวณและตรรกะ (ALU) ซึ่งทำหน้าที่คำนวณ ALU เป็น อุปกรณ์ ตรรกะแบบผสมที่มีตัวถูกดำเนินการอินพุต 16 บิตสองตัวและเอาต์พุต 16 บิตหนึ่งตัว ผลการคำนวณที่ได้จากตัวถูกดำเนินการจะถูกกำหนดโดยชุดอินพุตแบบบิตเดียวหกตัวที่เรียงลำดับไปยัง ALU นอกจากนี้ ALU ยังส่งสัญญาณสถานะแบบบิตเดียวสองตัวซึ่งบ่งชี้ว่าผลการคำนวณเป็นศูนย์ (สัญญาณ zr) หรือเป็นลบ (สัญญาณ ng)
ซีพียูยังมีรีจิสเตอร์ 16 บิตสองตัว ซึ่งมีชื่อกำกับว่า D และ A รีจิสเตอร์ D (Data) เป็นรีจิสเตอร์อเนกประสงค์ ค่าปัจจุบันของรีจิสเตอร์นี้จะใช้เป็นค่าตัวถูกดำเนินการ x ของ ALU เสมอ แม้ว่าสำหรับบางคำสั่ง ค่าของรีจิสเตอร์นี้จะถูกละเลยก็ตาม ส่วนรีจิสเตอร์ A (Address) อาจใช้ค่าปัจจุบันเป็นค่าตัวถูกดำเนินการ y ของ ALU เมื่อได้รับคำสั่ง นอกจากนี้ ค่าของรีจิสเตอร์ A ยังสามารถใช้สำหรับการแอดเดรสหน่วยความจำข้อมูล และเป็นแอดเดรสเป้าหมายในหน่วยความจำคำสั่งสำหรับคำสั่งการแตกสาขาได้อีกด้วย เพื่ออำนวยความสะดวกในการทำงานนี้ รีจิสเตอร์ A จึงเชื่อมโยงโดยตรงกับ "รีจิสเตอร์เสมือน" ที่กำหนดเป็น M ซึ่งไม่ได้ถูกนำไปใช้ในฮาร์ดแวร์อย่างชัดเจน ดังนั้น รีจิสเตอร์ M จึงแสดงถึงค่าที่อยู่ใน RAM ที่มีแอดเดรสเดียวกับค่าปัจจุบันที่อยู่ในรีจิสเตอร์ A
องค์ประกอบสำคัญสุดท้ายใน CPU คือรีจิสเตอร์ตัวนับโปรแกรม (PC) PC เป็นตัวนับไบนารี 16 บิต โดย 15 บิตล่างระบุที่อยู่ในหน่วยความจำคำสั่งของคำสั่งถัดไปที่จะดำเนินการ เว้นแต่จะได้รับคำสั่งอื่นจากคำสั่งแยกสาขา PC จะเพิ่มค่าขึ้นหนึ่งเมื่อสิ้นสุดรอบสัญญาณนาฬิกาแต่ละรอบ CPU ยังมีตรรกะในการเปลี่ยนลำดับการดำเนินการคำสั่งของคอมพิวเตอร์ภายใต้การควบคุมของโปรแกรม โดยการตั้งค่า PC เป็นค่าที่ไม่เรียงลำดับ นอกจากนี้ PC ยังมีอินพุตการรีเซ็ตแบบบิตเดียวที่กำหนดค่าเริ่มต้นของ PC เป็น 0 (0x0000) เมื่อวนรอบจากตรรกะ 0 ไปยังตรรกะ 1 และกลับมาอีกครั้ง แตกต่างจาก CPU ที่ใช้งานจริงหลายๆ แบบ CPU ไม่มีกลไกฮาร์ดแวร์ที่โปรแกรมสามารถเข้าถึงได้เพื่อใช้ในการขัดจังหวะภายนอกหรือภายในของ CPU หรือรองรับการเรียกใช้ฟังก์ชัน
อินพุตและเอาต์พุตภายนอก (I/O)
คอมพิวเตอร์ Hack ใช้แนวทางการแมปหน่วยความจำสำหรับการรับส่งข้อมูล (I/O) การแสดงผลภาพขาวดำแบบบิตแมปไปยังหน้าจอเสมือนขนาด 256 x 512 พิกเซล ทำได้โดยการเขียนบิตแมปของภาพที่ต้องการไปยังตำแหน่งหน่วยความจำข้อมูล 16384 ( 0x4000 ) ถึง 24575 ( 0x5FFF ) คำข้อมูลในช่วงที่อยู่หน่วยความจำนี้ถูกมองว่าเป็นอาร์เรย์เชิงเส้นของบิต โดยแต่ละค่าบิตแสดงถึงสถานะขาวดำของพิกเซลเดียวบนหน้าจอเสมือนของโปรแกรมจำลองคอมพิวเตอร์ บิตที่มีค่าต่ำที่สุดในคำที่อยู่หน่วยความจำแรกของส่วน RAM หน้าจอจะกำหนดให้พิกเซลที่มุมบนซ้ายของหน้าจอเป็นสีขาวหากเป็น 0 และเป็นสีดำหากเป็น 1 บิตที่มีค่าถัดไปในคำแรกจะควบคุมพิกเซลถัดไปทางด้านขวา และเป็นเช่นนี้เรื่อยไป หลังจากที่แถว 512 พิกเซลแรกถูกอธิบายโดยคำ 32 คำแรกของหน่วยความจำหน้าจอแล้ว การแมปจะดำเนินต่อไปในลักษณะเดียวกันสำหรับแถวที่สองด้วยคำ 32 คำถัดไป วงจรประมวลผลภายนอกคอมพิวเตอร์จะอ่านส่วนของแผนที่หน่วยความจำ RAM ของหน้าจอและอัปเดตหน้าจอเสมือน
หากมีการต่อแป้นพิมพ์เข้ากับคอมพิวเตอร์ที่รันโปรแกรมจำลองซีพียู โปรแกรมจำลองจะส่งรหัสสแกน 16 บิตที่สอดคล้องกับปุ่มที่ถูกกดระหว่างการทำงานของโปรแกรมไปยังรีจิสเตอร์แป้นพิมพ์ที่แอดเดรส RAM 24576 (0x6000) หากไม่มีการกดปุ่มใด ๆ รีจิสเตอร์นี้จะมีค่าเป็น 0 โปรแกรมจำลองมีปุ่มสลับเพื่อเปิด/ปิดใช้งานแป้นพิมพ์ รูปแบบการเข้ารหัสจะคล้ายกับการเข้ารหัส ASCII สำหรับอักขระที่พิมพ์ได้ โดยทั่วไปแล้วผลของปุ่ม Shiftจะถูกใช้งานอย่างถูกต้อง นอกจากนี้ยังมีรหัสสำหรับปุ่มอื่น ๆ ที่มักพบในแป้นพิมพ์พีซีมาตรฐาน เช่น ปุ่มควบคุมทิศทาง (←, ↑, ↓, →) และปุ่ม Fn
รอบการทำงาน
การทำงานทีละขั้นตอนของหน่วยประมวลผลกลาง (CPU) และหน่วยความจำถูกควบคุมโดยนาฬิกาที่ติดตั้งอยู่ในทั้งโปรแกรมจำลองฮาร์ดแวร์และโปรแกรมจำลองคอมพิวเตอร์ เมื่อเริ่มต้นรอบนาฬิกา คำสั่งที่แอดเดรส ROM ที่ส่งออกมาตามค่าปัจจุบันของตัวนับโปรแกรมจะถูกถอดรหัส ตัวถูกดำเนินการ ALU ที่ระบุในคำสั่งจะถูกจัดเรียงตามความจำเป็น การคำนวณที่ระบุจะถูกดำเนินการโดย ALU และสถานะแฟล็กที่เหมาะสมจะถูกตั้งค่า ผลลัพธ์ของการคำนวณจะถูกบันทึกตามที่ระบุในคำสั่ง สุดท้าย ตัวนับโปรแกรมจะได้รับการอัปเดตเป็นค่าของคำสั่งโปรแกรมถัดไปที่ต้องการ หากไม่มีการระบุการแตกแขนงโดยคำสั่งปัจจุบัน ค่า PC จะเพิ่มขึ้น หากมีการระบุการแตกแขนง PC จะถูกโหลด (จากรีจิสเตอร์ A) ด้วยแอดเดรสของคำสั่งถัดไปที่จะดำเนินการ จากนั้นวงจรจะทำซ้ำโดยใช้ค่า PC ปัจจุบัน
เนื่องจากสถาปัตยกรรมหน่วยความจำแบบฮาร์วาร์ด คอมพิวเตอร์ Hack ถูกออกแบบมาให้ประมวลผลคำสั่งปัจจุบันและ "ดึง" คำสั่งถัดไปในรอบสัญญาณนาฬิกาเดียวแบบสองส่วน ความเร็วของสัญญาณนาฬิกาสามารถปรับเปลี่ยนได้โดยองค์ประกอบควบคุมทั้งในโปรแกรมจำลองฮาร์ดแวร์และโปรแกรมจำลองซีพียู อย่างไรก็ตาม ไม่ว่าความเร็วที่เลือกจะเป็นเท่าใด คำสั่งแต่ละคำสั่งจะถูกประมวลผลอย่างสมบูรณ์ในรอบเดียว ผู้ใช้ยังสามารถดำเนินการทีละขั้นตอนในโปรแกรมได้อีกด้วย
การทำงานของโปรแกรมที่โหลดอยู่ใน ROM นั้นถูกควบคุมโดยบิตรีเซ็ตของ CPU หากค่าของบิตรีเซ็ตเป็น 0 การทำงานจะดำเนินไปตามรอบการทำงานที่อธิบายไว้ข้างต้น การตั้งค่าบิตรีเซ็ตเป็น 1 จะตั้งค่า PC เป็น 0 การตั้งค่าบิตรีเซ็ตกลับเป็นศูนย์จะเริ่มการทำงานของโปรแกรมปัจจุบันที่คำสั่งแรก อย่างไรก็ตาม RAM จะเก็บค่าจากการทำงานก่อนหน้าทั้งหมดเมื่อรีเซ็ต
ไม่มีการรองรับการทำงานของระบบขัดจังหวะใดๆ ทั้งในระดับฮาร์ดแวร์หรือภาษาเครื่อง
ประเภทข้อมูล
ค่าที่จัดเก็บในหน่วยความจำ ROM ต้องแสดงถึงคำสั่งภาษาเครื่อง Hack ที่ถูกต้องตามที่อธิบายไว้ในส่วนสถาปัตยกรรมชุดคำสั่ง
ค่า 16 บิตใดๆ ก็สามารถเก็บไว้ใน RAM ได้ชนิดข้อมูลของค่าที่เก็บใน RAM นั้นถูกกำหนดโดยตำแหน่งและ/หรือการใช้งานภายในโปรแกรม ชนิดข้อมูลหลักที่ฮาร์ดแวร์รองรับคือจำนวนเต็ม 16 บิตแบบมีเครื่องหมาย ซึ่งแสดงในรูปแบบ 2's complement ดังนั้นจำนวนเต็มแบบมีเครื่องหมายจึงมีช่วงตั้งแต่ −32768 ถึง 32767 บิตล่าง 15 บิตของค่าใน RAM อาจแทนที่อยู่ใน ROM หรือ RAM ในลักษณะเดียวกับตัวชี้ ได้เช่น กัน
สำหรับค่าในรีจิสเตอร์หน่วยความจำ RAM ที่กำหนดไว้สำหรับการรับส่งข้อมูลหน้าจอ ค่าดังกล่าวจะถูกตีความว่าเป็นแผนที่ 16 พิกเซลของหน้าจอเสมือนขนาด 256 แถว x 512 คอลัมน์ โดยระบบย่อยการรับส่งข้อมูลอิสระของคอมพิวเตอร์ หากหน้าจอ "เปิดอยู่"
ค่ารหัสในหน่วยความจำของแป้นพิมพ์สามารถอ่านได้โดยใช้โปรแกรม และตีความเพื่อนำไปใช้โดยโปรแกรมอื่นได้
ฮาร์ดแวร์ไม่มีการรองรับประเภทข้อมูลทศนิยม
สถาปัตยกรรมชุดคำสั่ง (ISA) และภาษาเครื่อง
สถาปัตยกรรมชุดคำสั่ง (ISA) และภาษาเครื่อง ที่ได้มาจาก ISA ของคอมพิวเตอร์ Hack นั้นค่อนข้างเรียบง่ายเมื่อเทียบกับสถาปัตยกรรมอื่นๆ ถึงแม้ว่า 6 บิตที่ใช้ในการระบุการคำนวณโดย ALU จะสามารถรองรับคำสั่งที่แตกต่างกันได้ถึง 64 คำสั่ง แต่มีเพียง 18 คำสั่งเท่านั้นที่ถูกนำมาใช้ใน ISA ของคอมพิวเตอร์ Hack อย่างเป็นทางการ เนื่องจากฮาร์ดแวร์ของคอมพิวเตอร์ Hack ไม่รองรับการคูณ (และการหาร) จำนวนเต็มหรือการเรียกใช้ฟังก์ชันโดยตรง จึงไม่มีคำสั่งภาษาเครื่องที่สอดคล้องกันใน ISA สำหรับการดำเนินการเหล่านี้
ภาษาเครื่องของแฮ็กมีคำสั่งเพียงสองประเภท โดยแต่ละประเภทเข้ารหัสด้วยเลขฐานสอง 16 หลัก
คำแนะนำ A
คำสั่งที่มีบิตสำคัญที่สุดเป็น "0" เรียกว่าคำสั่ง A หรือคำสั่งที่อยู่ คำสั่ง A ถูกเข้ารหัสด้วยบิตฟิลด์ดังนี้:
0 b b b b b b b b b b b b b b b
0 – ส่วนที่สำคัญที่สุดของคำสั่ง A คือ "0"
b - b - บิตเหล่านี้ให้ค่าเลขฐานสองของจำนวนเต็มที่ไม่เป็นลบในช่วงทศนิยม 0 ถึง 32767
เมื่อคำสั่งนี้ถูกประมวลผล บิตที่เหลืออีก 15 บิตจะถูกขยายด้วยค่าศูนย์ทางซ้ายและโหลดเข้าไปในรีจิสเตอร์ A ของซีพียู ผลข้างเคียงคือ รีจิสเตอร์ RAM ที่มีที่อยู่ซึ่งแสดงด้วยค่านั้นจะถูกเปิดใช้งานสำหรับการอ่าน/เขียนในรอบสัญญาณนาฬิกาถัดไป
คำสั่ง C
คำสั่งอีกประเภทหนึ่งที่เรียกว่า คำสั่ง C (คำสั่งคำนวณ) เป็นคำสั่งหลักในการเขียนโปรแกรม โดยมี "1" เป็นบิตที่มีความสำคัญสูงสุด บิตที่เหลืออีก 15 บิตจะถูกเข้ารหัสแบบบิตฟิลด์เพื่อกำหนดตัวถูกดำเนินการ การคำนวณที่ดำเนินการ และตำแหน่งจัดเก็บผลลัพธ์การคำนวณที่ระบุ คำสั่งนี้อาจระบุการกระโดดไปยังส่วนอื่นของโปรแกรมโดยอิงจากผลลัพธ์การคำนวณล่าสุด รูปแบบของคำสั่งคือ
คำสั่ง C: dest = comp ; jumpโดยที่destหรือjumpอาจว่างเปล่า ทำให้มีสองตัวเลือกคือdest = compหรือcomp ; jump
คำสั่ง C ถูกเข้ารหัสแบบบิตฟิลด์ดังนี้:
111 a c c c c c c d d d j j j
1 – ส่วนที่สำคัญที่สุดของคำสั่ง C คือ "1"
11 – สองบิตหลังนี้ CPU จะไม่สนใจ และตามธรรมเนียมแล้วจะถูกตั้งค่าเป็น "1" เสมอ
a – บิตนี้ระบุแหล่งที่มาของตัวถูกดำเนินการ "y" ของ ALU เมื่อใช้ในการคำนวณ
c -c – บิตควบคุมทั้งหกนี้ระบุตัวถูกดำเนินการและการคำนวณที่จะดำเนินการโดย ALU
d -d – บิตทั้งสามนี้ระบุปลายทางสำหรับการจัดเก็บเอาต์พุต ALU ปัจจุบัน
j -j – บิตทั้งสามนี้ระบุเงื่อนไขการแยกสาขาแบบคำนวณทางคณิตศาสตร์ การแยกสาขาแบบไม่มีเงื่อนไข (กระโดด) หรือไม่มีการแยกสาขาเลย
ตารางต่อไปนี้แสดงแผนผังการเข้ารหัสคำสั่ง C ของคอมพิวเตอร์ Hack
ในตารางเหล่านี้
- Aแทนค่าที่อยู่ในรีจิสเตอร์ A ในปัจจุบัน
- Dแทนค่าที่อยู่ในรีจิสเตอร์ D ในปัจจุบัน
- Mแทนค่าที่อยู่ในรีจิสเตอร์หน่วยความจำข้อมูลซึ่งมีที่อยู่เก็บอยู่ในรีจิสเตอร์ A กล่าวคือ M == RAM[A]
| เอ | ค | ซี | ค | ซี | ค | ค | เอาต์พุต ALU: f(x,y) | ตัวช่วยจำ |
|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 1 | 0 | 1 | 0 | ส่งคืนค่า 0; ไม่สนใจตัวถูกดำเนินการทั้งหมด | 0 |
| 0 | 1 | 1 | 1 | 1 | 1 | 1 | ส่งคืนค่า 1; ไม่สนใจตัวถูกดำเนินการทั้งหมด | 1 |
| 0 | 1 | 1 | 1 | 0 | 1 | 0 | ส่งคืนค่า −1; ไม่สนใจตัวถูกดำเนินการทั้งหมด | −1 |
| 0 | 0 | 0 | 1 | 1 | 0 | 0 | ส่งออก D; ไม่สนใจ A และ M | ดี |
| 0 | 1 | 1 | 0 | 0 | 0 | 0 | ส่งออก A; ไม่สนใจ D และ M | เอ |
| 1 | 1 | 1 | 0 | 0 | 0 | 0 | ส่งออกค่า M; ไม่สนใจค่า D และ A | เอ็ม |
| 0 | 0 | 0 | 1 | 1 | 0 | 1 | แสดงผลการกลับบิตของ D โดยไม่สนใจ A และ M | !D |
| 0 | 1 | 1 | 0 | 0 | 0 | 1 | แสดงผลการกลับบิตของ A; ไม่สนใจ D และ M | !A |
| 1 | 1 | 1 | 0 | 0 | 0 | 1 | แสดงผลการกลับบิตของ M โดยไม่สนใจ D และ A | !M |
| 0 | 0 | 0 | 1 | 1 | 1 | 1 | ส่งออกค่าผกผันแบบ 2's complement ของ D; ไม่สนใจ A และ M | -D |
| 0 | 1 | 1 | 0 | 0 | 1 | 1 | ส่งออกค่าผกผันแบบ 2's complement ของ A; ไม่สนใจ D และ M | -เอ |
| 1 | 1 | 1 | 0 | 0 | 1 | 1 | ส่งออกค่าผกผันแบบ 2's complement ของ M; ไม่สนใจ D และ A | -ม |
| 0 | 0 | 1 | 1 | 1 | 1 | 1 | ส่งคืนค่า D + 1 (เพิ่มค่า D) โดยไม่สนใจค่า A และ M | ดี+1 |
| 0 | 1 | 1 | 0 | 1 | 1 | 1 | ส่งคืนค่า A + 1 (เพิ่มค่า A ขึ้นหนึ่ง); ไม่สนใจค่า D และ M | เอ+1 |
| 1 | 1 | 1 | 0 | 1 | 1 | 1 | ส่งคืนค่า M + 1 (เพิ่มค่า M) โดยไม่สนใจค่า D และ A | ม+1 |
| 0 | 0 | 0 | 1 | 1 | 1 | 0 | ส่งคืนค่า D - 1 (ลดค่า D ลง); ไม่สนใจค่า A และ M | ดี-1 |
| 0 | 1 | 1 | 0 | 0 | 1 | 0 | ส่งคืนค่า A - 1 (ลดค่า A ลง); ไม่สนใจค่า D และ M | เอ-1 |
| 1 | 1 | 1 | 0 | 0 | 1 | 0 | ส่งคืนค่า M-1 (ลดค่า M ลง) โดยไม่สนใจค่า D และ A | เอ็ม-1 |
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | ส่งออก D + A; ไม่สนใจ M | ดี+เอ |
| 1 | 0 | 0 | 0 | 0 | 1 | 0 | ส่งออก D + M; ไม่สนใจ A | ดี+เอ็ม |
| 0 | 0 | 1 | 0 | 0 | 1 | 1 | ส่งออก D - A; ไม่สนใจ M | ดีเอ |
| 1 | 0 | 1 | 0 | 0 | 1 | 1 | ส่งออก D - M; ไม่สนใจ A | ดีเอ็ม |
| 0 | 0 | 0 | 0 | 1 | 1 | 1 | ส่งออกค่า A - D; ไม่สนใจค่า M | โฆษณา |
| 1 | 0 | 0 | 0 | 1 | 1 | 1 | ส่งออกค่า M - D; ไม่สนใจค่า A | เอ็มดี |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | ส่งคืนค่าตรรกะแบบบิตไวส์ AND ของ D และ A โดยไม่สนใจค่า M | ดีแอนด์เอ |
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | ส่งคืนค่าตรรกะแบบบิตไวส์ AND ของ D และ M โดยไม่สนใจ A | ดีแอนด์เอ็ม |
| 0 | 0 | 1 | 0 | 1 | 0 | 1 | ส่งคืนค่าตรรกะแบบบิตwise OR ของ D และ A โดยไม่สนใจ M | ดี|เอ |
| 1 | 0 | 1 | 0 | 1 | 0 | 1 | ส่งคืนค่าตรรกะแบบบิตwise OR ของ D และ M โดยไม่สนใจ A | ดีเอ็ม |
| ง | d | ง | บันทึกผลลัพธ์ของ ALU ใน | ตัวช่วยจำ |
|---|---|---|---|---|
| 0 | 0 | 0 | ผลลัพธ์ไม่ถูกบันทึก | ไม่มี |
| 0 | 0 | 1 | เอ็ม | เอ็ม |
| 0 | 1 | 0 | ดี | ดี |
| 0 | 1 | 1 | เอ็ม แอนด์ ดี | เอ็มดี |
| 1 | 0 | 0 | เอ | เอ |
| 1 | 0 | 1 | เอแอนด์เอ็ม | เช้า |
| 1 | 1 | 0 | เอ และ ดี | โฆษณา |
| 1 | 1 | 1 | เอ และ เอ็ม และ ดี | เอดีเอ็ม |
| เจ | เจ | เจ | แยกสาขาถ้า | ตัวช่วยจำ |
|---|---|---|---|---|
| 0 | 0 | 0 | ไม่มีสาขา | ไม่มี |
| 0 | 0 | 1 | เอาต์พุตมากกว่า 0 | เจจีที |
| 0 | 1 | 0 | ผลลัพธ์เท่ากับ 0 | เจอีคิว |
| 0 | 1 | 1 | เอาต์พุตมากกว่าหรือเท่ากับ 0 | เจจีอี |
| 1 | 0 | 0 | เอาต์พุตน้อยกว่า 0 | เจแอลที |
| 1 | 0 | 1 | ผลลัพธ์ไม่เท่ากับ 0 | เจเอ็นอี |
| 1 | 1 | 0 | เอาต์พุตน้อยกว่าหรือเท่ากับ 0 | เจแอลอี |
| 1 | 1 | 1 | สาขาแบบไม่มีเงื่อนไข | เจเอ็มพี |
ภาษาแอสเซมบลี
คอมพิวเตอร์ Hack ใช้ ภาษาแอสเซมบลีแบบข้อความในการสร้างโปรแกรมสำหรับแพลตฟอร์มฮาร์ดแวร์ที่ใช้สถาปัตยกรรมชุดคำสั่ง (ISA) ของคอมพิวเตอร์ Hack โปรแกรมภาษาแอสเซมบลีของ Hack สามารถจัดเก็บไว้ในไฟล์ข้อความที่มีนามสกุลไฟล์ “.asm” ไฟล์ต้นฉบับภาษาแอสเซมบลีของ Hack นั้นคำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก แต่ละบรรทัดของข้อความประกอบด้วยองค์ประกอบอย่างใดอย่างหนึ่งต่อไปนี้:
- บรรทัดว่าง
- ความคิดเห็น
- การประกาศฉลาก (พร้อมข้อความแสดงความคิดเห็นท้ายบรรทัดเพิ่มเติม)
- คำสั่ง A (พร้อมข้อความแสดงความคิดเห็นท้ายบรรทัดเพิ่มเติม)
- คำสั่ง C (พร้อมข้อความแสดงความคิดเห็นท้ายบรรทัดเพิ่มเติม)
แต่ละประเภทของบรรทัดเหล่านี้มีไวยากรณ์เฉพาะ และอาจมีสัญลักษณ์ที่กำหนดไว้ล่วงหน้าหรือที่ผู้ใช้กำหนด หรือค่าคงที่ตัวเลข บรรทัดว่างและข้อความแสดงความคิดเห็นจะถูกละเว้นโดยแอสเซมเบลอร์ การประกาศป้ายกำกับ คำสั่ง A และคำสั่ง C ตามที่กำหนดไว้ด้านล่าง จะต้องไม่มีอักขระช่องว่างภายในใดๆ แม้ว่าจะอนุญาตให้มีช่องว่างนำหน้าหรือต่อท้ายได้ (และจะถูกละเว้น)
ความคิดเห็น
ข้อความใดๆ ที่ขึ้นต้นด้วยลำดับอักขระสองตัว "//" คือข้อความแสดงความคิดเห็น ข้อความแสดงความคิดเห็นอาจปรากฏอยู่บนบรรทัดโค้ดต้นฉบับเพียงอย่างเดียว หรืออาจวางไว้ที่ท้ายบรรทัดโค้ดต้นฉบับอื่นๆ ก็ได้ ข้อความทั้งหมดที่อยู่หลังลำดับอักขระระบุข้อความแสดงความคิดเห็นจนถึงท้ายบรรทัดจะถูกแอสเซมเบลอร์ละเว้นโดยสิ้นเชิง ดังนั้นจึงไม่สร้างโค้ดเครื่องใดๆ
สัญลักษณ์และค่าคงที่ตัวเลข
ภาษาแอสเซมบลี Hack อนุญาตให้ใช้สัญลักษณ์ตัวอักษรและตัวเลขเพื่อวัตถุประสงค์เฉพาะต่างๆ สัญลักษณ์อาจเป็นลำดับของตัวอักษร (ตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก) หรือตัวเลข สัญลักษณ์อาจประกอบด้วยอักขระต่อไปนี้: ขีดล่าง ("_"), จุด ("."), เครื่องหมายดอลลาร์ ("$") และเครื่องหมายโคลอน (":") สัญลักษณ์ต้องไม่ขึ้นต้นด้วยตัวเลข สัญลักษณ์นั้นคำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก สัญลักษณ์ที่ผู้ใช้กำหนดเองจะใช้ในการสร้างชื่อตัวแปรและป้ายกำกับ (ดูด้านล่าง)
ตัวประกอบภาษาแอสเซมบลีของ Hack รู้จักสัญลักษณ์ที่กำหนดไว้ล่วงหน้าบางส่วนสำหรับการใช้งานในโปรแกรมภาษาแอสเซมบลี สัญลักษณ์ R0, R1, …, R15 ถูกผูกไว้กับจำนวนเต็ม 0 ถึง 15 ตามลำดับ สัญลักษณ์เหล่านี้มีไว้เพื่อแทนรีจิสเตอร์อเนกประสงค์ และค่าของสัญลักษณ์จึงแทนที่อยู่หน่วยความจำข้อมูล 0 ถึง 15 นอกจากนี้ยังมีการกำหนดสัญลักษณ์ที่กำหนดไว้ล่วงหน้า SCREEN และ KBD เพื่อแทนที่อยู่หน่วยความจำข้อมูลของจุดเริ่มต้นของเอาต์พุตหน้าจอเสมือนที่แมปหน่วยความจำ (16384) และอินพุตแป้นพิมพ์ (24756) ยังมีสัญลักษณ์อื่นๆ อีกเล็กน้อย (SP, LCL, ARG, THIS และ THAT) ที่ใช้ในการสร้างสแต็กซอฟต์แวร์ของระบบปฏิบัติการ
สามารถใช้สตริงของตัวเลขทศนิยม (0–9) เพื่อแสดงค่าคงที่ทศนิยมที่ไม่เป็นลบในช่วง 0 ถึง 32,767 ไม่อนุญาตให้ใช้เครื่องหมายลบเพื่อแสดงจำนวนลบ ไม่รองรับการแสดงผลในรูปแบบเลขฐานสองหรือเลขฐานแปด
ตัวแปร
สามารถสร้างสัญลักษณ์ที่ผู้ใช้กำหนดเองได้ในโปรแกรมภาษาแอสเซมบลีเพื่อใช้แทนตัวแปร ซึ่งก็คือรีจิสเตอร์ RAM ที่มีชื่อ สัญลักษณ์นั้นจะถูกผูกไว้กับที่อยู่ RAM ที่เลือกโดยแอสเซมเบลอร์ ดังนั้น ตัวแปรจึงต้องถูกมองว่าเป็นที่อยู่เมื่อปรากฏในซอร์สโค้ดภาษาแอสเซมบลี
ตัวแปรจะถูกกำหนดโดยปริยายในโค้ดต้นฉบับภาษาแอสเซมบลีเมื่อมีการอ้างอิงถึงเป็นครั้งแรกในคำสั่ง A เมื่อแอสเซมเบลอร์ประมวลผลโค้ดต้นฉบับ สัญลักษณ์ตัวแปรจะถูกผูกกับค่าจำนวนเต็มบวกที่ไม่ซ้ำกัน โดยเริ่มต้นที่แอดเดรส 16 แอดเดรสจะถูกผูกกับสัญลักษณ์ตัวแปรตามลำดับการปรากฏครั้งแรกในโค้ดต้นฉบับ ตามธรรมเนียม สัญลักษณ์ที่ผู้ใช้กำหนดเพื่อระบุตัวแปรโปรแกรมจะเขียนด้วยตัวพิมพ์เล็กทั้งหมด
ป้ายกำกับ
ป้ายกำกับ (Labels) คือสัญลักษณ์ที่คั่นด้วยวงเล็บเปิด "(" และวงเล็บปิด ")" ป้ายกำกับเหล่านี้ถูกกำหนดไว้ในบรรทัดโปรแกรมต้นฉบับแยกต่างหาก และจะถูกผูกไว้โดยแอสเซมเบลอร์กับแอดเดรสของตำแหน่งหน่วยความจำคำสั่งของคำสั่งถัดไปในโค้ดต้นฉบับ ป้ายกำกับสามารถกำหนดได้เพียงครั้งเดียว แต่สามารถใช้งานได้หลายครั้งในโปรแกรม แม้กระทั่งก่อนบรรทัดที่กำหนดป้ายกำกับนั้น ตามธรรมเนียมแล้ว ป้ายกำกับจะเขียนด้วยตัวพิมพ์ใหญ่ทั้งหมด ป้ายกำกับใช้เพื่อระบุแอดเดรสเป้าหมายของคำสั่งกระโดด (branch instructions) ในภาษาซี
คำแนะนำ A
คำสั่ง A มีไวยากรณ์ "@ xxxx " โดยที่xxxxคือค่าคงที่ตัวเลขทศนิยมในช่วง 0 ถึง 32767, ป้ายกำกับ หรือตัวแปร (ที่กำหนดไว้ล่วงหน้าหรือกำหนดโดยผู้ใช้) เมื่อดำเนินการ คำสั่งนี้จะกำหนดค่าของรีจิสเตอร์ A และรีจิสเตอร์เสมือน M ให้เป็นค่าไบนารี 15 บิตที่แสดงด้วย " xxxx " ค่า 15 บิตนี้จะถูกขยายโดยเติมศูนย์ทางซ้ายเป็น 16 บิตในรีจิสเตอร์ A
คำสั่ง A อาจถูกใช้เพื่อวัตถุประสงค์สามประการ ประการแรก คือ เป็นวิธีเดียวในการนำค่าตัวเลข (ที่ไม่ติดลบ) เข้าสู่คอมพิวเตอร์ภายใต้การควบคุมของโปรแกรม กล่าวคือ อาจใช้เพื่อสร้างค่าคงที่ของโปรแกรม ประการที่สอง คือ ใช้เพื่อระบุตำแหน่งหน่วยความจำ RAM โดยใช้กลไกของรีจิสเตอร์เสมือน M สำหรับการอ้างอิงในภายหลังโดยคำสั่ง C ประการสุดท้าย คำสั่ง C ที่ระบุการกระโดดจะใช้ค่าปัจจุบันของรีจิสเตอร์ A เป็นที่อยู่เป้าหมายของการกระโดด คำสั่ง A ใช้เพื่อตั้งค่าที่อยู่เป้าหมายนั้นก่อนคำสั่งการกระโดด โดยปกติจะอ้างอิงถึงป้ายกำกับ
คำแนะนำ C
คำสั่ง C ควบคุมกลไกการคำนวณ ALU และความสามารถในการควบคุมการไหลของโปรแกรมของคอมพิวเตอร์ Hack ไวยากรณ์ของคำสั่งถูกกำหนดโดยสามฟิลด์ ซึ่งเรียกว่า "comp", "dest" และ "jump" ฟิลด์ comp เป็นสิ่งที่จำเป็นในทุกคำสั่ง C ไวยากรณ์ของคำสั่ง C คือ "dest = comp ; jump" อักขระ "=" และ ";" ใช้เพื่อคั่นฟิลด์ของคำสั่ง หากไม่ได้ใช้ฟิลด์ dest จะละเว้นอักขระ "=" หากไม่ได้ใช้ฟิลด์ jump จะละเว้นอักขระ ";" คำสั่ง C ไม่อนุญาตให้มีช่องว่างภายใน
ฟิลด์compต้องเป็นหนึ่งใน 28 รหัสช่วยจำที่กำหนดไว้ในตารางด้านบน รหัสเหล่านี้ถือเป็นหน่วยที่แตกต่างกัน ต้องเขียนด้วยตัวพิมพ์ใหญ่ทั้งหมดโดยไม่มีช่องว่างภายใน ทั้งนี้ บิตควบคุม ALU ทั้ง 6 บิตอาจระบุฟังก์ชันการคำนวณได้ถึง 64 ฟังก์ชัน แต่มีเพียง 18 ฟังก์ชันที่แสดงในตารางเท่านั้นที่ได้รับการบันทึกอย่างเป็นทางการเพื่อให้แอสเซมเบลอร์รู้จัก
ช่องdestใช้สำหรับระบุตำแหน่งที่จะจัดเก็บผลลัพธ์ของการคำนวณที่ระบุไว้ตั้งแต่หนึ่งตำแหน่งขึ้นไป หากละเว้นช่องนี้ รวมถึงตัวคั่น "=" ค่าที่คำนวณได้จะไม่ถูกจัดเก็บ ตำแหน่งการจัดเก็บที่อนุญาตจะระบุไว้ด้วยรหัสช่วยจำในตารางด้านบน
ช่องกระโดด (jump field) ใช้เพื่อระบุที่อยู่ใน ROM ของคำสั่งถัดไปที่จะถูกประมวลผล หากละเว้นช่องนี้ พร้อมกับตัวคั่น ";" การประมวลผลจะดำเนินต่อไปที่คำสั่งถัดจากคำสั่งปัจจุบันทันที ที่อยู่เป้าหมายของการกระโดดใน ROM จะได้มาจากค่าปัจจุบันของรีจิสเตอร์ A หากเงื่อนไขการกระโดดที่ระบุเป็นจริง หากเงื่อนไขการกระโดดไม่เป็นจริง การประมวลผลจะดำเนินต่อไปที่คำสั่งถัดไปใน ROM มีรหัสช่วยจำ (mnemonic codes) สำหรับการเปรียบเทียบที่แตกต่างกันหกแบบโดยอิงจากค่าของการคำนวณปัจจุบัน นอกจากนี้ ยังมีการกระโดดแบบไม่มีเงื่อนไขเป็นตัวเลือกที่เจ็ด เนื่องจากต้องระบุช่อง comp เสมอ แม้ว่าค่าจะไม่จำเป็นสำหรับการกระโดดแบบไม่มีเงื่อนไขก็ตาม ไวยากรณ์ของคำสั่งนี้จึงกำหนดเป็น "0;JMP" เงื่อนไขการกระโดดที่รองรับจะระบุไว้ในตารางด้านบน
แอสเซมเบลอร์
ซอฟต์แวร์ที่ใช้งานได้ฟรีซึ่งสนับสนุนคอมพิวเตอร์ Hack ประกอบด้วยแอปพลิเคชันแอสเซมเบลอร์แบบบรรทัดคำสั่ง แอสเซมเบลอร์จะอ่านไฟล์ต้นฉบับภาษาแอสเซมบลีของ Hack (*.asm) และสร้างไฟล์เอาต์พุตภาษาเครื่องของ Hack (*.hack) ไฟล์ภาษาเครื่องนี้เป็นไฟล์ข้อความเช่นกัน แต่ละบรรทัดของไฟล์นี้เป็นสตริงตัวเลขไบนารี 16 ตัวอักษรที่แสดงถึงการเข้ารหัสของแต่ละบรรทัดที่สามารถเรียกใช้งานได้ในไฟล์ข้อความต้นฉบับตามข้อกำหนดที่อธิบายไว้ในส่วน "สถาปัตยกรรมชุดคำสั่ง (ISA) และภาษาเครื่อง" ไฟล์ที่สร้างขึ้นสามารถโหลดลงในอีมูเลเตอร์คอมพิวเตอร์ Hack ได้โดยใช้ฟังก์ชันที่จัดเตรียมไว้ในอินเทอร์เฟซผู้ใช้ของอีมูเลเตอร์
ตัวอย่างโปรแกรมภาษาแอสเซมบลี
ต่อไปนี้เป็นตัวอย่างโปรแกรมที่เขียนด้วยภาษาแอสเซมบลีของ Hack พร้อมคำอธิบายประกอบ โปรแกรมนี้จะบวกเลขจำนวนเต็ม 100 ตัวแรกที่เรียงติดกัน และเก็บผลลัพธ์ของการคำนวณไว้ในตัวแปรที่ผู้ใช้กำหนดเองชื่อ " sum " โปรแกรมนี้ใช้ลูป whileเพื่อวนซ้ำค่าจำนวนเต็มตั้งแต่ 1 ถึง 100 และบวกเลขจำนวนเต็มแต่ละตัวเข้ากับตัวแปร "sum" ตัวแปรที่ผู้ใช้กำหนดเองชื่อ " cnt " จะเก็บค่าจำนวนเต็มปัจจุบันไว้ตลอดลูป โปรแกรมนี้แสดงให้เห็นถึงคุณสมบัติทั้งหมดของความสามารถของภาษาแอสเซมบลีที่ "มีการบันทึกไว้" ของคอมพิวเตอร์ Hack ยกเว้นการรับส่งข้อมูลแบบแมปหน่วยความจำ (memory-mapped I/O) นี่คือการแปลภาษาแอสเซมบลีของ Hack จากส่วนของโค้ดภาษา C:
// บวก 1+...+100 int cnt = 1 ; int sum = 0 ; while ( cnt <= 100 ) { sum += cnt ; cnt ++ ; }เนื้อหาของไฟล์ต้นฉบับภาษาแอสเซมบลีของ Hack แสดงอยู่ในคอลัมน์ที่สองด้วยตัวอักษรตัวหนา หมายเลขบรรทัดมีไว้สำหรับการอ้างอิงในการอธิบายต่อไปนี้ แต่จะไม่ปรากฏในโค้ดต้นฉบับ โค้ดเครื่องของ Hack ที่สร้างโดยแอสเซมเบลอร์แสดงอยู่ในคอลัมน์สุดท้าย โดยมีที่อยู่ ROM ที่กำหนดไว้ในคอลัมน์ก่อนหน้า โปรดทราบว่า ข้อความแสดงความคิดเห็นแบบเต็มบรรทัด บรรทัดว่าง และคำสั่งกำหนดป้ายกำกับจะไม่สร้างโค้ดเครื่องใดๆ นอกจากนี้ ข้อความแสดงความคิดเห็นที่ให้ไว้ในตอนท้ายของแต่ละบรรทัดที่มีคำสั่งภาษาแอสเซมบลีจะถูกแอสเซมเบลอร์ละเว้น
ผลลัพธ์จากแอสเซมเบลอร์ที่แสดงในคอลัมน์สุดท้าย เป็นสตริงข้อความที่ประกอบด้วยอักขระไบนารี 16 ตัว ไม่ใช่การแสดงค่าจำนวนเต็มไบนารี 16 บิต
| เส้น หมายเลข | โปรแกรมแฮ็กภาษาแอสเซมบลี | หมายเหตุการใช้งาน | คำแนะนำ พิมพ์ | รอม ที่อยู่ | เครื่องแฮ็ก รหัส |
|---|---|---|---|---|---|
| 01 | // บวกจำนวนเต็มที่เรียงติดกันตั้งแต่ 1 ถึง 100 | ข้อความที่อธิบายการทำงานของโปรแกรม | ความคิดเห็นแบบเต็มบรรทัด | - - - - | ไม่มีการสร้างโค้ด |
| 02 | // ผลรวม = 1 + 2 + 3 + ... + 99 + 100 | ตัวประกอบจะไม่สนใจความคิดเห็น | ความคิดเห็นแบบเต็มบรรทัด | - - - - | ไม่มีการสร้างโค้ด |
| 03 | บรรทัดโค้ดที่ว่างเปล่าจะถูกละเว้นโดยแอสเซมเบลอร์ | บรรทัดว่าง | - - - - | ไม่มีการสร้างโค้ด | |
| 04 | @cnt // การประกาศตัวนับลูป | สัญลักษณ์ตัวแปร "cnt" ผูกกับ 16 | คำแนะนำ A | 00 | 0000000000010000 |
| 05 | M=1 // กำหนดค่าเริ่มต้นตัวนับลูปเป็น 1 | RAM[16] ← 1 | คำสั่ง C | 01 | 1110111111001000 |
| 06 | @sum // การประกาศตัวสะสมผลรวม | สัญลักษณ์ตัวแปร "ผลรวม" ถูกผูกไว้กับ 17 | คำแนะนำ A | 02 | 0000000000010001 |
| 07 | M=0 // กำหนดค่าผลรวมเริ่มต้นเป็น 0 | RAM[17] ← 0 | คำสั่ง C | 03 | 1110101010001000 |
| 08 | (ลูป) // เริ่มต้นลูป while | สัญลักษณ์ป้ายกำกับที่ผูกกับที่อยู่ ROM 04 | การประกาศฉลาก | - - - - | ไม่มีการสร้างโค้ด |
| 09 | @cnt // ที่อยู่อ้างอิงของ cnt | ม. ← 16 | คำแนะนำ A | 04 | 0000000000010000 |
| 10 | D=M // ย้ายค่า cnt ปัจจุบันไปที่ D | D ← RAM[16] | คำสั่ง C | 05 | 1111110000010000 |
| 11 | @100 // โหลดค่าขีดจำกัดลูปเข้าไปใน A | A ← 100 | คำแนะนำ A | 06 | 0000000001100100 |
| 12 | D=DA // ดำเนินการคำนวณทดสอบลูป | ดี ← ดี - เอ | คำสั่ง C | 07 | 1110010011010000 |
| 13 | @END // โหลดปลายทางเป้าหมายสำหรับสาขา | ม.← 18 | คำแนะนำ A | 08 | 0000000000010010 |
| 14 | D;JGT //ออกจากลูปหาก D > 0 | สาขาแบบมีเงื่อนไข | คำสั่ง C | 09 | 1110001100000001 |
| 15 | @cnt // ที่อยู่อ้างอิงของ cnt | ม. ← 16 | คำแนะนำ A | 10 | 0000000000010000 |
| 16 | D=M // ย้ายค่า cnt ปัจจุบันไปที่ D | D ← RAM[16] | คำสั่ง C | 11 | 1111110000010000 |
| 17 | @sum // ที่อยู่สำหรับอ้างอิงของผลรวม | ม. ← 17 | คำแนะนำ A | 12 | 0000000000010001 |
| 18 | M=D+M // เพิ่มค่า cnt ลงในผลรวม | M ← D + RAM[17] | คำสั่ง C | 13 | 1111000010001000 |
| 19 | @cnt // ที่อยู่อ้างอิงของ cnt | ม. ← 16 | คำแนะนำ A | 14 | 0000000000010000 |
| 20 | M=M+1 // เพิ่มค่าตัวนับ | RAM[16] ← RAM[16] + 1 | คำสั่ง C | 15 | 1111110111001000 |
| 21 | @LOOP // โหลดปลายทางเป้าหมายสำหรับสาขา | ม ← 4 | คำแนะนำ A | 16 | 0000000000000100 |
| 22 | 0;JMP // กระโดดไปยังจุดเริ่มต้นของลูป | สาขาแบบไม่มีเงื่อนไข | คำสั่ง C | 17 | 1110101010000111 |
| 23 | (จบ) // จุดเริ่มต้นของลูปที่สิ้นสุด | สัญลักษณ์ป้ายกำกับที่ผูกกับที่อยู่ ROM 18 | การประกาศฉลาก | - - - - | ไม่มีการสร้างโค้ด |
| 24 | @END // โหลดปลายทางเป้าหมายสำหรับสาขา | ม.← 18 | คำแนะนำ A | 18 | 0000000000010010 |
| 25 | 0;JMP // กระโดดไปยังรายการ END | สาขาแบบไม่มีเงื่อนไข | คำสั่ง C | 19 | 1110101010000111 |
โปรดสังเกตว่าลำดับคำสั่งเป็นไปตามรูปแบบของคำสั่ง A, คำสั่ง C, คำสั่ง A, คำสั่ง C, ... ซึ่งเป็นรูปแบบทั่วไปของโปรแกรมภาษาแอสเซมบลี Hack คำสั่ง A ระบุค่าคงที่หรือที่อยู่หน่วยความจำที่ใช้ในคำสั่ง C ถัดไป
ตัวอย่างทั้งสามรูปแบบของคำสั่ง A แสดงไว้ในภาพประกอบ ในบรรทัดที่ 11 (@100) ค่าคงที่ 100 จะถูกโหลดเข้าไปในรีจิสเตอร์ A ค่านี้จะถูกนำไปใช้ในบรรทัดที่ 12 (D=DA) เพื่อคำนวณค่าที่ใช้ในการทดสอบเงื่อนไขการแยกสาขาของลูป
เนื่องจากบรรทัดที่ 4 (@cnt) มีการปรากฏครั้งแรกของตัวแปรที่ผู้ใช้กำหนด "cnt" คำสั่งนี้จึงผูกสัญลักษณ์เข้ากับที่อยู่ RAM ที่ไม่ได้ใช้ถัดไป ในกรณีนี้ ที่อยู่คือ 16 และค่าดังกล่าวจะถูกโหลดลงในรีจิสเตอร์ A นอกจากนี้ รีจิสเตอร์เสมือน M ยังอ้างอิงถึงที่อยู่นี้ด้วย และ RAM[16] จะถูกทำให้เป็นตำแหน่งหน่วยความจำ RAM ที่ใช้งานอยู่
การใช้งานคำสั่ง A ครั้งที่สามพบได้ในบรรทัดที่ 21 (@LOOP) คำสั่งนี้จะโหลดค่าป้ายกำกับที่ผูกไว้ ซึ่งแสดงถึงที่อยู่ในหน่วยความจำ ROM ลงในรีจิสเตอร์ A และรีจิสเตอร์เสมือน M คำสั่งกระโดดแบบไม่มีเงื่อนไขในบรรทัดที่ 22 (0;JMP) จะโหลดค่ารีจิสเตอร์ M ลงในรีจิสเตอร์ตัวนับโปรแกรมของ CPU เพื่อทำการถ่ายโอนการควบคุมไปยังจุดเริ่มต้นของลูป
คอมพิวเตอร์ Hack ไม่มีคำสั่งภาษาเครื่องเพื่อหยุดการทำงานของโปรแกรม บรรทัดสองบรรทัดสุดท้ายของโปรแกรม (@END และ 0;JMP) สร้างเงื่อนไขลูปอนันต์ ซึ่งโปรแกรมภาษาแอสเซมบลีของ Hack มักใช้เพื่อยุติโปรแกรมที่ออกแบบมาให้ทำงานในโปรแกรมจำลอง CPU
ดูเพิ่มเติม
- Hennessy, John L. และ Patterson, David A. (2019). สถาปัตยกรรมคอมพิวเตอร์: แนวทางเชิงปริมาณ ฉบับที่ 6.เคมบริดจ์ รัฐแมสซาชูเซตส์: สำนักพิมพ์ Morgan Kaufmann
- จัสติส, แมทธิว. (2021). คอมพิวเตอร์ทำงานอย่างไรกันแน่.ซานฟรานซิสโก, แคลิฟอร์เนีย: โน สตาร์ช เพรส.
- Malvino, Albert P. และ Brown, Jerald A. (1993). อิเล็กทรอนิกส์คอมพิวเตอร์ดิจิทัล ฉบับที่ 3นิวยอร์ก, นิวยอร์ก: Glencoe McGraw-Hill
- Null, Linda และ Lobur, Julia. (2019). สาระสำคัญของการจัดระเบียบและสถาปัตยกรรมคอมพิวเตอร์ ฉบับที่ 5เบอร์ลิงตัน รัฐแมสซาชูเซตส์: Jones and Bartlett Learning.
- Patt, Yale N. และ Patel, Sanjay J. (2020). บทนำสู่ระบบคอมพิวเตอร์: จากบิตและเกตไปจนถึงภาษาซีและอื่นๆ ฉบับที่ 3นิวยอร์ก, นิวยอร์ก: McGraw Hill Education.
- เพทโซลด์, ชาร์ลส์. (2009). รหัส: ภาษาที่ซ่อนเร้นของฮาร์ดแวร์และซอฟต์แวร์คอมพิวเตอร์.เรดมอนด์, วอชิงตัน: สำนักพิมพ์ไมโครซอฟต์.
- สกอตต์, จอห์น คลาร์ก. (2009). แต่มันรู้ได้อย่างไร? หลักการพื้นฐานของคอมพิวเตอร์สำหรับทุกคน.โอลด์สมาร์, ฟลอริดา: จอห์น ซี. สกอตต์.
- วิปเปิล, ริชาร์ด. (2019). สร้างคอมพิวเตอร์ของคุณเองตั้งแต่เริ่มต้น.ซีแอตเติล, วอชิงตัน: Amazon Kindle.