บทที่ 6: พื้นฐานสถาปัตยกรรมคอมพิวเตอร์สมัยใหม่พร้อมภาษาแอสเซมบลี

Bth Thi 6 Phun Than Sthapatykrrm Khxmphiwtexr Smay Him Phrxm Phas A Xae S Semb Li



6.1 บทนำ

คอมพิวเตอร์อเนกประสงค์สมัยใหม่มีสองประเภท: CISC และ RISC CISC ย่อมาจาก Complex Instruction Set Computer RISK ย่อมาจากคอมพิวเตอร์ชุดคำสั่งที่ลดลง ไมโครโปรเซสเซอร์ 6502 หรือ 6510 ซึ่งใช้ได้กับคอมพิวเตอร์ Commodore-64 มีลักษณะคล้ายกับสถาปัตยกรรม RISC มากกว่าสถาปัตยกรรม CISC

โดยทั่วไปคอมพิวเตอร์ RISC จะมีคำสั่งภาษาแอสเซมบลีที่สั้นกว่า (ตามจำนวนไบต์) เมื่อเปรียบเทียบกับคอมพิวเตอร์ CISC







บันทึก : ไม่ว่าจะจัดการกับ CISC, RISC หรือคอมพิวเตอร์เก่า อุปกรณ์ต่อพ่วงเริ่มต้นจากพอร์ตภายในและออกไปด้านนอกผ่านพอร์ตภายนอกบนพื้นผิวแนวตั้งของยูนิตระบบของคอมพิวเตอร์ (ยูนิตฐาน) และไปยังอุปกรณ์ภายนอก



คำสั่งทั่วไปของคอมพิวเตอร์ CISC สามารถมองเห็นได้เหมือนกับการรวมคำสั่งภาษาแอสเซมบลีสั้นๆ หลายคำสั่งเข้าเป็นคำสั่งภาษาแอสเซมบลีที่ยาวกว่าคำสั่งเดียว ซึ่งทำให้คำสั่งผลลัพธ์มีความซับซ้อน โดยเฉพาะอย่างยิ่ง คอมพิวเตอร์ CISC จะโหลดตัวถูกดำเนินการจากหน่วยความจำลงในการลงทะเบียนไมโครโปรเซสเซอร์ จากนั้นดำเนินการ จากนั้นจึงจัดเก็บผลลัพธ์กลับเข้าไปในหน่วยความจำ ทั้งหมดนี้อยู่ในคำสั่งเดียว ในทางกลับกัน นี่เป็นคำสั่งอย่างน้อยสามคำสั่ง (ย่อ) สำหรับคอมพิวเตอร์ RISC



คอมพิวเตอร์ CISC มีสองซีรีส์ยอดนิยม: คอมพิวเตอร์ไมโครโปรเซสเซอร์ Intel และคอมพิวเตอร์ไมโครโปรเซสเซอร์ AMD AMD ย่อมาจาก Advanced Micro Devices; เป็นบริษัทผู้ผลิตเซมิคอนดักเตอร์ ซีรีส์ไมโครโปรเซสเซอร์ของ Intel ตามลำดับการพัฒนาคือ 8086, 8088, 80186, 80286, 80386, 80486, Pentium, Core, i Series, Celeron และ Xeon คำสั่งภาษาแอสเซมบลีสำหรับไมโครโปรเซสเซอร์ Intel รุ่นแรก ๆ เช่น 8086 และ 8088 นั้นไม่ซับซ้อนมากนัก อย่างไรก็ตาม ไมโครโปรเซสเซอร์รุ่นใหม่มีความซับซ้อน ไมโครโปรเซสเซอร์ AMD ล่าสุดสำหรับซีรีส์ CISC ได้แก่ Ryzen, Opteron, Athlon, Turion, Phenom และ Sempron ไมโครโปรเซสเซอร์ Intel และ AMD รู้จักกันในชื่อไมโครโปรเซสเซอร์ x86





ARM ย่อมาจาก Advanced RISC Machine สถาปัตยกรรม ARM กำหนดตระกูลโปรเซสเซอร์ RISC ซึ่งเหมาะสำหรับใช้ในแอปพลิเคชันที่หลากหลาย แม้ว่าไมโครโปรเซสเซอร์ Intel และ AMD จำนวนมากจะถูกใช้ในคอมพิวเตอร์ส่วนบุคคลแบบเดสก์ท็อป แต่โปรเซสเซอร์ ARM จำนวนมากทำหน้าที่เป็นโปรเซสเซอร์แบบฝังในระบบที่มีความสำคัญด้านความปลอดภัย เช่น ระบบเบรกป้องกันล้อล็อกของรถยนต์ และเป็นโปรเซสเซอร์อเนกประสงค์ในนาฬิกาอัจฉริยะ โทรศัพท์แบบพกพา แท็บเล็ต และคอมพิวเตอร์แล็ปท็อป . แม้ว่าไมโครโปรเซสเซอร์ทั้งสองประเภทสามารถมองเห็นได้ในอุปกรณ์ขนาดเล็กและขนาดใหญ่ แต่ไมโครโปรเซสเซอร์ RISC นั้นพบได้ในอุปกรณ์ขนาดเล็กมากกว่าในอุปกรณ์ขนาดใหญ่

คำคอมพิวเตอร์
หากคอมพิวเตอร์ถูกกล่าวว่าเป็นคอมพิวเตอร์ที่มีเวิร์ดขนาด 32 บิต นั่นหมายความว่าข้อมูลนั้นจะถูกจัดเก็บ ถ่ายโอน และจัดการในรูปแบบของรหัสไบนารี่ 32 บิตภายในส่วนด้านในของเมนบอร์ด นอกจากนี้ยังหมายความว่าการลงทะเบียนอเนกประสงค์ในไมโครโปรเซสเซอร์ของคอมพิวเตอร์นั้นมีความกว้าง 32 บิต รีจิสเตอร์ A, X และ Y ของไมโครโปรเซสเซอร์ 6502 เป็นรีจิสเตอร์เอนกประสงค์ มีความกว้างแปดบิต ดังนั้นคอมพิวเตอร์ Commodore-64 จึงเป็นคอมพิวเตอร์เวิร์ดแปดบิต



คำศัพท์บางส่วน
คอมพิวเตอร์ X86

ความหมายของไบต์, คำ, doubleword, quadword และ double-quadword มีดังนี้สำหรับคอมพิวเตอร์ x86:

  • ไบต์ : 8 บิต
  • คำ : 16 บิต
  • คำสองคำ : 32 บิต
  • สี่คำ : 64 บิต
  • สี่คำคู่ : 128 บิต

คอมพิวเตอร์อาร์ม
ความหมายของไบต์ halfword word และ doubleword มีดังต่อไปนี้สำหรับคอมพิวเตอร์ ARM:

  • ไบต์ : 8 บิต
  • กลายเป็นครึ่งหนึ่ง : 16 บิต
  • คำ : 32 บิต
  • คำสองคำ : 64 บิต

ควรสังเกตความแตกต่างและความคล้ายคลึงสำหรับชื่อ x86 และ ARM (และค่า)

บันทึก : จำนวนเต็มเครื่องหมายในคอมพิวเตอร์ทั้งสองประเภทเป็นส่วนเสริมของสอง

ตำแหน่งหน่วยความจำ
สำหรับคอมพิวเตอร์ Commodore-64 ตำแหน่งหน่วยความจำโดยทั่วไปจะเป็นหนึ่งไบต์ แต่อาจเป็นสองไบต์ติดต่อกันในบางครั้งเมื่อพิจารณาถึงพอยน์เตอร์ (การกำหนดที่อยู่ทางอ้อม) ด้วยคอมพิวเตอร์ x86 ที่ทันสมัย ​​ตำแหน่งหน่วยความจำคือ 16 ไบต์ติดต่อกันเมื่อจัดการกับควอดเวิร์ดคู่ขนาด 16 ไบต์ (128 บิต) 8 ไบต์ติดต่อกันเมื่อจัดการกับควอดเวิร์ดขนาด 8 ไบต์ (64 บิต) และ 4 ไบต์ติดต่อกันเมื่อจัดการกับดับเบิลเวิร์ดของ 4 ไบต์ (32 บิต), 2 ไบต์ติดต่อกันเมื่อจัดการกับคำที่มีขนาด 2 ไบต์ (16 บิต) และ 1 ไบต์เมื่อจัดการกับไบต์ (8 บิต) ด้วยคอมพิวเตอร์ ARM สมัยใหม่ ตำแหน่งหน่วยความจำคือ 8 ไบต์ติดต่อกันเมื่อจัดการกับ doubleword ขนาด 8 ไบต์ (64 บิต) 4 ไบต์ติดต่อกันเมื่อจัดการกับคำขนาด 4 ไบต์ (32 บิต) และ 2 ไบต์ติดต่อกันเมื่อจัดการกับ halfword 2 ไบต์ (16 บิต) และ 1 ไบต์เมื่อจัดการกับไบต์ (8 บิต)

บทนี้อธิบายสิ่งที่พบบ่อยในสถาปัตยกรรม CISC และ RISC และความแตกต่างคืออะไร ซึ่งทำได้เมื่อเปรียบเทียบกับคอมพิวเตอร์ 6502 µP และคอมพิวเตอร์ Commodore-64 ที่เกี่ยวข้อง

6.2 แผนผังบล็อกเมนบอร์ดของพีซีสมัยใหม่

PC ย่อมาจาก Personal Computer ต่อไปนี้เป็นบล็อกไดอะแกรมพื้นฐานทั่วไปสำหรับมาเธอร์บอร์ดสมัยใหม่ที่มีไมโครโปรเซสเซอร์ตัวเดียวสำหรับคอมพิวเตอร์ส่วนบุคคล มันแสดงถึงมาเธอร์บอร์ด CISC หรือ RISC


รูปที่ 6.21 แผนภาพบล็อกเมนบอร์ดพื้นฐานของพีซีสมัยใหม่

พอร์ตภายในสามพอร์ตแสดงอยู่ในแผนภาพ แต่ในทางปฏิบัติยังมีพอร์ตอื่นๆ อีกมาก แต่ละพอร์ตมีรีจิสเตอร์ซึ่งสามารถมองเห็นได้ว่าเป็นพอร์ตนั้นเอง แต่ละวงจรพอร์ตมีรีจิสเตอร์อย่างน้อยอีกหนึ่งตัวซึ่งสามารถเรียกว่า 'รีจิสเตอร์สถานะ' การลงทะเบียนสถานะระบุพอร์ตไปยังโปรแกรมที่กำลังส่งสัญญาณขัดจังหวะไปยังไมโครโปรเซสเซอร์ มีวงจรตัวควบคุมอินเทอร์รัปต์ (ไม่แสดงไว้) ที่สร้างความแตกต่างระหว่างบรรทัดอินเทอร์รัปต์ต่างๆ จากพอร์ตต่างๆ และมีเพียงไม่กี่บรรทัดจนถึง µP

HD.C ในแผนภาพย่อมาจาก Hard Drive Card NIC ย่อมาจากการ์ดเชื่อมต่อเครือข่าย การ์ดฮาร์ดไดรฟ์ (วงจร) เชื่อมต่อกับฮาร์ดไดรฟ์ซึ่งอยู่ภายในหน่วยฐาน (หน่วยระบบ) ของคอมพิวเตอร์สมัยใหม่ การ์ดอินเทอร์เฟซเครือข่าย (วงจร) เชื่อมต่อผ่านสายเคเบิลภายนอกกับคอมพิวเตอร์เครื่องอื่น ในแผนภาพ มีหนึ่งพอร์ตและ DMA (โปรดดูภาพประกอบต่อไปนี้) ที่เชื่อมต่อกับการ์ดฮาร์ดดิสก์และ/หรือการ์ดอินเทอร์เฟซเครือข่าย DMA ย่อมาจาก Direct Memory Access

โปรดจำไว้ว่าจากบทคอมพิวเตอร์ Commodore-64 ว่าในการส่งไบต์จากหน่วยความจำไปยังดิสก์ไดรฟ์หรือคอมพิวเตอร์เครื่องอื่น แต่ละไบต์จะต้องถูกคัดลอกไปยังรีจิสเตอร์ในไมโครโปรเซสเซอร์ก่อนที่จะคัดลอกไปยังพอร์ตภายในที่เกี่ยวข้อง จากนั้นโดยอัตโนมัติ ไปยังอุปกรณ์ ในการรับไบต์จากดิสก์ไดรฟ์หรือคอมพิวเตอร์เครื่องอื่นไปยังหน่วยความจำ แต่ละไบต์จะต้องถูกคัดลอกจากรีจิสเตอร์พอร์ตภายในที่เกี่ยวข้องไปยังรีจิสเตอร์ไมโครโปรเซสเซอร์ก่อนที่จะคัดลอกไปยังหน่วยความจำ โดยปกติจะใช้เวลานานหากจำนวนไบต์ในสตรีมมีขนาดใหญ่ วิธีแก้ปัญหาสำหรับการถ่ายโอนที่รวดเร็วคือการใช้ Direct Memory Access (วงจร) โดยไม่ผ่านไมโครโปรเซสเซอร์

วงจร DMA อยู่ระหว่างพอร์ตและ HD C หรือ NIC ด้วยการเข้าถึงหน่วยความจำโดยตรงของวงจร DMA การถ่ายโอนกระแสข้อมูลไบต์ขนาดใหญ่จะเกิดขึ้นโดยตรงระหว่างวงจร DMA และหน่วยความจำ (RAM) โดยไม่ต้องมีส่วนร่วมอย่างต่อเนื่องของไมโครโปรเซสเซอร์ DMA ใช้แอดเดรสบัสและบัสข้อมูลแทน µP ระยะเวลารวมของการถ่ายโอนจะสั้นกว่าหากใช้ฮาร์ด µP ทั้ง HD C. หรือ NIC ใช้ DMA เมื่อมีข้อมูลจำนวนมาก (ไบต์) สำหรับการถ่ายโอนด้วย RAM (หน่วยความจำ)

GPU ย่อมาจากหน่วยประมวลผลกราฟิก บล็อกบนเมนบอร์ดนี้มีหน้าที่ในการส่งข้อความและภาพเคลื่อนไหวหรือภาพนิ่งไปยังหน้าจอ

เนื่องจากคอมพิวเตอร์ (พีซี) สมัยใหม่ไม่มี Read Only Memory (ROM) อย่างไรก็ตาม มี BIOS หรือ UEFI ซึ่งเป็น RAM แบบไม่ลบเลือน ข้อมูลใน BIOS ได้รับการดูแลโดยแบตเตอรี่จริงๆ แบตเตอรี่เป็นสิ่งที่ช่วยรักษาตัวจับเวลาของนาฬิกาในเวลาและวันที่ที่เหมาะสมสำหรับคอมพิวเตอร์ UEFI ได้รับการประดิษฐ์ขึ้นหลังจาก BIOS และได้เข้ามาแทนที่ BIOS แม้ว่า BIOS จะยังค่อนข้างเกี่ยวข้องกับพีซีสมัยใหม่ก็ตาม เราจะหารือเพิ่มเติมเกี่ยวกับสิ่งเหล่านี้ในภายหลัง!

ในพีซีสมัยใหม่ ที่อยู่และบัสข้อมูลระหว่าง µP และวงจรพอร์ตภายใน (และหน่วยความจำ) ไม่ใช่บัสแบบขนาน เป็นบัสอนุกรมที่ต้องการตัวนำสองตัวสำหรับการส่งสัญญาณในทิศทางเดียวและอีกสองตัวสำหรับการส่งสัญญาณในทิศทางตรงกันข้าม ซึ่งหมายความว่า ตัวอย่างเช่น สามารถส่ง 32 บิตเป็นอนุกรม (หนึ่งบิตต่อจากอีกบิตหนึ่ง) ไปในทิศทางใดทิศทางหนึ่งก็ได้

หากการส่งข้อมูลแบบอนุกรมไปในทิศทางเดียวโดยมีตัวนำไฟฟ้าสองตัว (สองเส้น) นั่นก็คือฮาล์ฟดูเพล็กซ์ หากการส่งข้อมูลแบบอนุกรมอยู่ในทั้งสองทิศทางโดยมีตัวนำสี่ตัว หนึ่งคู่ในทิศทางใดทิศทางหนึ่ง นั่นเรียกว่าฟูลดูเพล็กซ์

หน่วยความจำทั้งหมดของคอมพิวเตอร์สมัยใหม่ยังคงประกอบด้วยชุดของตำแหน่งไบต์: 8 บิตต่อไบต์ คอมพิวเตอร์สมัยใหม่มีพื้นที่หน่วยความจำอย่างน้อย 4 กิกะไบต์ = 4 x 210 x 2 10 x2 10 = 4 x 1,073,741,824 10 ไบต์ = 4 x 1024 10/ย่อย> x 1024 10 x1024 10 = 4 x 1,073,741,824 10 .

บันทึก : แม้ว่าจะไม่มีการแสดงวงจรจับเวลาบนเมนบอร์ดรุ่นก่อน แต่เมนบอร์ดสมัยใหม่ทั้งหมดก็มีวงจรจับเวลา

6.3 พื้นฐานสถาปัตยกรรมคอมพิวเตอร์ x64

6.31 ชุดการลงทะเบียน x64
ไมโครโปรเซสเซอร์ 64 บิตของไมโครโปรเซสเซอร์ซีรีส์ x86 คือไมโครโปรเซสเซอร์ 64 บิต มันค่อนข้างทันสมัยที่จะแทนที่โปรเซสเซอร์ 32 บิตของซีรีย์เดียวกัน การลงทะเบียนวัตถุประสงค์ทั่วไปของไมโครโปรเซสเซอร์ 64 บิตและชื่อมีดังนี้:


รูปที่ 6.31 รีจิสเตอร์วัตถุประสงค์ทั่วไปสำหรับ x64

รีจิสเตอร์อเนกประสงค์สิบหก (16) รายการแสดงอยู่ในภาพประกอบที่ให้มา แต่ละรีจิสเตอร์เหล่านี้มีความกว้าง 64 บิต เมื่อดูที่รีจิสเตอร์ที่มุมซ้ายบน 64 บิตจะถูกระบุว่าเป็น RAX 32 บิตแรกของรีจิสเตอร์เดียวกันนี้ (จากขวา) ถูกระบุเป็น EAX 16 บิตแรกของรีจิสเตอร์เดียวกันนี้ (จากขวา) จะถูกระบุเป็น AX ไบต์ที่สอง (จากขวา) ของรีจิสเตอร์เดียวกันนี้ระบุเป็น AH (H ในที่นี้หมายถึงสูง) และไบต์แรก (ของรีจิสเตอร์เดียวกันนี้) ถูกระบุเป็น AL (L ในที่นี้หมายถึงต่ำ) เมื่อดูที่รีจิสเตอร์ที่มุมขวาล่าง 64 บิตจะถูกระบุเป็น R15 32 บิตแรกของรีจิสเตอร์เดียวกันนี้ถูกระบุเป็น R15D 16 บิตแรกของรีจิสเตอร์เดียวกันนี้ถูกระบุเป็น R15W และไบต์แรกระบุเป็น R15B ชื่อของการลงทะเบียนอื่นๆ (และการลงทะเบียนย่อย) ได้รับการอธิบายในทำนองเดียวกัน

มีความแตกต่างบางประการระหว่าง Intel และ AMD µP ข้อมูลในส่วนนี้มีไว้สำหรับ Intel

ด้วย 6502 µP รีจิสเตอร์โปรแกรมตัวนับ (ไม่สามารถเข้าถึงได้โดยตรง) ซึ่งเก็บคำสั่งถัดไปที่จะดำเนินการจะมีความกว้าง 16 บิต ในที่นี้ (x64) ตัวนับโปรแกรมเรียกว่า Instruction Pointer และมีความกว้าง 64 บิต มีป้ายกำกับว่า RIP ซึ่งหมายความว่า x64 µP สามารถระบุตำแหน่งไบต์หน่วยความจำได้สูงสุด 264 = 1.844674407 x 1019 (จริงๆ แล้ว 18,446,744,073,709,551,616) RIP ไม่ใช่การลงทะเบียนเพื่อวัตถุประสงค์ทั่วไป

Stack Pointer Register หรือ RSP เป็นหนึ่งใน 16 รีจิสเตอร์เอนกประสงค์ มันชี้ไปที่รายการสแต็กสุดท้ายในหน่วยความจำ เช่นเดียวกับ 6502 µP สแต็กสำหรับ x64 จะลดลง ด้วย x64 สแต็กใน RAM จะถูกใช้เพื่อจัดเก็บที่อยู่ผู้ส่งคืนสำหรับรูทีนย่อย นอกจากนี้ยังใช้สำหรับจัดเก็บ 'พื้นที่เงา' (ดูการสนทนาต่อไปนี้)

6502 µP มีการลงทะเบียนสถานะโปรเซสเซอร์ 8 บิต ค่าที่เทียบเท่าใน x64 เรียกว่า RFLAGS register รีจิสเตอร์นี้จะจัดเก็บแฟล็กที่ใช้สำหรับผลลัพธ์ของการดำเนินการและสำหรับการควบคุมโปรเซสเซอร์ (µP) มีความกว้าง 64 บิต 32 บิตที่สูงกว่าถูกสงวนไว้และไม่ได้ใช้งานในปัจจุบัน ตารางต่อไปนี้ให้ชื่อ ดัชนี และความหมายสำหรับบิตที่ใช้ทั่วไปในการลงทะเบียน RFLAGS:

ตารางที่ 6.31.1
ธง RFLAGS ที่ใช้มากที่สุด (บิต)
เครื่องหมาย นิดหน่อย ชื่อ วัตถุประสงค์
ซีเอฟ 0 พก มันถูกตั้งค่าถ้าการดำเนินการทางคณิตศาสตร์ทำให้เกิดการยกหรือการยืมผลลัพธ์ที่สำคัญที่สุด เคลียร์เป็นอย่างอื่น แฟล็กนี้ระบุเงื่อนไขโอเวอร์โฟลว์สำหรับเลขคณิตจำนวนเต็มที่ไม่ได้ลงนาม นอกจากนี้ยังใช้ในเลขคณิตที่มีความแม่นยำหลายระดับด้วย
พีเอฟ 2 ความเท่าเทียมกัน มันถูกตั้งค่าถ้าไบต์ที่มีนัยสำคัญน้อยที่สุดของผลลัพธ์มีจำนวน 1 บิตเป็นเลขคู่ เคลียร์เป็นอย่างอื่น
ของ 4 ปรับ มันถูกตั้งค่าถ้าการดำเนินการทางคณิตศาสตร์สร้างการพกพาหรือการยืมจากบิต 3 ของผลลัพธ์ เคลียร์เป็นอย่างอื่น แฟล็กนี้ใช้ในเลขคณิตทศนิยมแบบไบนารี (BCD)
แซดเอฟ 6 ศูนย์ มันถูกตั้งค่าหากผลลัพธ์เป็นศูนย์ เคลียร์เป็นอย่างอื่น
เอสเอฟ 7 เข้าสู่ระบบ จะถูกตั้งค่าถ้ามันเท่ากับบิตที่สำคัญที่สุดของผลลัพธ์ ซึ่งเป็นบิตเครื่องหมายของจำนวนเต็มที่มีเครื่องหมาย (0 หมายถึงค่าบวก และ 1 หมายถึงค่าลบ)
ของ สิบเอ็ด ล้น จะถูกตั้งค่าหากผลลัพธ์จำนวนเต็มเป็นจำนวนบวกมากเกินไป หรือจำนวนลบน้อยเกินไป (ไม่รวมเครื่องหมายบิต) เพื่อให้พอดีกับตัวถูกดำเนินการปลายทาง เคลียร์เป็นอย่างอื่น แฟล็กนี้ระบุเงื่อนไขโอเวอร์โฟลว์สำหรับเลขคณิตจำนวนเต็มที่ลงนาม (ส่วนเสริมสองตัว)
ดีเอฟ 10 ทิศทาง มันถูกตั้งค่าหากคำสั่งสตริงทิศทางทำงาน (เพิ่มขึ้นหรือลดลง)
บัตรประจำตัวประชาชน ยี่สิบเอ็ด บัตรประจำตัว มันถูกตั้งค่าหากความสามารถในการเปลี่ยนแปลงแสดงว่ามีคำสั่ง CPUID อยู่

นอกเหนือจากรีจิสเตอร์ 64 บิตจำนวน 18 ตัวที่ระบุไว้ก่อนหน้านี้ สถาปัตยกรรม x64 µP ยังมีรีจิสเตอร์แบบกว้าง 80 บิตจำนวน 8 ตัวสำหรับเลขคณิตทศนิยม รีจิสเตอร์ทั้งแปดนี้ยังสามารถใช้เป็นรีจิสเตอร์ MMX ได้ (โปรดดูการสนทนาต่อไปนี้) นอกจากนี้ยังมีรีจิสเตอร์ 128 บิตจำนวน 16 รายการสำหรับ XMM (โปรดดูการสนทนาต่อไปนี้)

นั่นไม่ใช่ทั้งหมดเกี่ยวกับการลงทะเบียน มีรีจิสเตอร์ x64 เพิ่มเติมซึ่งเป็นเซ็กเมนต์รีจิสเตอร์ (ส่วนใหญ่ไม่ได้ใช้ใน x64), รีจิสเตอร์ควบคุม, รีจิสเตอร์การจัดการหน่วยความจำ, รีจิสเตอร์ดีบัก, รีจิสเตอร์การจำลองเสมือน, รีจิสเตอร์ประสิทธิภาพที่ติดตามพารามิเตอร์ภายในทุกประเภท (การเข้าชม/พลาดแคช, การดำเนินการแบบไมโคร, เวลา และอีกมากมาย)

ซิมดี

SIMD ย่อมาจาก Single Instruction Multiple Data ซึ่งหมายความว่าคำสั่งภาษาแอสเซมบลีหนึ่งคำสั่งสามารถดำเนินการกับข้อมูลหลายรายการพร้อมกันในไมโครโปรเซสเซอร์ตัวเดียว พิจารณาตารางต่อไปนี้:

1 2 3 4 5 6 7 8
+ 9 10 สิบเอ็ด 12 13 14 สิบห้า 16
= 10 12 14 16 18 ยี่สิบ 22 24

ในตารางนี้ จะมีการบวกตัวเลขแปดคู่ขนานกัน (ในช่วงเวลาเดียวกัน) เพื่อให้คำตอบแปดข้อ คำสั่งภาษาแอสเซมบลีหนึ่งคำสั่งสามารถทำการบวกจำนวนเต็มคู่ขนานแปดตัวในรีจิสเตอร์ MMX สิ่งที่คล้ายกันนี้สามารถทำได้ด้วยการลงทะเบียน XMM ดังนั้นจึงมีคำสั่ง MMX สำหรับจำนวนเต็มและคำสั่ง XMM สำหรับการลอยตัว

6.32 Memory Map และ x64

ด้วยตัวชี้คำสั่ง (ตัวนับโปรแกรม) ที่มี 64 บิต หมายความว่าสามารถระบุตำแหน่งไบต์หน่วยความจำ 264 = 1.844674407 x 1019 ได้ ในเลขฐานสิบหก ตำแหน่งไบต์สูงสุดคือ FFFF,FFFF,FFFF,FFFF16 ไม่มีคอมพิวเตอร์ธรรมดาในปัจจุบันที่สามารถให้พื้นที่หน่วยความจำขนาดใหญ่ (สมบูรณ์) ได้ ดังนั้นแผนผังหน่วยความจำที่เหมาะสมสำหรับคอมพิวเตอร์ x64 จึงเป็นดังนี้:

โปรดสังเกตว่าช่องว่างจาก 0000,8000,0000,000016 ถึง FFFF,7FFF,FFFF,FFFF16 ไม่มีตำแหน่งหน่วยความจำ (ไม่มีช่อง RAM หน่วยความจำ) นี่คือส่วนต่างของ FFFF,0000,0000,000116 ซึ่งค่อนข้างมาก Canonical High Half มีระบบปฏิบัติการ ในขณะที่ Canonical Low Half มีโปรแกรมผู้ใช้ (แอปพลิเคชัน) และข้อมูล ระบบปฏิบัติการประกอบด้วยสองส่วน: UEFI (BIOS) ขนาดเล็กและส่วนใหญ่ที่โหลดจากฮาร์ดไดรฟ์ บทต่อไปจะพูดถึงระบบปฏิบัติการสมัยใหม่เพิ่มเติม สังเกตความคล้ายคลึงกันกับแผนที่หน่วยความจำนี้และสำหรับ Commodore-64 เมื่อ 64KB อาจดูเหมือนมีหน่วยความจำจำนวนมาก

ในบริบทนี้ ระบบปฏิบัติการจะเรียกคร่าวๆ ว่า 'เคอร์เนล' เคอร์เนลนั้นคล้ายกับ Kernal ของคอมพิวเตอร์ Commodore-64 แต่มีรูทีนย่อยมากกว่ามาก

ค่า endianness สำหรับ x64 มีค่า endian เพียงเล็กน้อย ซึ่งหมายความว่าสำหรับตำแหน่ง ที่อยู่ด้านล่างจะชี้ไปที่ไบต์เนื้อหาด้านล่างในหน่วยความจำ

6.33 โหมดการกำหนดภาษาแอสเซมบลีสำหรับ x64

โหมดการกำหนดแอดเดรสเป็นวิธีที่คำสั่งสามารถเข้าถึงรีจิสเตอร์ µP และหน่วยความจำ (รวมถึงรีจิสเตอร์พอร์ตภายใน) x64 มีโหมดการกำหนดแอดเดรสมากมาย แต่เฉพาะโหมดการกำหนดแอดเดรสที่ใช้กันทั่วไปเท่านั้นที่จะกล่าวถึงที่นี่ ไวยากรณ์ทั่วไปสำหรับคำสั่งที่นี่คือ:

ปลายทาง opcode แหล่งที่มา

ตัวเลขทศนิยมเขียนโดยไม่มีคำนำหน้าหรือส่วนต่อท้ายใดๆ ด้วย 6502 แหล่งที่มาจะเป็นนัย x64 มี op-code มากกว่า 6502 แต่ opcode บางตัวมีตัวช่วยจำเหมือนกัน คำสั่ง x64 แต่ละรายการมีความยาวผันแปรได้และสามารถมีขนาดได้ตั้งแต่ 1 ถึง 15 ไบต์ โหมดการกำหนดที่อยู่ที่ใช้กันทั่วไปมีดังนี้:

โหมดที่อยู่ทันที
ในที่นี้ ตัวถูกดำเนินการแหล่งที่มาเป็นค่าจริง ไม่ใช่ที่อยู่หรือป้ายกำกับ ตัวอย่าง (อ่านความคิดเห็น):

เพิ่ม EAX, 14 ; เพิ่มทศนิยม 14 ถึง 32 บิต EAX ของ RAX 64 บิต คำตอบยังคงอยู่ใน EAX (ปลายทาง)

ลงทะเบียนเพื่อลงทะเบียนโหมดการกำหนดที่อยู่
ตัวอย่าง:

เพิ่ม R8B, อัล ; เพิ่ม 8-บิต AL ของ RAX ไปยัง R8B ของ 64-บิต R8 - คำตอบยังคงอยู่ใน R8B (ปลายทาง)

โหมดการกำหนดที่อยู่ทางอ้อมและจัดทำดัชนี
การกำหนดที่อยู่ทางอ้อมด้วย 6502 µP หมายความว่าตำแหน่งของที่อยู่ที่ระบุในคำสั่งมีที่อยู่ที่มีประสิทธิภาพ (ตัวชี้) ของตำแหน่งสุดท้าย สิ่งที่คล้ายกันเกิดขึ้นกับ x64 การกำหนดที่อยู่ดัชนีด้วย 6502 µP หมายความว่าเนื้อหาของรีจิสเตอร์ µP จะถูกเพิ่มไปยังที่อยู่ที่กำหนดในคำสั่งเพื่อให้มีที่อยู่ที่มีประสิทธิภาพ สิ่งที่คล้ายกันนี้เกิดขึ้นกับ x64 นอกจากนี้ ด้วย x64 เนื้อหาของรีจิสเตอร์ยังสามารถคูณด้วย 1 หรือ 2 หรือ 4 หรือ 8 ก่อนที่จะเพิ่มไปยังที่อยู่ที่กำหนด คำสั่ง mov (คัดลอก) ของ x64 สามารถรวมการกำหนดที่อยู่ทั้งทางอ้อมและที่จัดทำดัชนีไว้ได้ ตัวอย่าง:

MOV R8W, 1234[8*RAX+RCX] ; ย้ายคำที่อยู่ (8 x RAX + RCX) + 1234

ที่นี่ R8W มี 16 บิตแรกของ R8 ที่อยู่ที่กำหนดคือ 1234 รีจิสเตอร์ RAX มีหมายเลข 64 บิตซึ่งคูณด้วย 8 ผลลัพธ์จะถูกเพิ่มเข้าไปในเนื้อหาของรีจิสเตอร์ RCX 64 บิต ผลลัพธ์ที่สองนี้จะถูกเพิ่มไปยังที่อยู่ที่กำหนดซึ่งก็คือ 1234 เพื่อให้ได้ที่อยู่ที่มีประสิทธิภาพ หมายเลขในตำแหน่งของที่อยู่ที่มีประสิทธิภาพจะถูกย้าย (คัดลอก) ไปยังตำแหน่ง 16 บิตแรก (R8W) ของรีจิสเตอร์ R8 โดยแทนที่หมายเลขที่มีอยู่ สังเกตการใช้วงเล็บเหลี่ยม โปรดจำไว้ว่าคำใน x64 นั้นมีความกว้าง 16 บิต

RIP ที่อยู่ญาติ
สำหรับ 6502 µP การกำหนดที่อยู่แบบสัมพันธ์จะใช้กับคำสั่งสาขาเท่านั้น ที่นั่น ตัวถูกดำเนินการเดียวของ opcode คือออฟเซ็ตที่ถูกเพิ่มหรือลบออกจากเนื้อหาของตัวนับโปรแกรมสำหรับที่อยู่คำสั่งที่มีประสิทธิภาพ (ไม่ใช่ที่อยู่ข้อมูล) สิ่งที่คล้ายกันนี้เกิดขึ้นกับ x64 โดยที่ Program Counter เรียกว่า Instruction Pointer คำสั่ง x64 ไม่เพียงแต่ต้องเป็นคำสั่งสาขาเท่านั้น ตัวอย่างของการกำหนดที่อยู่แบบสัมพันธ์กับ RIP คือ:

MOV อัล [RIP]

AL ของ RAX มีตัวเลขที่เซ็นชื่อ 8 บิต ซึ่งเพิ่มหรือลบออกจากเนื้อหาใน RIP (ตัวชี้คำสั่ง 64 บิต) เพื่อชี้ไปยังคำสั่งถัดไป โปรดทราบว่าต้นทางและปลายทางมีการสลับกันเป็นพิเศษในคำสั่งนี้ นอกจากนี้ ให้สังเกตการใช้วงเล็บเหลี่ยมซึ่งอ้างอิงถึงเนื้อหาของ RIP

6.34 คำแนะนำที่ใช้ทั่วไปของ x64

ในตารางต่อไปนี้ * หมายถึงส่วนต่อท้ายที่เป็นไปได้ที่แตกต่างกันของชุดย่อยของ opcodes:

ตารางที่ 6.34.1
คำแนะนำที่ใช้กันทั่วไปใน x64
ออปโค้ด ความหมาย
มธ ย้าย (คัดลอก) ไปยัง/จาก/ระหว่างหน่วยความจำและรีจิสเตอร์
ซีเอ็มโอวี* การเคลื่อนไหวตามเงื่อนไขต่างๆ
XCHG แลกเปลี่ยน
บีสวอป สลับไบต์
พุช/ป๊อป การใช้งานสแต็ก
เพิ่ม/ADC เพิ่ม/พร้อมพกพา
ย่อย/SBC ลบ/ด้วยการยก
มัล/อิมัล ทวีคูณ/ไม่ได้ลงนาม
กรม/IDIV แบ่ง/ไม่ได้ลงนาม
อิงค์/ธ.ค เพิ่ม/ลด
เอ็นอีจี ปฏิเสธ
ซีเอ็มพี เปรียบเทียบ
และ/หรือ/XOR/ไม่ การดำเนินการระดับบิต
เอสเอชอาร์/ซาร์ เลื่อนไปทางขวา ตรรกะ/เลขคณิต
เอสเอชแอล/สล เลื่อนไปทางซ้าย ตรรกะ/เลขคณิต
ร/บทบาท หมุนไปทางขวา/ซ้าย
อาร์ซีอาร์/อาร์ซีแอล หมุนขวา/ซ้ายผ่านแครี่บิต
BT/รถไฟฟ้า/BTR ทดสอบบิต/และตั้งค่า/และรีเซ็ต
เจเอ็มพี การกระโดดแบบไม่มีเงื่อนไข
JE/JNE/JC/JNC/J* กระโดดถ้าเท่ากัน/ไม่เท่ากัน/ยก/ไม่ยก/อื่นๆ อีกมากมาย
เดิน/เดิน/เดิน วนซ้ำด้วย ECX
โทร/กลับ เรียกรูทีนย่อย / กลับ
นพ ไม่มีการดำเนินการ
CPUID ข้อมูลซีพียู

x64 มีคำแนะนำการคูณและหาร มีวงจรฮาร์ดแวร์การคูณและการหารอยู่ใน µP 6502 µP ไม่มีวงจรฮาร์ดแวร์การคูณและการหาร การคูณและหารด้วยฮาร์ดแวร์เร็วกว่าการใช้ซอฟต์แวร์ (รวมถึงการขยับบิตด้วย)

คำแนะนำสตริง
มีคำสั่งสตริงหลายคำสั่ง แต่คำสั่งเดียวที่จะกล่าวถึงในที่นี้คือคำสั่ง MOVS (สำหรับสตริงการย้าย) เพื่อคัดลอกสตริงเริ่มต้นที่ที่อยู่ C000 ชม . เริ่มต้นที่ที่อยู่ C100 ชม ให้ใช้คำสั่งต่อไปนี้:

ภาพเคลื่อนไหว [C100H], [C000H]

สังเกตคำต่อท้าย H สำหรับเลขฐานสิบหก

6.35 วนซ้ำใน x64

6502 µP มีคำสั่งสาขาสำหรับการวนซ้ำ คำสั่งสาขาข้ามไปยังตำแหน่งที่อยู่ซึ่งมีคำสั่งใหม่ ตำแหน่งที่อยู่อาจเรียกว่า 'วนซ้ำ' x64 มีคำสั่ง LOOP/LOOPE/LOOPNE สำหรับการวนซ้ำ อย่าสับสนคำภาษาแอสเซมบลีที่สงวนไว้เหล่านี้กับป้ายกำกับ 'loop' (โดยไม่มีเครื่องหมายคำพูด) พฤติกรรมมีดังนี้:

LOOP ลดค่า ECX และตรวจสอบว่า ECX ไม่เป็นศูนย์หรือไม่ หากตรงตามเงื่อนไข (ศูนย์) ระบบจะข้ามไปยังป้ายกำกับที่ระบุ มิฉะนั้นจะล้มเหลว (ทำตามคำแนะนำที่เหลือในการสนทนาต่อไปนี้)

LOOPE ลด ECX และตรวจสอบว่า ECX ไม่เป็นศูนย์ (อาจเป็น 1 เป็นต้น) และตั้งค่า ZF (เป็น 1) หากตรงตามเงื่อนไขเหล่านี้จะข้ามไปที่ป้ายกำกับ ไม่งั้นก็ผ่านไป

LOOPNE ลด ECX และตรวจสอบว่า ECX ไม่เป็นศูนย์และไม่ได้ตั้งค่า ZF (เช่น เป็นศูนย์) หากตรงตามเงื่อนไขเหล่านี้จะข้ามไปที่ป้ายกำกับ ไม่งั้นก็ผ่านไป

ด้วย x64 รีจิสเตอร์ RCX หรือส่วนย่อย เช่น ECX หรือ CX จะเก็บจำนวนเต็มตัวนับ ด้วยคำสั่ง LOOP ตัวนับปกติจะนับถอยหลัง โดยลดลง 1 สำหรับการกระโดดแต่ละครั้ง (วนซ้ำ) ในส่วนโค้ดการวนซ้ำต่อไปนี้ ตัวเลขในรีจิสเตอร์ EAX จะเพิ่มขึ้นจาก 0 เป็น 10 ในการวนซ้ำ 10 ครั้ง ในขณะที่ตัวเลขใน ECX นับ (ลดลง) ลง 10 ครั้ง (อ่านความคิดเห็น):

MOV EAX, 0 ;
MOV อีซีเอ็กซ์, 10 ; นับถอยหลัง 10 ครั้งตามค่าเริ่มต้น หนึ่งครั้งสำหรับการวนซ้ำแต่ละครั้ง
ฉลาก:
อิงค์ EAX ; เพิ่ม EAX เป็นส่วนของลูป
ป้ายห่วง ; ลด EAX และถ้า EAX ไม่เป็นศูนย์ ให้ดำเนินการวนซ้ำเนื้อหาจาก “label:”

การเข้ารหัสแบบวนซ้ำเริ่มต้นจาก 'label:' สังเกตการใช้เครื่องหมายทวิภาค การเข้ารหัสแบบวนซ้ำจะลงท้ายด้วย 'ป้ายกำกับ LOOP' ซึ่งระบุว่า EAX ลดลง หากเนื้อหาไม่เป็นศูนย์ ให้กลับไปที่คำสั่งหลัง 'label:' และดำเนินการคำสั่งใด ๆ อีกครั้ง (คำสั่งเนื้อหาทั้งหมด) ที่ลงมาจนถึง 'ป้ายกำกับ LOOP' โปรดทราบว่า 'ป้ายกำกับ' ยังสามารถมีชื่ออื่นได้

6.36 อินพุต/เอาต์พุต x64

เนื้อหาในส่วนนี้ของบทนี้เกี่ยวข้องกับการส่งข้อมูลไปยังพอร์ตเอาต์พุต (ภายใน) หรือการรับข้อมูลจากพอร์ตอินพุต (ภายใน) ชิปเซ็ตมีพอร์ตแปดบิต พอร์ต 8 บิตต่อเนื่องกันสองพอร์ตถือเป็นพอร์ต 16 บิต และพอร์ตสี่พอร์ตต่อเนื่องกันสามารถเป็นพอร์ต 32 บิตได้ ในลักษณะนี้ โปรเซสเซอร์สามารถถ่ายโอน 8, 16 หรือ 32 บิตไปยังหรือจากอุปกรณ์ภายนอกได้

ข้อมูลสามารถถ่ายโอนระหว่างโปรเซสเซอร์และพอร์ตภายในได้สองวิธี: การใช้สิ่งที่เรียกว่าอินพุต/เอาต์พุตที่แมปหน่วยความจำ หรือใช้พื้นที่ที่อยู่อินพุต/เอาต์พุตแยกต่างหาก I/O ที่แมปหน่วยความจำนั้นเหมือนกับสิ่งที่เกิดขึ้นกับโปรเซสเซอร์ 6502 โดยที่ที่อยู่พอร์ตเป็นส่วนหนึ่งของพื้นที่หน่วยความจำทั้งหมด ในกรณีนี้ เมื่อส่งข้อมูลไปยังตำแหน่งที่อยู่เฉพาะ ข้อมูลจะไปที่พอร์ต ไม่ใช่ไปยังคลังหน่วยความจำ พอร์ตอาจมีพื้นที่ที่อยู่ I/O แยกต่างหาก ในกรณีหลังนี้ ธนาคารหน่วยความจำทั้งหมดมีที่อยู่จากศูนย์ มีช่วงที่อยู่แยกต่างหากตั้งแต่ 0000H ถึง FFFF16 พอร์ตเหล่านี้ถูกใช้โดยพอร์ตในชิปเซ็ต เมนบอร์ดได้รับการตั้งโปรแกรมไว้เพื่อไม่ให้เกิดความสับสนระหว่าง I/O ที่แมปหน่วยความจำและพื้นที่ที่อยู่ I/O ที่แยกจากกัน

I/O ที่แมปหน่วยความจำ
ด้วยเหตุนี้ พอร์ตต่างๆ จึงถือเป็นตำแหน่งของหน่วยความจำ และใช้ opcode ปกติที่ใช้ระหว่างหน่วยความจำและ µP สำหรับการถ่ายโอนข้อมูลระหว่าง µP และพอร์ต ดังนั้น หากต้องการย้ายไบต์จากพอร์ตที่อยู่ F000H ไปยังรีจิสเตอร์ µP RAX:EAX:AX:AL ให้ทำดังต่อไปนี้:

MOV อัล, [F000H]

สามารถย้ายสตริงจากหน่วยความจำไปยังพอร์ตและในทางกลับกันได้ ตัวอย่าง:

ภาพเคลื่อนไหว [F000H], [C000H] ; ต้นทางคือ C000H และปลายทางคือพอร์ตที่ F000H

แยกพื้นที่ที่อยู่ I/O

ด้วยเหตุนี้ จึงจำเป็นต้องใช้คำแนะนำพิเศษสำหรับอินพุตและเอาต์พุต

การโอนรายการเดี่ยว
การลงทะเบียนตัวประมวลผลสำหรับการถ่ายโอนคือ RAX จริงๆ แล้ว มันคือ RAX:EAX สำหรับ doubleword, RAX:EAX:AX ​​สำหรับ word และ RAX:EAX:AX:AL สำหรับไบต์ ดังนั้น หากต้องการถ่ายโอนไบต์จากพอร์ตที่ FFF0h ไปยัง RAX:EAX:AX:AL ให้พิมพ์ดังต่อไปนี้:

ในอัล [FFF0H]

สำหรับการถ่ายโอนแบบย้อนกลับ ให้พิมพ์ดังต่อไปนี้:

ออก [FFF0H], อัล

ดังนั้นสำหรับรายการเดี่ยว คำแนะนำคือ IN และ OUT ที่อยู่พอร์ตยังสามารถระบุได้ในการลงทะเบียน RDX:EDX:DX

การถ่ายโอนสตริง
สามารถถ่ายโอนสตริงจากหน่วยความจำไปยังพอร์ตชิปเซ็ตและในทางกลับกัน หากต้องการถ่ายโอนสตริงจากพอร์ตที่แอดเดรส FFF0H ไปยังหน่วยความจำ ให้เริ่มต้นที่ C100H พิมพ์:

อิน [ESI], [DX]

ซึ่งมีผลเช่นเดียวกับ:

อิน [EDI], [DX]

โปรแกรมเมอร์ควรใส่ที่อยู่พอร์ตสองไบต์ของ FFF0H ในการลงทะเบียน RDX:EDX:Dx และควรใส่ที่อยู่สองไบต์ของ C100H ในการลงทะเบียน RSI:ESI หรือ RDI:EDI สำหรับการถ่ายโอนแบบย้อนกลับ ให้ทำดังต่อไปนี้:

อิน [DX], [ESI]

ซึ่งมีผลเช่นเดียวกับ:

อิน [DX], [EDI]

6.37 สแต็กใน x64

เช่นเดียวกับโปรเซสเซอร์ 6502 โปรเซสเซอร์ x64 มีสแต็กใน RAM เช่นกัน สแต็กสำหรับ x64 สามารถเป็น 2 ได้ 16 = ยาว 65,536 ไบต์หรืออาจเป็น 2 ก็ได้ 32 = ความยาว 4,294,967,296 ไบต์ มันยังเติบโตลดลงอีกด้วย เมื่อเนื้อหาของรีจิสเตอร์ถูกผลักลงบนสแต็ก ตัวเลขในตัวชี้สแต็ก RSP จะลดลง 8 โปรดจำไว้ว่าที่อยู่หน่วยความจำสำหรับ x64 จะมีความกว้าง 64 บิต ค่าในตัวชี้สแต็กใน µP ชี้ไปยังตำแหน่งถัดไปในสแต็กใน RAM เมื่อเนื้อหาของรีจิสเตอร์ (หรือค่าในโอเปอเรเตอร์หนึ่งตัว) ถูกดึงจากสแต็กไปยังรีจิสเตอร์ หมายเลขในตัวชี้สแต็ก RSP จะเพิ่มขึ้น 8 ระบบปฏิบัติการจะตัดสินใจขนาดของสแต็กและจุดเริ่มต้นใน RAM และเติบโตต่ำลง โปรดจำไว้ว่าสแต็กเป็นโครงสร้าง Last-In-First-Out (LIFO) ซึ่งขยายลงและย่อขึ้นในกรณีนี้

หากต้องการส่งเนื้อหาของรีจิสเตอร์ µP RBX ไปยังสแต็ก ให้ทำดังต่อไปนี้:

ดัน RBX

หากต้องการแสดงรายการสุดท้ายในสแต็กกลับไปที่ RBX ให้ทำดังต่อไปนี้:

ป๊อป RBX

6.38 ขั้นตอนใน x64

รูทีนย่อยใน x64 เรียกว่า 'ขั้นตอน' มีการใช้สแต็กที่นี่มากกว่าที่ใช้กับ 6502 µP ไวยากรณ์สำหรับโพรซีเดอร์ x64 คือ:

proc_name:
เนื้อหาของขั้นตอน

ขวา

ก่อนดำเนินการต่อ โปรดสังเกตว่า opcode และเลเบลสำหรับรูทีนย่อย x64 (คำสั่งภาษาแอสเซมบลีโดยทั่วไป) จะไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ นั่นคือ proc_name เหมือนกับ PROC_NAME เช่นเดียวกับ 6502 ชื่อของชื่อขั้นตอน (ป้ายกำกับ) เริ่มต้นที่จุดเริ่มต้นของบรรทัดใหม่ในโปรแกรมแก้ไขข้อความสำหรับภาษาแอสเซมบลี ตามด้วยเครื่องหมายโคลอน ไม่ใช่ช่องว่างและ opcode เช่นเดียวกับ 6502 ส่วนเนื้อหาของรูทีนย่อยจะตามหลัง โดยลงท้ายด้วย RET ไม่ใช่ RTS เช่นเดียวกับ 6502 µP เช่นเดียวกับรุ่น 6502 แต่ละคำสั่งในร่างกาย รวมถึง RET ไม่ได้เริ่มต้นที่จุดเริ่มต้นของบรรทัด โปรดทราบว่าป้ายกำกับที่นี่สามารถมีความยาวได้มากกว่า 8 อักขระ เมื่อต้องการเรียกขั้นตอนนี้ จากด้านบนหรือด้านล่างของขั้นตอนที่พิมพ์ ให้ทำดังต่อไปนี้:

โทร proc_name

ด้วยรุ่น 6502 ชื่อฉลากเป็นเพียงการพิมพ์สำหรับการโทรเท่านั้น อย่างไรก็ตาม ในที่นี้จะพิมพ์คำสงวนว่า 'CALL' หรือ 'call' ตามด้วยชื่อของขั้นตอน (รูทีนย่อย) หลังช่องว่าง

เมื่อต้องจัดการกับขั้นตอนต่างๆ โดยปกติจะมีสองขั้นตอน ขั้นตอนหนึ่งเรียกอีกขั้นตอนหนึ่ง ขั้นตอนที่เรียก (มีคำสั่งการโทร) เรียกว่า 'ผู้โทร' และขั้นตอนที่เรียกว่า 'ผู้โทร' มีแบบแผน (กฎ) ให้ปฏิบัติตาม

กฎของผู้โทร

ผู้เรียกควรปฏิบัติตามกฎต่อไปนี้เมื่อเรียกใช้รูทีนย่อย:

1. ก่อนที่จะเรียกรูทีนย่อย ผู้เรียกควรบันทึกเนื้อหาของรีจิสเตอร์บางตัวที่กำหนดให้เป็นผู้โทรที่บันทึกไว้ในสแต็ก รีจิสเตอร์ที่บันทึกโดยผู้โทรคือ R10, R11 และรีจิสเตอร์ใดๆ ที่ใส่พารามิเตอร์ไว้ (RDI, RSI, RDX, RCX, R8, R9) ถ้าเนื้อหาของรีจิสเตอร์เหล่านี้จะถูกรักษาไว้ตลอดการเรียกรูทีนย่อย ให้กดมันลงบนสแต็กแทนที่จะบันทึกใน RAM สิ่งเหล่านี้จะต้องทำเพราะผู้โทรต้องใช้รีจิสเตอร์เพื่อลบเนื้อหาก่อนหน้า

2. หากขั้นตอนคือการบวกตัวเลขสองตัว เช่น ตัวเลขสองตัวนั้นจะเป็นพารามิเตอร์ที่จะส่งผ่านไปยังสแต็ก หากต้องการส่งพารามิเตอร์ไปยังรูทีนย่อย ให้ใส่พารามิเตอร์ 6 รายการลงในรีจิสเตอร์ต่อไปนี้ตามลำดับ: RDI, RSI, RDX, RCX, R8, R9 หากมีพารามิเตอร์มากกว่าหกตัวในรูทีนย่อย ให้ดันส่วนที่เหลือลงบนสแต็กในลำดับย้อนกลับ (เช่น พารามิเตอร์ตัวสุดท้ายอยู่ก่อน) เนื่องจากสแต็กมีขนาดลดลง พารามิเตอร์ตัวแรกของพารามิเตอร์พิเศษ (จริงๆ แล้วคือพารามิเตอร์ตัวที่ 7) จะถูกจัดเก็บไว้ที่ที่อยู่ต่ำสุด (การผกผันของพารามิเตอร์นี้เคยถูกใช้ในอดีตเพื่อให้ฟังก์ชัน (รูทีนย่อย) สามารถส่งผ่านด้วยจำนวนพารามิเตอร์ที่แปรผันได้)

3. ในการเรียกรูทีนย่อย (ขั้นตอน) ให้ใช้คำสั่งการโทร คำสั่งนี้วางที่อยู่ผู้ส่งไว้ด้านบนของพารามิเตอร์บนสแต็ก (ตำแหน่งต่ำสุด) และสาขาไปยังโค้ดรูทีนย่อย

4. หลังจากที่รูทีนย่อยส่งคืน (เช่น ทำตามคำแนะนำการโทรทันที) ผู้เรียกจะต้องลบพารามิเตอร์เพิ่มเติมใด ๆ (นอกเหนือจากหกตัวที่เก็บอยู่ในรีจิสเตอร์) ออกจากสแต็ก วิธีนี้จะคืนค่าสแต็กกลับสู่สถานะก่อนที่จะดำเนินการโทร

5. ผู้เรียกสามารถคาดหวังที่จะค้นหาค่าที่ส่งคืน (ที่อยู่) ของรูทีนย่อยในการลงทะเบียน RAX

6. ผู้เรียกกู้คืนเนื้อหาของรีจิสเตอร์ที่บันทึกของผู้โทร (R10, R11 และรีจิสเตอร์ที่ส่งผ่านพารามิเตอร์) โดยการดึงมันออกจากสแต็ก ผู้เรียกสามารถสันนิษฐานได้ว่าไม่มีการแก้ไขการลงทะเบียนอื่นโดยรูทีนย่อย

เนื่องจากวิธีการจัดโครงสร้างแบบแผนการเรียก โดยทั่วไปแล้วขั้นตอนเหล่านี้บางส่วน (หรือส่วนใหญ่) จะไม่ทำการเปลี่ยนแปลงใดๆ กับสแต็ก ตัวอย่างเช่น หากมีพารามิเตอร์หกตัวหรือน้อยกว่า จะไม่มีอะไรถูกพุชลงบนสแต็กในขั้นตอนนั้น ในทำนองเดียวกัน โปรแกรมเมอร์ (และคอมไพเลอร์) มักจะเก็บผลลัพธ์ที่พวกเขาสนใจออกจากรีจิสเตอร์ที่บันทึกไว้ของผู้โทรในขั้นตอนที่ 1 และ 6 เพื่อป้องกันการพุชและป๊อปส่วนเกิน

มีสองวิธีในการส่งพารามิเตอร์ไปยังรูทีนย่อย แต่จะไม่มีการกล่าวถึงในหลักสูตรอาชีพออนไลน์นี้ หนึ่งในนั้นใช้สแต็กแทนรีจิสเตอร์ทั่วไป

กฎของผู้รับสาย

คำจำกัดความของรูทีนย่อยที่เรียกว่าควรเป็นไปตามกฎต่อไปนี้:

1. จัดสรรตัวแปรท้องถิ่น (ตัวแปรที่พัฒนาขึ้นภายในขั้นตอน) โดยใช้รีจิสเตอร์หรือเพิ่มพื้นที่บนสแต็ก จำได้ว่ากองโตขึ้นลง ดังนั้น เพื่อเพิ่มพื้นที่ด้านบนของสแต็ก ตัวชี้สแต็กควรลดลง จำนวนที่ตัวชี้สแต็กจะลดลงขึ้นอยู่กับจำนวนตัวแปรโลคัลที่ต้องการ ตัวอย่างเช่น หากจำเป็นต้องใช้โฟลตในเครื่องและค่ายาวในเครื่อง (รวม 12 ไบต์) ตัวชี้สแต็กจะต้องลดลง 12 เพื่อสร้างพื้นที่สำหรับตัวแปรในเครื่องเหล่านี้ ในภาษาระดับสูงเช่น C หมายถึงการประกาศตัวแปรโดยไม่ต้องกำหนดค่า (เริ่มต้น)

2. ถัดไป ค่าของรีจิสเตอร์ใดๆ ที่ถูกกำหนดให้บันทึกโดยผู้โทร (รีจิสเตอร์วัตถุประสงค์ทั่วไปที่ไม่ได้บันทึกโดยผู้โทร) ที่ใช้โดยฟังก์ชันจะต้องถูกบันทึก หากต้องการบันทึกรีจิสเตอร์ ให้ดันมันลงบนสแต็ก รีจิสเตอร์ที่บันทึกไว้ของผู้เรียกคือ RBX, RBP และ R12 ถึง R15 (RSP จะถูกรักษาไว้ตามรูปแบบการโทรเช่นกัน แต่ไม่จำเป็นต้องพุชบนสแต็กระหว่างขั้นตอนนี้)

หลังจากที่ดำเนินการทั้งสามนี้แล้ว การดำเนินการจริงของรูทีนย่อยอาจดำเนินการต่อได้ เมื่อรูทีนย่อยพร้อมที่จะส่งคืน กฎการประชุมการโทรจะดำเนินต่อไป

3. เมื่อรูทีนย่อยเสร็จสิ้น ค่าที่ส่งคืนสำหรับรูทีนย่อยควรถูกวางไว้ใน RAX หากยังไม่มีอยู่

4. รูทีนย่อยต้องคืนค่าเก่าของรีจิสเตอร์ที่บันทึกไว้ของผู้เรียก (RBX, RBP และ R12 ถึง R15) ที่ถูกแก้ไข เนื้อหารีจิสเตอร์จะถูกกู้คืนโดยการดึงเนื้อหาออกจากสแต็ก โปรดทราบว่ารีจิสเตอร์ควรถูกแสดงในลำดับผกผันที่ถูกผลัก

5. ต่อไป เราจะจัดสรรตัวแปรท้องถิ่นใหม่ วิธีที่ง่ายที่สุดในการทำเช่นนี้คือเพิ่มจำนวนเงินเดียวกันกับที่หักออกจาก RSP ในขั้นตอนที่ 1

6. ในที่สุด เราก็กลับไปหาผู้โทรโดยดำเนินการคำสั่ง ret คำสั่งนี้จะค้นหาและลบที่อยู่ผู้ส่งที่เหมาะสมออกจากสแต็ก

ตัวอย่างของเนื้อความของรูทีนย่อยของผู้เรียกเพื่อเรียกรูทีนย่อยอื่นซึ่งก็คือ “myFunc” มีดังต่อไปนี้ (อ่านความคิดเห็น):

; ต้องการเรียกใช้ฟังก์ชัน ”myFunc” ที่ใช้เวลาสาม
; พารามิเตอร์จำนวนเต็ม พารามิเตอร์แรกอยู่ใน RAX
; พารามิเตอร์ตัวที่สองคือค่าคงที่ 456 ประการที่สาม
; พารามิเตอร์อยู่ในตำแหน่งหน่วยความจำ ”variabl”

กด rdi ; rdi จะเป็น param ดังนั้นให้บันทึกมัน
; retVal ยาว = myFunc ( x , 456 , z ) ;

mov rdi , rax ; ใส่พารามิเตอร์แรกใน RDI
มอฟอาร์ซี, 456 ; ใส่พารามิเตอร์ที่สองใน RSI
mov rdx , [ตัวแปร] ; ใส่พารามิเตอร์ที่สามใน RDX

โทรหา myFunc ; เรียกใช้ฟังก์ชัน

ป๊อป rdi ; คืนค่า RDI ที่บันทึกไว้
; ค่าที่ส่งคืนของ myFunc มีอยู่ใน RAX แล้ว

ตัวอย่างของฟังก์ชันผู้รับสาย (myFunc) คือ (อ่านความคิดเห็น):

myFunc :
; ∗∗∗ อารัมภบทย่อยมาตรฐาน ∗∗∗
ย่อย RSP, 8 ; ห้องสำหรับตัวแปรท้องถิ่น 64 บิต (ผลลัพธ์) โดยใช้ opcode 'ย่อย'

กด rbx ; บันทึกผู้โทร − บันทึกการลงทะเบียน
ดัน RBP ; myFunc จะใช้ทั้งสองอย่าง

; ∗∗∗ รูทีนย่อย ร่างกาย ∗∗∗
mov rax rdi ; พารามิเตอร์ 1 ถึง RAX
mov rbp , อาร์เอสไอ ; พารามิเตอร์ 2 ถึง RBP
mov rbx , rdx ; พารามิเตอร์ 3 ถึง rb x
mov [rsp + 1 6 ] , rbx ; ใส่ rbx ลงในตัวแปรท้องถิ่น
เพิ่ม [ rsp + 1 6 ] , rbp ; เพิ่ม rbp ลงในตัวแปรท้องถิ่น
mov rax , [ rsp +16 ] ; mov เนื้อหาของตัวแปรท้องถิ่นไปยัง RAX
; (ค่าส่งคืน/ผลลัพธ์สุดท้าย)

; ∗∗∗ บทส่งท้ายรูทีนย่อยมาตรฐาน ∗∗∗
ป๊อป RBP ; กู้คืนผู้โทรบันทึกการลงทะเบียน
ป๊อป rbx ; ย้อนกลับเมื่อถูกผลัก
เพิ่ม RSP, 8 ; จัดสรรตัวแปรท้องถิ่น (s) 8 หมายถึง 8 ไบต์
พักผ่อน ; ปรากฏค่าบนสุดจาก stack กระโดดไปตรงนั้น

6.39 การขัดจังหวะและข้อยกเว้นสำหรับ x64

โปรเซสเซอร์มีกลไกสองประการสำหรับการขัดจังหวะการทำงานของโปรแกรม การขัดจังหวะ และข้อยกเว้น:

  • การขัดจังหวะเป็นเหตุการณ์อะซิงโครนัส (สามารถเกิดขึ้นได้ตลอดเวลา) ซึ่งโดยทั่วไปจะถูกทริกเกอร์โดยอุปกรณ์ I/O
  • ข้อยกเว้นคือเหตุการณ์ซิงโครนัส (เกิดขึ้นเมื่อโค้ดถูกดำเนินการ ตั้งโปรแกรมไว้ล่วงหน้า ขึ้นอยู่กับเหตุการณ์บางอย่าง) ที่เกิดขึ้นเมื่อโปรเซสเซอร์ตรวจพบเงื่อนไขที่กำหนดไว้ล่วงหน้าตั้งแต่หนึ่งเงื่อนไขขึ้นไปในขณะที่ดำเนินการคำสั่ง มีการระบุข้อยกเว้นสามคลาส: ข้อบกพร่อง กับดัก และการยกเลิก

โปรเซสเซอร์ตอบสนองต่อการขัดจังหวะและข้อยกเว้นในลักษณะเดียวกัน เมื่อมีการส่งสัญญาณขัดจังหวะหรือข้อยกเว้น โปรเซสเซอร์จะหยุดการทำงานของโปรแกรมหรืองานปัจจุบัน และสลับไปใช้ขั้นตอนของตัวจัดการที่เขียนขึ้นโดยเฉพาะเพื่อจัดการกับเงื่อนไขขัดจังหวะหรือข้อยกเว้น โปรเซสเซอร์เข้าถึงขั้นตอนตัวจัดการผ่านรายการใน Interrupt Descriptor Table (IDT) เมื่อตัวจัดการจัดการการขัดจังหวะหรือข้อยกเว้นเสร็จสิ้นแล้ว การควบคุมโปรแกรมจะถูกส่งกลับไปยังโปรแกรมหรืองานที่ถูกขัดจังหวะ

โดยปกติแล้วระบบปฏิบัติการ ผู้บริหาร และ/หรือไดรเวอร์อุปกรณ์จะจัดการกับการขัดจังหวะและข้อยกเว้นโดยไม่ขึ้นอยู่กับโปรแกรมหรืองานของแอปพลิเคชัน อย่างไรก็ตาม แอปพลิเคชันสามารถเข้าถึงตัวจัดการการขัดจังหวะและข้อยกเว้นที่รวมอยู่ในระบบปฏิบัติการหรือจัดการผ่านการเรียกภาษาแอสเซมบลี

มีการกำหนดอินเทอร์รัปต์และข้อยกเว้นที่กำหนดไว้ล่วงหน้าสิบแปด (18) รายการ ซึ่งเกี่ยวข้องกับรายการใน IDT การขัดจังหวะที่ผู้ใช้กำหนดจำนวนสองร้อยยี่สิบสี่ (224) สามารถสร้างและเชื่อมโยงกับตารางได้ การขัดจังหวะและข้อยกเว้นแต่ละครั้งใน IDT จะถูกระบุด้วยตัวเลขที่เรียกว่า 'เวกเตอร์' ตาราง 6.39.1 แสดงรายการการขัดจังหวะและข้อยกเว้นพร้อมรายการใน IDT และเวกเตอร์ตามลำดับ เวกเตอร์ 0 ถึง 8, 10 ถึง 14 และ 16 ถึง 19 เป็นการขัดจังหวะและข้อยกเว้นที่กำหนดไว้ล่วงหน้า เวกเตอร์ 32 ถึง 255 ใช้สำหรับการขัดจังหวะที่กำหนดโดยซอฟต์แวร์ (ผู้ใช้) ซึ่งใช้สำหรับขัดจังหวะซอฟต์แวร์หรือการขัดจังหวะด้วยฮาร์ดแวร์ที่ปกปิดได้

เมื่อโปรเซสเซอร์ตรวจพบการขัดจังหวะหรือข้อยกเว้น จะดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้:

  • ดำเนินการเรียกโดยนัยไปยังขั้นตอนการจัดการ
  • ดำเนินการเรียกโดยนัยไปยังงานตัวจัดการ

6.4 พื้นฐานสถาปัตยกรรมคอมพิวเตอร์ ARM 64 บิต

สถาปัตยกรรม ARM กำหนดตระกูลโปรเซสเซอร์ RISC ที่เหมาะสำหรับใช้ในแอปพลิเคชันที่หลากหลาย ARM เป็นสถาปัตยกรรมโหลด/จัดเก็บที่ต้องการโหลดข้อมูลจากหน่วยความจำไปยังรีจิสเตอร์ก่อนจึงจะสามารถประมวลผลใดๆ เช่น การดำเนินการ ALU (Arithmetic Logic Unit) ได้ คำสั่งต่อมาจะเก็บผลลัพธ์กลับไปยังหน่วยความจำ แม้ว่าสิ่งนี้อาจดูเหมือนเป็นการก้าวถอยหลังจากสถาปัตยกรรม x86 และ x64 ซึ่งดำเนินการโดยตรงบนตัวถูกดำเนินการในหน่วยความจำในคำสั่งเดียว (โดยใช้การลงทะเบียนตัวประมวลผลแน่นอน) ในทางปฏิบัติ วิธีการโหลด/จัดเก็บ อนุญาตให้มีการดำเนินการตามลำดับหลายอย่าง จะดำเนินการด้วยความเร็วสูงบนตัวถูกดำเนินการเมื่อมีการโหลดลงในรีจิสเตอร์ตัวประมวลผลตัวใดตัวหนึ่ง โปรเซสเซอร์ ARM มีตัวเลือกระหว่าง endianness น้อยหรือ endianness ใหญ่ การตั้งค่าเริ่มต้นของ ARM 64 คือ little-endian ซึ่งเป็นการกำหนดค่าที่ระบบปฏิบัติการใช้กันทั่วไป สถาปัตยกรรม ARM 64 บิตมีความทันสมัยและได้รับการตั้งค่าให้มาแทนที่สถาปัตยกรรม ARM 32 บิต

บันทึก : ทุกคำสั่งสำหรับ ARM µP 64 บิตจะมีความยาว 4 ไบต์ (32 บิต)

6.41 ชุดการลงทะเบียน ARM 64 บิต
มีจุดประสงค์ทั่วไป 31 ประการของการลงทะเบียน 64 บิตสำหรับ ARM µP 64 บิต แผนภาพต่อไปนี้แสดงรีจิสเตอร์เอนกประสงค์และรีจิสเตอร์ที่สำคัญบางส่วน:


รูปที่ 4.11.1 วัตถุประสงค์ทั่วไป 64 บิตและการลงทะเบียนที่สำคัญบางอย่าง

รีจิสเตอร์เอนกประสงค์เรียกว่า X0 ถึง X30 ส่วน 32 บิตแรกสำหรับแต่ละรีจิสเตอร์จะเรียกว่า W0 ถึง W30 เมื่อไม่ได้เน้นความแตกต่างระหว่าง 32 บิตและ 64 บิต ระบบจะใช้คำนำหน้า 'R' ตัวอย่างเช่น R14 หมายถึง W14 หรือ X14

6502 µP มีตัวนับโปรแกรม 16 บิตและสามารถจัดการกับ 2 ได้ 16 ตำแหน่งไบต์หน่วยความจำ ARM µP 64 บิตมีตัวนับโปรแกรม 64 บิตและสามารถระบุที่อยู่ได้สูงสุด 2 64 = 1.844674407 x 1,019 (จริงๆ แล้ว 18,446,744,073,709,551,616) ตำแหน่งไบต์หน่วยความจำ ตัวนับโปรแกรมเก็บที่อยู่ของคำสั่งถัดไปที่จะดำเนินการ ความยาวของคำสั่งของ ARM64 หรือ AArch64 โดยทั่วไปคือสี่ไบต์ โปรเซสเซอร์จะเพิ่มรีจิสเตอร์นี้สี่โดยอัตโนมัติหลังจากดึงคำสั่งแต่ละคำสั่งจากหน่วยความจำ

การลงทะเบียน Stack Pointer หรือ SP ไม่ได้อยู่ใน 31 การลงทะเบียนวัตถุประสงค์ทั่วไป ตัวชี้สแต็กของสถาปัตยกรรมใดๆ ชี้ไปที่รายการสแต็กสุดท้ายในหน่วยความจำ สำหรับ ARM-64 กองจะขยายลงด้านล่าง

6502 µP มีการลงทะเบียนสถานะโปรเซสเซอร์ 8 บิต สิ่งที่เทียบเท่าใน ARM64 เรียกว่าการลงทะเบียน PSTATE รีจิสเตอร์นี้จะจัดเก็บแฟล็กที่ใช้สำหรับผลลัพธ์ของการดำเนินการและสำหรับการควบคุมโปรเซสเซอร์ (µP) มีความกว้าง 32 บิต ตารางต่อไปนี้ให้ชื่อ ดัชนี และความหมายสำหรับบิตที่ใช้ทั่วไปในการลงทะเบียน PSTATE:

ตารางที่ 6.41.1
ธง PSTATE ที่ใช้มากที่สุด (บิต)
เครื่องหมาย นิดหน่อย วัตถุประสงค์
0-3 โหมด: ระดับสิทธิ์ในการดำเนินการปัจจุบัน (USR, SVC และอื่นๆ)
4 Thumb: จะถูกตั้งค่าหากชุดคำสั่ง T32 (Thumb) ทำงานอยู่ หากชัดเจน แสดงว่าชุดคำสั่ง ARM ทำงานอยู่ รหัสผู้ใช้สามารถตั้งค่าและล้างบิตนี้ได้
และ 9 Endianness: การตั้งค่าบิตนี้จะเปิดใช้งานโหมด big-endian หากชัดเจน แสดงว่าโหมด little-endian ทำงานอยู่ ค่าเริ่มต้นคือโหมด little-endian
ถาม 27 ธงความอิ่มตัวสะสม: จะถูกตั้งค่าหาก ณ จุดใดจุดหนึ่งในชุดของการดำเนินการ เกิดโอเวอร์โฟลว์หรือความอิ่มตัว
ใน 28 ธงโอเวอร์โฟลว์: จะถูกตั้งค่าหากการดำเนินการส่งผลให้เกิดการโอเวอร์โฟลว์ที่ลงนาม
29 ธงพกพา: ระบุว่าการบวกทำให้เกิดการพกพาหรือการลบทำให้เกิดการยืม
กับ 30 การตั้งค่าสถานะเป็นศูนย์: จะถูกตั้งค่าหากผลลัพธ์ของการดำเนินการเป็นศูนย์
เอ็น 31 ค่าสถานะเชิงลบ: จะถูกตั้งค่าหากผลลัพธ์ของการดำเนินการเป็นค่าลบ

ARM-64 µP มีรีจิสเตอร์อื่นๆ อีกมากมาย

ซิมดี
SIMD ย่อมาจาก Single Instruction, Multiple Data ซึ่งหมายความว่าคำสั่งภาษาแอสเซมบลีหนึ่งคำสั่งสามารถดำเนินการกับข้อมูลหลายรายการพร้อมกันในไมโครโปรเซสเซอร์ตัวเดียว มีรีจิสเตอร์กว้าง 128 บิตจำนวน 32 บิตสำหรับใช้กับ SIMD และการดำเนินการจุดลอยตัว

6.42 การทำแผนที่หน่วยความจำ
RAM และ DRAM เป็นทั้งหน่วยความจำเข้าถึงโดยสุ่ม DRAM ทำงานช้ากว่า RAM DRAM ราคาถูกกว่า RAM หากมี DRAM ต่อเนื่องมากกว่า 32 กิกะไบต์ (GB) ในหน่วยความจำ จะมีปัญหาในการจัดการหน่วยความจำมากขึ้น: 32 GB = 32 x 1024 x 1024 x 1024 ไบต์ สำหรับพื้นที่หน่วยความจำทั้งหมดที่มีขนาดใหญ่กว่า 32 GB DRAM ที่สูงกว่า 32 GB ควรสลับกับ RAM เพื่อการจัดการหน่วยความจำที่ดีขึ้น เพื่อให้เข้าใจแผนผังหน่วยความจำ ARM-64 คุณควรทำความเข้าใจแผนผังหน่วยความจำ 4GB สำหรับหน่วยประมวลผลกลาง (CPU) ARM แบบ 32 บิต CPU หมายถึง µP สำหรับคอมพิวเตอร์ 32 บิต พื้นที่หน่วยความจำสูงสุดที่สามารถระบุตำแหน่งได้คือ 2 32 = 4 x 2 10 x2 10 x2 10 = 4 x 1024 x 1024 x 1024 = 4,294,967,296 = 4GB

แผนที่หน่วยความจำ ARM 32 บิต
แผนผังหน่วยความจำสำหรับ ARM 32 บิตคือ:

สำหรับคอมพิวเตอร์ 32 บิต ขนาดสูงสุดของหน่วยความจำทั้งหมดคือ 4GB จากที่อยู่ 0GB ถึงที่อยู่ 1GB คือตำแหน่งระบบปฏิบัติการ ROM, RAM และ I/O แนวคิดทั้งหมดของที่อยู่ ROM OS, RAM และ I/O นั้นคล้ายคลึงกับสถานการณ์ของ Commodore-64 ที่มี CPU 6502 ที่เป็นไปได้ OS ROM สำหรับ Commodore-64 อยู่ที่ด้านบนสุดของพื้นที่หน่วยความจำ ROM OS ที่นี่มีขนาดใหญ่กว่า Commodore-64 มากและอยู่ที่จุดเริ่มต้นของพื้นที่ที่อยู่หน่วยความจำทั้งหมด เมื่อเปรียบเทียบกับคอมพิวเตอร์สมัยใหม่อื่นๆ ROM OS ที่นี่มีความสมบูรณ์ในแง่ที่เทียบเคียงได้กับจำนวน OS ในฮาร์ดไดรฟ์ มีสองเหตุผลหลักที่ทำให้ระบบปฏิบัติการอยู่ในวงจรรวม ROM: 1) CPU ARM ส่วนใหญ่จะใช้ในอุปกรณ์ขนาดเล็กเช่นสมาร์ทโฟน ฮาร์ดไดรฟ์จำนวนมากมีขนาดใหญ่กว่าสมาร์ทโฟนและอุปกรณ์ขนาดเล็กอื่นๆ 2) เพื่อความปลอดภัย เมื่อระบบปฏิบัติการอยู่ในหน่วยความจำแบบอ่านอย่างเดียว แฮกเกอร์จะไม่เสียหาย (บางส่วนถูกเขียนทับ) ส่วน RAM และส่วนอินพุต/เอาท์พุตก็ใหญ่มากเช่นกันเมื่อเทียบกับของ Commodore-64

เมื่อเปิดเครื่องด้วย ROM OS 32 บิต ระบบปฏิบัติการจะต้องเริ่มต้นที่ (บูตจาก) ที่อยู่ 0x00000000 หรือที่อยู่ 0xFFFF0000 หากเปิดใช้งาน HiVEC ดังนั้น เมื่อเปิดเครื่องหลังจากเฟสรีเซ็ต ฮาร์ดแวร์ CPU จะโหลด 0x00000000 หรือ 0xFFFF0000 ไปที่ตัวนับโปรแกรม คำนำหน้า '0x' หมายถึงเลขฐานสิบหก ที่อยู่สำหรับบูตของซีพียู ARMv8 64 บิตเป็นการใช้งานที่กำหนดไว้ อย่างไรก็ตาม ผู้เขียนแนะนำให้วิศวกรคอมพิวเตอร์เริ่มต้นที่ 0x00000000 หรือ 0xFFFF0000 เพื่อประโยชน์ของความเข้ากันได้แบบย้อนหลัง

ตั้งแต่ 1GB ถึง 2GB คืออินพุต/เอาท์พุตที่แมป มีความแตกต่างระหว่าง I/O ที่แมปและ I/O ที่พบระหว่าง 0GB ถึง 1GB ด้วย I/O ที่อยู่ของแต่ละพอร์ตจะได้รับการแก้ไขเช่นเดียวกับ Commodore-64 ด้วยแมป I/O ที่อยู่สำหรับแต่ละพอร์ตไม่จำเป็นต้องเหมือนกันสำหรับการทำงานของคอมพิวเตอร์แต่ละเครื่อง (ไดนามิก)

จาก 2GB ถึง 4GB คือ DRAM นี่คือ RAM ที่คาดหวัง (หรือปกติ) DRAM ย่อมาจาก Dynamic RAM ไม่ใช่ความรู้สึกของการเปลี่ยนแปลงที่อยู่ระหว่างการทำงานของคอมพิวเตอร์ แต่ในแง่ที่ว่าค่าของแต่ละเซลล์ใน RAM จริงจะต้องรีเฟรชที่แต่ละพัลส์นาฬิกา

บันทึก : :

  • จาก 0x0000,0000 ถึง 0x0000 FFFF คือ OS ROM
  • จาก 0x0001,0000 ถึง 0x3FFF,FFFF อาจมี ROM เพิ่มเติม จากนั้น RAM และ I/O บางส่วน
  • ตั้งแต่ 0x4000,0000 ถึง 0x7FFF,FFFF อนุญาตให้ใช้ I/O เพิ่มเติม และ/หรือ I/O ที่แมปได้
  • จาก 0x8000,0000 ถึง 0xFFFF,FFFF คือ DRAM ที่คาดหวัง

ซึ่งหมายความว่า DRAM ที่คาดหวังไม่จำเป็นต้องเริ่มต้นที่ขอบเขตหน่วยความจำ 2GB ในทางปฏิบัติ เหตุใดโปรแกรมเมอร์จึงควรเคารพขอบเขตในอุดมคติเมื่อมีธนาคาร RAM ไม่เพียงพอที่เสียบเข้ากับเมนบอร์ด เนื่องจากลูกค้าไม่มีเงินเพียงพอสำหรับธนาคาร RAM ทั้งหมด

แผนที่หน่วยความจำ ARM 36 บิต
สำหรับคอมพิวเตอร์ ARM 64 บิต จะใช้ 32 บิตทั้งหมดเพื่อระบุหน่วยความจำทั้งหมด สำหรับคอมพิวเตอร์ ARM 64 บิต 36 บิตแรกสามารถใช้เพื่อระบุหน่วยความจำทั้งหมด ซึ่งในกรณีนี้คือ 2 36 = 68,719,476,736 = 64GB นี่เป็นความทรงจำมากมายแล้ว คอมพิวเตอร์ทั่วไปในปัจจุบันไม่ต้องการหน่วยความจำจำนวนนี้ นี่ยังไม่ถึงช่วงสูงสุดของหน่วยความจำที่สามารถเข้าถึงได้ด้วย 64 บิต แผนผังหน่วยความจำสำหรับ 36 บิตสำหรับ CPU ARM คือ:

จากที่อยู่ 0GB ไปยังที่อยู่ 4GB คือแผนผังหน่วยความจำ 32 บิต “สงวน” หมายถึง ไม่ได้ใช้และเก็บไว้เพื่อใช้ในอนาคต ไม่จำเป็นต้องเป็นหน่วยความจำกายภาพที่เสียบเข้ากับเมนบอร์ดสำหรับพื้นที่นั้น ในที่นี้ DRAM และ I/O ที่แมปมีความหมายเหมือนกับการแมปหน่วยความจำ 32 บิต

สถานการณ์ต่อไปนี้อาจพบได้ในทางปฏิบัติ:

  • 0x1 0000 0000 – 0x3 FFFF FFFF; ที่สงวนไว้. พื้นที่ที่อยู่ 12GB สงวนไว้สำหรับการใช้งานในอนาคต
  • 0x4 0000 0000 – 0x7 FFFF FFFF; แมป I/O พื้นที่ที่อยู่ 16GB พร้อมใช้งานสำหรับ I/O ที่แมปแบบไดนามิก
  • 0x8 0000 0000 – 0x8 7FFFF FFFF FFFF; รูหรือ DRAM พื้นที่ที่อยู่ 2GB สามารถมีอย่างใดอย่างหนึ่งต่อไปนี้:
    • ช่องสำหรับเปิดใช้งานการแบ่งพาร์ติชันอุปกรณ์ DRAM (ตามที่อธิบายไว้ในการสนทนาต่อไปนี้)
    • แดรม.
  • 0x8 8000 0000 – 0xF FFFF FFFF; แดรม. พื้นที่ที่อยู่ 30GB สำหรับ DRAM

การแมปหน่วยความจำนี้เป็นชุดที่เหนือกว่าของการแมปที่อยู่แบบ 32 บิต โดยพื้นที่เพิ่มเติมจะถูกแบ่งเป็น 50% DRAM (1/2) พร้อมด้วยรูเสริมในนั้น และพื้นที่ I/O ที่แมป 25% และพื้นที่สงวน (1/4 ). ส่วนที่เหลืออีก 25% (1/4) ใช้สำหรับแมปหน่วยความจำ 32 บิต ½ + ¼ + ¼ = 1

บันทึก : จาก 32 บิตเป็น 360 บิตจะเป็นการเพิ่ม 4 บิตไปยังด้านที่สำคัญที่สุดของ 36 บิต

แผนที่หน่วยความจำ 40 บิต
การแมปที่อยู่ 40 บิตเป็นชุดที่เหนือกว่าของการแมปที่อยู่ 36 บิตและเป็นไปตามรูปแบบเดียวกันคือ 50% DRAM ของรูเสริมในนั้น พื้นที่ I/O ที่แมป 25% และพื้นที่สงวนไว้ และส่วนที่เหลือของ 25% พื้นที่สำหรับแผนที่หน่วยความจำก่อนหน้า (36 บิต) แผนภาพสำหรับแผนผังหน่วยความจำคือ:

ขนาดของรูคือ 544 – 512 = 32GB สถานการณ์ต่อไปนี้อาจพบได้ในทางปฏิบัติ:

  • 0x10 0000 0000 – 0x3F FFFF FFFF; ที่สงวนไว้. พื้นที่ที่อยู่ 192GB ถูกสงวนไว้สำหรับการใช้งานในอนาคต
  • 0x40 0000 0000 – 0x7F FFFF FFFF; แมป พื้นที่ที่อยู่ I/O 256GB พร้อมใช้งานสำหรับ I/O ที่แมปแบบไดนามิก
  • 0x80 0000 0000 – 0x87 FFFF FFFF; รูหรือ DRAM พื้นที่ที่อยู่ขนาด 32GB สามารถมีอย่างใดอย่างหนึ่งต่อไปนี้:
    • ช่องสำหรับเปิดใช้งานการแบ่งพาร์ติชันอุปกรณ์ DRAM (ตามที่อธิบายไว้ในการสนทนาต่อไปนี้)
    • แดรม
  • 0x88 0000 0000 – 0xFF FFFF FFFF; แดรม. พื้นที่ที่อยู่ 480GB สำหรับ DRAM

บันทึก : จาก 36 บิตเป็น 40 บิตจะเป็นการเพิ่ม 4 บิตไปยังด้านที่สำคัญที่สุดของ 36 บิต

แดรมโฮล
ในแมปหน่วยความจำที่เกินกว่า 32 บิต อาจเป็น DRAM Hole หรือ DRAM ต่อจากด้านบน เมื่อเป็นรู ควรคำนึงถึงดังนี้: รู DRAM เป็นวิธีในการแบ่งพาร์ติชันอุปกรณ์ DRAM ขนาดใหญ่ออกเป็นหลายช่วงที่อยู่ มีการเสนอช่อง DRAM เสริมที่จุดเริ่มต้นของขอบเขตที่อยู่ DRAM ที่สูงกว่า ซึ่งจะช่วยให้รูปแบบการถอดรหัสง่ายขึ้นเมื่อแบ่งพาร์ติชันอุปกรณ์ DRAM ความจุสูงข้ามภูมิภาคที่อยู่ด้านล่างทางกายภาพ

ตัวอย่างเช่น ส่วน DRAM ขนาด 64GB จะถูกแบ่งย่อยออกเป็นสามภูมิภาคโดยมีการชดเชยที่อยู่โดยการลบอย่างง่ายในบิตที่อยู่ลำดับสูงดังต่อไปนี้:

ตารางที่ 6.42.1
ตัวอย่างการแบ่งพาร์ติชัน DRAM ขนาด 64GB แบบมีรู
ที่อยู่ทางกายภาพใน SoC ออฟเซ็ต ที่อยู่ DRAM ภายใน
2 GBytes (แผนที่ 32 บิต) 0x00 8000 0000 – 0x00 FFFF FFFF -0x00 8000 0000 0x00 0000 0000 – 0x00 7FFF FFFF
30 GBytes (แผนที่ 36 บิต) 0x08 8000 0000 – 0x0F FFFF FFFF -0x08 0000 0000 0x00 8000 0000 – 0x07 FFFF FFFF
32 GBytes (แผนที่ 40 บิต) 0x88 0000 0000 – 0x8F FFFF FFFF -0x80 0000 0000 0x08 0000 0000 – 0x0F FFFF FFFF

แผนที่หน่วยความจำที่อยู่แบบ 44 บิตและ 48 บิตที่เสนอสำหรับ CPU ARM
สมมติว่าคอมพิวเตอร์ส่วนบุคคลมีหน่วยความจำ 1024GB (= 1TB) นั่นเป็นความทรงจำที่มากเกินไป ดังนั้นการแมปหน่วยความจำแบบ 44 บิตและ 48 บิตสำหรับ CPU ARM ขนาด 16 TB และ 256 TB ตามลำดับ จึงเป็นเพียงข้อเสนอสำหรับความต้องการคอมพิวเตอร์ในอนาคต ในความเป็นจริง ข้อเสนอเหล่านี้สำหรับ CPU ARM มีการแบ่งหน่วยความจำตามอัตราส่วนเดียวกันกับแผนที่หน่วยความจำก่อนหน้านี้ นั่นคือ: DRAM 50% พร้อมช่องเสริมในนั้น พื้นที่ I/O ที่แมป 25% และพื้นที่ที่สงวนไว้ และพื้นที่ที่เหลือ 25% สำหรับการแมปหน่วยความจำก่อนหน้า

แผนที่หน่วยความจำระบุที่อยู่แบบ 52 บิต, 56 บิต, 60 บิตและ 64 บิตยังคงถูกเสนอสำหรับ ARM 64 บิตสำหรับอนาคตอันไกล หากนักวิทยาศาสตร์ในขณะนั้นยังพบว่าการแบ่งพื้นที่หน่วยความจำทั้งหมดเป็น 50 : 25 : 25 มีประโยชน์ พวกเขาจะคงอัตราส่วนไว้

บันทึก : SoC ย่อมาจาก System-on-Chip ซึ่งหมายถึงวงจรในชิป µP ซึ่งถ้าไม่เป็นเช่นนั้นจะไม่มีอยู่จริง

SRAM หรือหน่วยความจำเข้าถึงโดยสุ่มแบบคงที่เร็วกว่า DRAM แบบเดิม แต่ต้องใช้พื้นที่ซิลิคอนมากกว่า SRAM ไม่ต้องการการรีเฟรช ผู้อ่านสามารถจินตนาการว่า RAM เป็น SRAM

6.43 โหมดการกำหนดภาษาแอสเซมบลีสำหรับ ARM 64
ARM เป็นสถาปัตยกรรมโหลด/จัดเก็บซึ่งต้องการข้อมูลที่จะโหลดจากหน่วยความจำไปยังการลงทะเบียนตัวประมวลผลก่อนที่การประมวลผลใดๆ เช่น การดำเนินการลอจิกทางคณิตศาสตร์จะเกิดขึ้นด้วย คำสั่งต่อมาจะเก็บผลลัพธ์กลับไปยังหน่วยความจำ แม้ว่าสิ่งนี้อาจดูเหมือนเป็นการก้าวถอยหลังจาก x86 และสถาปัตยกรรม x64 ต่อมา ซึ่งดำเนินการโดยตรงบนตัวถูกดำเนินการในหน่วยความจำในคำสั่งเดียว ในทางปฏิบัติ วิธีการโหลด/จัดเก็บอนุญาตให้ดำเนินการตามลำดับหลายอย่างที่ดำเนินการด้วยความเร็วสูงบน ตัวถูกดำเนินการเมื่อโหลดลงในรีจิสเตอร์ตัวประมวลผลตัวใดตัวหนึ่ง

รูปแบบของภาษาแอสเซมบลี ARM มีความเหมือนและแตกต่างกับซีรีส์ x64 (x86)

  • ออฟเซ็ต : สามารถเพิ่มค่าคงที่ที่เซ็นชื่อลงในรีจิสเตอร์ฐานได้ ออฟเซ็ตถูกพิมพ์เป็นส่วนหนึ่งของคำสั่ง ตัวอย่างเช่น: ldr x0, [rx, #10] โหลด r0 พร้อมด้วยคำที่ที่อยู่ r1+10
  • ลงทะเบียน : ส่วนเพิ่มที่ไม่ได้ลงนามซึ่งจัดเก็บไว้ในรีจิสเตอร์สามารถเพิ่มหรือลบออกจากค่าในรีจิสเตอร์ฐานได้ ตัวอย่างเช่น: ldr r0, [x1, x2] โหลด r0 พร้อมด้วยคำที่ที่อยู่ x1+x2 การลงทะเบียนอย่างใดอย่างหนึ่งสามารถถือเป็นการลงทะเบียนฐานได้
  • ทะเบียนปรับขนาด : ส่วนที่เพิ่มขึ้นในรีจิสเตอร์จะถูกเลื่อนไปทางซ้ายหรือขวาตามจำนวนตำแหน่งบิตที่ระบุก่อนที่จะเพิ่มหรือลบออกจากค่ารีจิสเตอร์ฐาน ตัวอย่างเช่น: ldr x0, [x1, x2, lsl #3] โหลด r0 พร้อมด้วยคำที่ที่อยู่ r1+(r2×8) การเปลี่ยนแปลงอาจเป็นการเลื่อนไปทางซ้ายหรือทางขวาแบบลอจิคัล (lsl หรือ lsr) ซึ่งจะแทรกบิตศูนย์ในตำแหน่งบิตที่ว่าง หรือการเปลี่ยนทางขวาทางคณิตศาสตร์ (asr) ที่จำลองบิตเครื่องหมายในตำแหน่งที่ว่าง

เมื่อมีตัวถูกดำเนินการสองตัวเกี่ยวข้อง ปลายทางจะอยู่ก่อน (ทางซ้าย) ต้นทาง (มีข้อยกเว้นบางประการ) opcodes สำหรับภาษาแอสเซมบลี ARM คำนึงถึงขนาดตัวพิมพ์

โหมดการกำหนดแอดเดรส ARM64 ทันที
ตัวอย่าง:

mov r0, #0xFF000000 ; โหลดค่า 32 บิต FF000000h ลงใน r0

ค่าทศนิยมไม่มี 0x แต่ยังคงนำหน้าด้วย #

ลงทะเบียนโดยตรง
ตัวอย่าง:

mov x0, x1 ; คัดลอก x1 ถึง x0

ลงทะเบียนทางอ้อม
ตัวอย่าง:

STR x0, [x3] ; เก็บ x0 ไปยังที่อยู่ใน x3

ลงทะเบียนทางอ้อมด้วย Offset
ตัวอย่าง:

ldr x0, [x1, #32] ; โหลด r0 ด้วยค่าตามที่อยู่ [r1+32]; r1 คือรีจิสเตอร์ฐาน
STR x0, [x1, #4] ; เก็บ r0 ไปยังที่อยู่ [r1+4]; r1 คือรีจิสเตอร์ฐาน ตัวเลขเป็นฐาน 10

ลงทะเบียนทางอ้อมด้วย Offset (เพิ่มล่วงหน้า)
ตัวอย่าง:

ldr x0, [x1, #32]! ; โหลด r0 ด้วย [r1+32] และอัปเดต r1 เป็น (r1+32)
STR x0, [x1, #4]! ; เก็บ r0 เป็น [r1+4] และอัปเดต r1 เป็น (r1+4)

โปรดสังเกตการใช้เครื่องหมาย “!” เครื่องหมาย.

ลงทะเบียนทางอ้อมด้วยออฟเซ็ต (หลังเพิ่มขึ้น)
ตัวอย่าง:

ldr x0, [x1], #32 ; โหลด [x1] เป็น x0 จากนั้นอัปเดต x1 เป็น (x1+32)
STR x0, [x1], #4 ; เก็บ x0 เป็น [x1] จากนั้นอัปเดต x1 เป็น (x1+4)

ลงทะเบียนทางอ้อมสองครั้ง
ที่อยู่ของตัวถูกดำเนินการคือผลรวมของการลงทะเบียนฐานและการลงทะเบียนส่วนเพิ่ม ชื่อรีจิสเตอร์จะล้อมรอบด้วยวงเล็บเหลี่ยม
ตัวอย่าง:

ldr x0, [x1, x2] ; โหลด x0 ด้วย [x1+x2]
STR x0, [rx, x2] ; เก็บ x0 ถึง [x1+x2]

โหมดการกำหนดที่อยู่แบบสัมพัทธ์
ในโหมดการกำหนดแอดเดรสแบบสัมพันธ์ คำสั่งที่มีประสิทธิผลคือคำสั่งถัดไปในตัวนับโปรแกรมบวกกับดัชนี ดัชนีอาจเป็นค่าบวกหรือค่าลบ
ตัวอย่าง:

ldr x0, [พีซี, #24]

นี่หมายถึงโหลดรีจิสเตอร์ X0 พร้อมด้วยคำที่เนื้อหา PC ชี้ไปบวก 24

6.44 คำแนะนำที่ใช้กันทั่วไปสำหรับ ARM 64
คำแนะนำที่ใช้กันทั่วไปมีดังนี้:

6.45 วนลูป

ภาพประกอบ
รหัสต่อไปนี้จะเพิ่มค่าในการลงทะเบียน X10 ให้กับค่าใน X9 จนกว่าค่าใน X8 จะเป็นศูนย์ สมมติว่าค่าทั้งหมดเป็นจำนวนเต็ม ค่าใน X8 จะถูกลบด้วย 1 ในการวนซ้ำแต่ละครั้ง:

วนซ้ำ:
CBZ X8 ข้ามไป
เพิ่ม X9, X9, X10 ; X9 อันแรกคือปลายทางและ X9 อันที่สองคือต้นทาง
ย่อย X8, X8, #1 ; X8 อันแรกคือปลายทางและ X8 อันที่สองคือต้นทาง
ห่วงบี
ข้าม:

เช่นเดียวกับ 6502 µP และ X64 µP ป้ายใน ARM 64 µP เริ่มต้นที่จุดเริ่มต้นของบรรทัด คำแนะนำที่เหลือเริ่มต้นที่ช่องว่างหลังจุดเริ่มต้นของบรรทัด ด้วย x64 และ ARM 64 ป้ายกำกับจะตามด้วยเครื่องหมายโคลอนและขึ้นบรรทัดใหม่ ในขณะที่ใช้ 6502 ป้ายกำกับจะตามด้วยคำสั่งหลังช่องว่าง ในโค้ดก่อนหน้า คำสั่งแรกซึ่งก็คือ “CBZ X8, ข้าม” หมายความว่าหากค่าใน X8 เป็นศูนย์ ให้ดำเนินการต่อที่ป้ายกำกับ “ข้าม:” โดยข้ามคำแนะนำที่อยู่ระหว่างนั้นและดำเนินการต่อด้วยคำแนะนำที่เหลือด้านล่าง 'ข้าม:'. “B loop” เป็นการข้ามไปยังป้ายกำกับ “loop” โดยไม่มีเงื่อนไข ชื่อป้ายกำกับอื่นๆ สามารถใช้แทน 'loop' ได้

ดังนั้น เช่นเดียวกับ 6502 µP ให้ใช้คำสั่งสาขาเพื่อให้มีการวนซ้ำกับ ARM 64

6.46 ARM 64 อินพุต/เอาต์พุต
อุปกรณ์ต่อพ่วง ARM ทั้งหมด (พอร์ตภายใน) ได้รับการแมปหน่วยความจำ ซึ่งหมายความว่าอินเทอร์เฟซการเขียนโปรแกรมคือชุดของรีจิสเตอร์ที่ระบุที่อยู่ของหน่วยความจำ (พอร์ตภายใน) ที่อยู่ของการลงทะเบียนดังกล่าวเป็นการชดเชยจากที่อยู่ฐานหน่วยความจำเฉพาะ สิ่งนี้คล้ายกับวิธีที่ 6502 ทำอินพุต/เอาท์พุต ARM ไม่มีตัวเลือกสำหรับพื้นที่ที่อยู่ I/O แยกกัน

6.47 สแต็คของ ARM 64
ARM 64 มีสแต็กในหน่วยความจำ (RAM) ในลักษณะเดียวกับที่ 6502 และ x64 มี อย่างไรก็ตาม สำหรับ ARM64 จะไม่มี opcode แบบพุชหรือป๊อป สแต็กใน ARM 64 ก็เพิ่มขึ้นเช่นกัน ที่อยู่ในตัวชี้สแต็กชี้หลังจากไบต์สุดท้ายของค่าสุดท้ายที่วางไว้ในสแต็ก

สาเหตุที่ไม่มีป๊อปโค้ดทั่วไปหรือพุช opcode สำหรับ ARM64 ก็คือ ARM 64 จัดการสแต็กในกลุ่มที่มีขนาด 16 ไบต์ติดต่อกัน อย่างไรก็ตาม ค่ามีอยู่ในกลุ่มไบต์ที่มีหนึ่งไบต์ สองไบต์ สี่ไบต์ และ 8 ไบต์ ดังนั้น สามารถวางค่าหนึ่งค่าลงในสแต็กได้ และส่วนที่เหลือ (ตำแหน่งไบต์) ที่จะรวมกันเป็น 16 ไบต์จะถูกเสริมด้วยไบต์จำลอง นี้มีข้อเสียของการสิ้นเปลืองหน่วยความจำ ทางออกที่ดีกว่าคือการเติมตำแหน่ง 16 ไบต์ด้วยค่าที่น้อยกว่าและมีโค้ดเขียนโปรแกรมเมอร์บางตัวที่ติดตามว่าค่าในตำแหน่ง 16 ไบต์มาจากไหน (รีจิสเตอร์) จำเป็นต้องใช้รหัสพิเศษนี้ในการดึงค่ากลับ อีกทางเลือกหนึ่งคือการกรอกรีจิสเตอร์วัตถุประสงค์ทั่วไปขนาด 8 ไบต์สองตัวด้วยค่าที่แตกต่างกัน จากนั้นส่งเนื้อหาของรีจิสเตอร์ขนาด 8 ไบต์สองตัวไปยังสแต็ก ยังจำเป็นต้องมีโค้ดพิเศษที่นี่เพื่อติดตามค่าเล็กๆ เฉพาะที่เข้าไปในสแต็กและออกจากสแต็ก

รหัสต่อไปนี้เก็บข้อมูลขนาด 4 ไบต์สี่รายการลงในสแต็ก:

STR W0, [sp, #-4]!
STR W1, [sp, #-8]!
STR W2, [sp, #-12]!
STR W3, [sp, #-16]!

สี่ไบต์แรก (w) ของรีจิสเตอร์ – x0, x1, x2 และ x3 – จะถูกส่งไปยังตำแหน่งไบต์ 16 ไบต์ติดต่อกันในสแต็ก สังเกตการใช้ 'str' ​​ไม่ใช่ 'push' สังเกตเครื่องหมายอัศเจรีย์ที่ส่วนท้ายของคำสั่งแต่ละคำสั่ง เนื่องจากสแต็กหน่วยความจำขยายลดลง ค่าสี่ไบต์แรกจึงเริ่มต้นที่ตำแหน่งซึ่งต่ำกว่าตำแหน่งตัวชี้สแต็กก่อนหน้าด้วยลบสี่ไบต์ ค่าสี่ไบต์ที่เหลือจะตามมา โดยลดลง ส่วนของโค้ดต่อไปนี้จะทำสิ่งที่ถูกต้อง (และตามลำดับ) ของการแตกไบต์สี่ไบต์:

ldr w3, [sp], #0
ldr w2, [sp], #4
ldr w1, [sp], #8
ldr w0, [sp], #12

สังเกตการใช้ ldr opcode แทน pop โปรดทราบว่าไม่ได้ใช้เครื่องหมายอัศเจรีย์ที่นี่

ไบต์ทั้งหมดใน X0 (8 ไบต์) และ X1 (8 ไบต์) สามารถส่งไปยังตำแหน่ง 16 ไบต์ในสแต็กได้ดังนี้:

ขั้น x0, x1, [sp, #-16]! ; 8 + 8 = 16

ในกรณีนี้ ไม่จำเป็นต้องลงทะเบียน x2 (w2) และ x3 (w3) ไบต์ที่ต้องการทั้งหมดอยู่ในรีจิสเตอร์ X0 และ X2 สังเกต stp opcode สำหรับจัดเก็บคู่ของเนื้อหารีจิสเตอร์ลงใน RAM โปรดสังเกตเครื่องหมายอัศเจรีย์ด้วย ป๊อปที่เทียบเท่าคือ:

ldp x0, x1, [sp], #0

ไม่มีเครื่องหมายอัศเจรีย์สำหรับคำสั่งนี้ สังเกต opcode LDP แทน LDR สำหรับการโหลดตำแหน่งข้อมูลสองตำแหน่งติดต่อกันจากหน่วยความจำไปยังรีจิสเตอร์ µP สองตัว นอกจากนี้ โปรดจำไว้ว่ากำลังโหลดการคัดลอกจากหน่วยความจำไปยังรีจิสเตอร์ µP อย่าสับสนกับการโหลดไฟล์จากดิสก์ไปยัง RAM และการคัดลอกจากรีจิสเตอร์ µP ไปยัง RAM ถือเป็นการจัดเก็บ

6.48 รูทีนย่อย
รูทีนย่อยคือบล็อกของโค้ดที่ทำงาน โดยขึ้นอยู่กับอาร์กิวเมนต์บางตัวและส่งคืนผลลัพธ์หรือไม่ก็ได้ ตามแบบแผน รีจิสเตอร์ R0 ถึง R3 (รีจิสเตอร์สี่ตัว) ใช้เพื่อส่งผ่านอาร์กิวเมนต์ (พารามิเตอร์) ไปยังรูทีนย่อย และ R0 ใช้เพื่อส่งผลลัพธ์กลับไปยังผู้เรียก รูทีนย่อยที่ต้องการอินพุตมากกว่า 4 อินพุตจะใช้สแต็กสำหรับอินพุตเพิ่มเติม หากต้องการเรียกรูทีนย่อย ให้ใช้ลิงก์หรือคำสั่งสาขาแบบมีเงื่อนไข ไวยากรณ์สำหรับคำสั่งลิงก์คือ:

ป้ายบีแอล

โดยที่ BL คือ opcode และเลเบลแสดงถึงจุดเริ่มต้น (ที่อยู่) ของรูทีนย่อย สาขานี้ไม่มีเงื่อนไข ไปข้างหน้าหรือข้างหลังภายใน 128MB ไวยากรณ์สำหรับคำสั่งสาขาแบบมีเงื่อนไขคือ:

ฉลากบีคอน

โดยที่ cond คือเงื่อนไข เช่น eq (เท่ากับ) หรือ ne (ไม่เท่ากัน) โปรแกรมต่อไปนี้มีรูทีนย่อย doadd ที่เพิ่มค่าของสองอาร์กิวเมนต์และส่งกลับผลลัพธ์เป็น R0:

พื้นที่ย่อย, รหัส, อ่านอย่างเดียว; ตั้งชื่อบล็อกของโค้ดนี้
รายการ ; ทำเครื่องหมายคำสั่งแรกที่จะดำเนินการ
เริ่ม MOV r0, #10 ; ตั้งค่าพารามิเตอร์
MOV r1, #3
BL ดูแอด ; เรียกรูทีนย่อย
หยุด MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; ARM semihosting (เดิมชื่อ SWI)
เพิ่มเพิ่ม r0, r0, r1 ; รหัสรูทีนย่อย
BX lr ; กลับจากรูทีนย่อย
;
จบ ; ทำเครื่องหมายจุดสิ้นสุดของไฟล์

ตัวเลขที่จะบวกคือทศนิยม 10 และทศนิยม 3 สองบรรทัดแรกในบล็อคโค้ด (โปรแกรม) นี้จะมีการอธิบายในภายหลัง สามบรรทัดถัดไปส่ง 10 ถึง R0 register และ 3 ถึง R1 register และยังเรียกรูทีนย่อย doadd ด้วย “doadd” คือป้ายกำกับที่เก็บที่อยู่ของจุดเริ่มต้นของรูทีนย่อย

รูทีนย่อยประกอบด้วยเพียงสองบรรทัด บรรทัดแรกจะเพิ่มเนื้อหา 3 ของ R ไปยังเนื้อหา 10 ของ R0 ซึ่งยอมให้ผลลัพธ์เป็น 13 ใน R0 บรรทัดที่สองที่มี BX opcode และตัวถูกดำเนินการ LR ส่งคืนจากรูทีนย่อยไปยังรหัสผู้โทร

ขวา
opcode RET ใน ARM 64 ยังคงเกี่ยวข้องกับรูทีนย่อย แต่ทำงานแตกต่างออกไปกับ RTS ใน 6502 หรือ RET บน x64 หรือการรวมกัน “BX LR” ใน ARM 64 ใน ARM 64 ไวยากรณ์สำหรับ RET คือ:

ตรง {Xn}

คำสั่งนี้เปิดโอกาสให้โปรแกรมดำเนินการต่อด้วยรูทีนย่อยที่ไม่ใช่รูทีนย่อยของผู้เรียก หรือเพียงดำเนินการต่อด้วยคำสั่งอื่นและส่วนของโค้ดต่อไปนี้ Xn เป็นรีจิสเตอร์เอนกประสงค์ที่เก็บที่อยู่ซึ่งโปรแกรมควรดำเนินการต่อ คำสั่งนี้แยกสาขาโดยไม่มีเงื่อนไข โดยค่าเริ่มต้นจะเป็นเนื้อหา X30 หากไม่ได้ระบุ Xn

มาตรฐานการโทรขั้นตอน
หากโปรแกรมเมอร์ต้องการให้โค้ดของเขาโต้ตอบกับโค้ดที่เขียนโดยบุคคลอื่นหรือกับโค้ดที่ผลิตโดยคอมไพเลอร์ โปรแกรมเมอร์จำเป็นต้องเห็นด้วยกับบุคคลหรือผู้เขียนคอมไพเลอร์เกี่ยวกับกฎสำหรับการใช้งานรีจิสเตอร์ สำหรับสถาปัตยกรรม ARM กฎเหล่านี้เรียกว่า Procedure Call Standard หรือ PCS เหล่านี้เป็นข้อตกลงระหว่างสองหรือสามฝ่าย PCS ระบุสิ่งต่อไปนี้:

  • รีจิสเตอร์ µP ใดที่ใช้ในการส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชัน (รูทีนย่อย)
  • รีจิสเตอร์ µP ใดที่ใช้ในการส่งคืนผลลัพธ์ไปยังฟังก์ชันที่ทำการเรียกซึ่งเรียกว่าผู้เรียก
  • ซึ่ง µP จะลงทะเบียนฟังก์ชันที่กำลังถูกเรียก ซึ่งเรียกว่าผู้เรียก อาจเสียหายได้
  • ซึ่ง µP ลงทะเบียนผู้ถูกเรียกจะไม่เสียหาย

6.49 ขัดจังหวะ
มีวงจรควบคุมการขัดจังหวะสองประเภทสำหรับโปรเซสเซอร์ ARM:

  • ตัวควบคุมอินเทอร์รัปต์มาตรฐาน: ตัวจัดการอินเทอร์รัปต์จะกำหนดว่าอุปกรณ์ใดต้องการการบริการ โดยการอ่านรีจิสเตอร์บิตแมปของอุปกรณ์ในตัวควบคุมอินเทอร์รัปต์
  • Vector Interrupt Controller (VIC): จัดลำดับความสำคัญของการขัดจังหวะและลดความซับซ้อนในการพิจารณาว่าอุปกรณ์ใดที่ทำให้เกิดการขัดจังหวะ หลังจากเชื่อมโยงลำดับความสำคัญและที่อยู่ตัวจัดการกับการขัดจังหวะแต่ละครั้ง VIC จะยืนยันสัญญาณขัดจังหวะไปยังโปรเซสเซอร์เท่านั้นหากลำดับความสำคัญของการขัดจังหวะใหม่สูงกว่าตัวจัดการขัดจังหวะที่กำลังดำเนินการอยู่ในปัจจุบัน

บันทึก : ข้อยกเว้นหมายถึงข้อผิดพลาด รายละเอียดสำหรับตัวควบคุมการขัดจังหวะเวกเตอร์สำหรับคอมพิวเตอร์ ARM 32 บิตมีดังต่อไปนี้ (64 บิตคล้ายกัน):

ตารางที่ 6.49.1
ARM Vector Exception/Interrupt สำหรับคอมพิวเตอร์ 32 บิต
ข้อยกเว้น/ขัดจังหวะ มือสั้น ที่อยู่ ที่อยู่สูง
รีเซ็ต รีเซ็ต 0x00000000 0xffff0000
คำสั่งที่ไม่ได้กำหนด UNDEF 0x00000004 0xffff0004
ซอฟต์แวร์ขัดจังหวะ สว 0x00000008 0xffff0008
ยกเลิกการดึงข้อมูลล่วงหน้า ปาบัต 0x0000000C 0xffff000C
วันที่ทำแท้ง ตบ 0x00000010 0xffff0010
ที่สงวนไว้ 0x00000014 0xffff0014
คำขอขัดจังหวะ IRQ 0x00000018 0xffff0018
คำขอขัดจังหวะอย่างรวดเร็ว เอฟไอคิว 0x0000001C 0xffff001C

ดูเหมือนการจัดเรียงสถาปัตยกรรม 6502 ตรงไหน เอ็นเอ็มไอ , บีอาร์ , และ IRQ สามารถมีพอยน์เตอร์ในหน้าศูนย์ และรูทีนที่เกี่ยวข้องจะมีหน่วยความจำสูง (ROM OS) คำอธิบายโดยย่อของแถวของตารางก่อนหน้ามีดังนี้:

รีเซ็ต
สิ่งนี้จะเกิดขึ้นเมื่อโปรเซสเซอร์เปิดเครื่อง เริ่มต้นระบบและตั้งค่าสแต็กสำหรับโหมดโปรเซสเซอร์ที่แตกต่างกัน เป็นข้อยกเว้นที่มีลำดับความสำคัญสูงสุด เมื่อเข้าสู่ตัวจัดการการรีเซ็ต CPSR จะอยู่ในโหมด SVC และทั้งบิต IRQ และ FIQ จะถูกตั้งค่าเป็น 1 เพื่อปกปิดการขัดจังหวะใดๆ

วันที่ทำแท้ง
ลำดับความสำคัญสูงสุดเป็นอันดับสอง สิ่งนี้เกิดขึ้นเมื่อเราพยายามอ่าน/เขียนลงในที่อยู่ที่ไม่ถูกต้องหรือเข้าถึงสิทธิ์การเข้าถึงที่ไม่ถูกต้อง เมื่อเข้าสู่ Data Abort Handler แล้ว IRQ จะถูกปิดใช้งาน (I-bit set 1) และ FIQ จะถูกเปิดใช้งาน IRQ ถูกปกปิด แต่ FIQ จะถูกปกปิด

เอฟไอคิว
การขัดจังหวะที่มีลำดับความสำคัญสูงสุด IRQ และ FIQ จะถูกปิดใช้งานจนกว่า FIQ จะได้รับการจัดการ

IRQ
การขัดจังหวะที่มีลำดับความสำคัญสูง ซึ่งก็คือตัวจัดการ IRQ จะถูกป้อนเฉพาะในกรณีที่ไม่มี FIQ ที่กำลังดำเนินอยู่และข้อมูลถูกยกเลิก

ยกเลิกการดึงข้อมูลล่วงหน้า
สิ่งนี้คล้ายกับการยกเลิกข้อมูล แต่เกิดขึ้นเมื่อการดึงที่อยู่ล้มเหลว เมื่อเข้าสู่ตัวจัดการ IRQ จะถูกปิดใช้งาน แต่ FIQ ยังคงเปิดใช้งานอยู่และอาจเกิดขึ้นได้ในระหว่างการยกเลิกการดึงข้อมูลล่วงหน้า

สว
ข้อยกเว้นของซอฟต์แวร์ขัดจังหวะ (SWI) เกิดขึ้นเมื่อดำเนินการคำสั่ง SWI และไม่มีข้อยกเว้นอื่นที่มีลำดับความสำคัญสูงกว่าถูกตั้งค่าสถานะ

คำสั่งที่ไม่ได้กำหนด
ข้อยกเว้นคำสั่งที่ไม่ได้กำหนดเกิดขึ้นเมื่อคำสั่งที่ไม่ได้อยู่ในชุดคำสั่ง ARM หรือ Thumb ถึงขั้นตอนการดำเนินการของไปป์ไลน์และไม่มีข้อยกเว้นอื่นใดที่ถูกตั้งค่าสถานะ นี่เป็นลำดับความสำคัญเดียวกันกับ SWI ที่สามารถเกิดขึ้นได้ในแต่ละครั้ง ซึ่งหมายความว่าคำสั่งที่กำลังดำเนินการไม่สามารถเป็นทั้งคำสั่ง SWI และคำสั่งที่ไม่ได้กำหนดในเวลาเดียวกันได้

การจัดการข้อยกเว้น ARM
เหตุการณ์ต่อไปนี้เกิดขึ้นเมื่อมีข้อยกเว้นเกิดขึ้น:

  • เก็บ CPSR ไปยัง SPSR ของโหมดข้อยกเว้น
  • พีซีถูกจัดเก็บไว้ใน LR ของโหมดข้อยกเว้น
  • การลงทะเบียนลิงค์ถูกตั้งค่าเป็นที่อยู่เฉพาะตามคำสั่งปัจจุบัน ตัวอย่างเช่น: สำหรับ ISR, LR = คำสั่งที่ดำเนินการล่าสุด + 8
  • อัพเดต CPSR เกี่ยวกับข้อยกเว้น
  • ตั้งค่าพีซีเป็นที่อยู่ของตัวจัดการข้อยกเว้น

6.5 คำแนะนำและข้อมูล

ข้อมูลอ้างอิงถึงตัวแปร (ป้ายกำกับที่มีค่า) และอาร์เรย์และโครงสร้างอื่นๆ ที่คล้ายกับอาร์เรย์ สตริงเป็นเหมือนอาร์เรย์ของอักขระ อาร์เรย์ของจำนวนเต็มมีให้เห็นในบทก่อนหน้าบทหนึ่ง คำแนะนำอ้างถึง opcodes และตัวถูกดำเนินการ โปรแกรมสามารถเขียนด้วย opcodes และข้อมูลที่ผสมกันในส่วนต่อเนื่องของหน่วยความจำ วิธีการดังกล่าวมีข้อเสียแต่ไม่แนะนำ

ควรเขียนโปรแกรมโดยมีคำสั่งก่อน ตามด้วยข้อมูล (พหูพจน์ของ datum คือ data) การแยกระหว่างคำสั่งและข้อมูลอาจมีขนาดเพียงไม่กี่ไบต์ สำหรับโปรแกรม ทั้งคำสั่งและข้อมูลสามารถอยู่ในส่วนแยกกันหนึ่งหรือสองส่วนในหน่วยความจำ

6.6 สถาปัตยกรรมฮาร์วาร์ด

คอมพิวเตอร์ในยุคแรกๆ เรียกว่า Harvard Mark I (1944) สถาปัตยกรรมฮาร์วาร์ดที่เข้มงวดใช้พื้นที่ที่อยู่เดียวสำหรับคำสั่งโปรแกรม และใช้พื้นที่ที่อยู่แยกต่างหากสำหรับข้อมูล ซึ่งหมายความว่ามีสองความทรงจำที่แยกจากกัน ต่อไปนี้จะแสดงสถาปัตยกรรม:


รูปที่ 6.71 สถาปัตยกรรมฮาร์วาร์ด

หน่วยควบคุมทำการถอดรหัสคำสั่ง หน่วยลอจิกเลขคณิต (ALU) ดำเนินการทางคณิตศาสตร์ด้วยตรรกะเชิงผสม (เกต) ALU ยังดำเนินการเชิงตรรกะด้วย (เช่น การขยับ)

ด้วยไมโครโปรเซสเซอร์ 6502 คำสั่งจะส่งไปที่ไมโครโปรเซสเซอร์ก่อน (หน่วยควบคุม) ก่อนที่ Datum (เอกพจน์สำหรับข้อมูล) จะถูกส่งไปยังรีจิสเตอร์ µP ก่อนที่จะโต้ตอบ ซึ่งจำเป็นต้องมีพัลส์นาฬิกาอย่างน้อยสองพัลส์ และไม่ใช่การเข้าถึงคำสั่งและ Datum พร้อมๆ กัน ในทางกลับกัน สถาปัตยกรรมของ Harvard ให้การเข้าถึงคำสั่งและข้อมูลไปพร้อมๆ กัน โดยทั้งคำสั่งและ Datum จะเข้าสู่ µP ในเวลาเดียวกัน (opcode ไปยังหน่วยควบคุมและ Datum ไปยัง µP register) ซึ่งช่วยประหยัดพัลส์นาฬิกาได้อย่างน้อยหนึ่งตัว นี่คือรูปแบบหนึ่งของความเท่าเทียม ความขนานรูปแบบนี้ใช้ในแคชฮาร์ดแวร์ในมาเธอร์บอร์ดสมัยใหม่ (โปรดดูการสนทนาต่อไปนี้)

6.7 หน่วยความจำแคช

หน่วยความจำแคช (RAM) เป็นพื้นที่หน่วยความจำความเร็วสูง (เมื่อเทียบกับความเร็วของหน่วยความจำหลัก) ที่จะจัดเก็บคำสั่งโปรแกรมหรือข้อมูลไว้ชั่วคราวเพื่อใช้ในอนาคต หน่วยความจำแคชทำงานเร็วกว่าหน่วยความจำหลัก โดยปกติแล้ว คำแนะนำหรือรายการข้อมูลเหล่านี้จะถูกดึงมาจากหน่วยความจำหลักล่าสุด และมีแนวโน้มที่จะจำเป็นต้องใช้อีกครั้งในไม่ช้า วัตถุประสงค์หลักของหน่วยความจำแคชคือเพื่อเพิ่มความเร็วในการเข้าถึงตำแหน่งหน่วยความจำหลักเดียวกันซ้ำๆ เพื่อให้มีประสิทธิภาพ การเข้าถึงรายการแคชจะต้องเร็วกว่าการเข้าถึงแหล่งต้นฉบับของคำสั่งหรือข้อมูลซึ่งเรียกว่า Backing Store อย่างมาก

เมื่อใช้แคช ความพยายามในการเข้าถึงตำแหน่งหน่วยความจำหลักแต่ละครั้งจะเริ่มต้นด้วยการค้นหาแคช หากมีรายการที่ร้องขอ ตัวประมวลผลจะดึงข้อมูลและใช้งานทันที สิ่งนี้เรียกว่า Cache Hit หากการค้นหาแคชไม่สำเร็จ (ไม่มีแคช) คำสั่งหรือรายการข้อมูลจะต้องถูกดึงมาจากที่เก็บข้อมูลสำรอง (หน่วยความจำหลัก) ในกระบวนการเรียกค้นรายการที่ร้องขอ สำเนาจะถูกเพิ่มลงในแคชสำหรับการใช้งานที่คาดว่าจะเกิดขึ้นในอนาคตอันใกล้นี้

หน่วยการจัดการหน่วยความจำ
Memory Management Unit (MMU) เป็นวงจรที่จัดการหน่วยความจำหลักและการลงทะเบียนหน่วยความจำที่เกี่ยวข้องบนเมนบอร์ด สมัยก่อนจะเป็นวงจรรวมบนเมนบอร์ดแยกกัน แต่ทุกวันนี้มันมักจะเป็นส่วนหนึ่งของไมโครโปรเซสเซอร์ MMU ควรจัดการแคช (วงจร) ซึ่งเป็นส่วนหนึ่งของไมโครโปรเซสเซอร์ในปัจจุบันด้วย วงจรแคชเป็นวงจรรวมที่แยกจากกันในอดีต

แรมแบบคงที่
Static RAM (SRAM) มีเวลาในการเข้าถึงเร็วกว่า DRAM อย่างมาก แม้ว่าจะมีวงจรที่ซับซ้อนกว่ามากก็ตาม เซลล์บิตของ SRAM ใช้พื้นที่บนวงจรรวมมากกว่าเซลล์ของอุปกรณ์ DRAM ที่สามารถจัดเก็บข้อมูลในปริมาณที่เท่ากันได้ หน่วยความจำหลัก (RAM) โดยทั่วไปประกอบด้วย DRAM (Dynamic RAM)

หน่วยความจำแคชช่วยปรับปรุงประสิทธิภาพของคอมพิวเตอร์เนื่องจากอัลกอริธึมจำนวนมากที่ดำเนินการโดยระบบปฏิบัติการและแอพพลิเคชั่นแสดงตำแหน่งที่อ้างอิง สถานที่อ้างอิงหมายถึงการนำข้อมูลที่มีการเข้าถึงกลับมาใช้ซ้ำเมื่อเร็วๆ นี้ สิ่งนี้เรียกว่าสถานที่ชั่วคราว บนมาเธอร์บอร์ดสมัยใหม่ หน่วยความจำแคชจะอยู่ในวงจรรวมเดียวกันกับไมโครโปรเซสเซอร์ หน่วยความจำหลัก (DRAM) อยู่ไกลและสามารถเข้าถึงได้โดยรถประจำทาง สถานที่อ้างอิงยังหมายถึงสถานที่เชิงพื้นที่ด้วย ตำแหน่งเชิงพื้นที่เกี่ยวข้องกับความเร็วที่สูงขึ้นของการเข้าถึงข้อมูลเนื่องจากความใกล้ชิดทางกายภาพ

ตามกฎแล้ว พื้นที่หน่วยความจำแคชมีขนาดเล็ก (ในจำนวนตำแหน่งไบต์) เมื่อเปรียบเทียบกับที่เก็บสำรอง (หน่วยความจำหลัก) อุปกรณ์หน่วยความจำแคชได้รับการออกแบบให้มีความเร็วสูงสุด ซึ่งโดยทั่วไปหมายความว่าอุปกรณ์เหล่านี้มีความซับซ้อนและมีค่าใช้จ่ายต่อบิตมากกว่าเทคโนโลยีจัดเก็บข้อมูลที่ใช้ในที่จัดเก็บสำรอง เนื่องจากขนาดที่จำกัด อุปกรณ์หน่วยความจำแคชจึงมีแนวโน้มที่จะเต็มอย่างรวดเร็ว เมื่อแคชไม่มีตำแหน่งที่พร้อมใช้งานสำหรับจัดเก็บรายการใหม่ จะต้องละทิ้งรายการที่เก่ากว่า ตัวควบคุมแคชใช้นโยบายการแทนที่แคชเพื่อเลือกรายการแคชที่จะถูกเขียนทับโดยรายการใหม่

เป้าหมายของหน่วยความจำแคชของไมโครโปรเซสเซอร์คือการเพิ่มเปอร์เซ็นต์ของการเข้าถึงแคชให้สูงสุดเมื่อเวลาผ่านไป จึงทำให้มีอัตราการดำเนินการคำสั่งที่ยั่งยืนสูงสุด เพื่อให้บรรลุวัตถุประสงค์นี้ ลอจิกแคชจะต้องกำหนดว่าคำสั่งและข้อมูลใดจะถูกวางลงในแคชและเก็บรักษาไว้เพื่อใช้ในอนาคตอันใกล้นี้

ตรรกะการแคชของโปรเซสเซอร์ไม่รับประกันว่ารายการข้อมูลที่แคชไว้จะถูกนำมาใช้อีกครั้งเมื่อถูกแทรกลงในแคช

ตรรกะของการแคชขึ้นอยู่กับความเป็นไปได้ว่าเนื่องจากตำแหน่งชั่วคราว (ที่เกิดซ้ำเมื่อเวลาผ่านไป) และตำแหน่งเชิงพื้นที่ (อวกาศ) จึงมีโอกาสที่ดีมากที่ข้อมูลที่แคชไว้จะเข้าถึงได้ในอนาคตอันใกล้นี้ ในการใช้งานจริงบนโปรเซสเซอร์สมัยใหม่ ปัญหาแคชมักเกิดขึ้นที่ 95 ถึง 97 เปอร์เซ็นต์ของการเข้าถึงหน่วยความจำ เนื่องจากเวลาแฝงของหน่วยความจำแคชเป็นเพียงเศษเสี้ยวเล็กน้อยของเวลาแฝงของ DRAM อัตราการเข้าถึงแคชที่สูงจึงทำให้ประสิทธิภาพดีขึ้นอย่างมากเมื่อเปรียบเทียบกับการออกแบบที่ปราศจากแคช

ความคล้ายคลึงกับแคชบางอย่าง
ตามที่กล่าวไว้ข้างต้น โปรแกรมที่ดีในหน่วยความจำจะมีคำสั่งแยกจากข้อมูล ในระบบแคชบางระบบ จะมีวงจรแคชอยู่ที่ “ซ้าย” ของโปรเซสเซอร์ และมีวงจรแคชอีกวงจรอยู่ที่ “ขวา” ของโปรเซสเซอร์ แคชด้านซ้ายจัดการคำสั่งของโปรแกรม (หรือแอปพลิเคชัน) และแคชด้านขวาจัดการข้อมูลของโปรแกรมเดียวกัน (หรือแอปพลิเคชันเดียวกัน) สิ่งนี้นำไปสู่ความเร็วที่เพิ่มขึ้นที่ดีขึ้น

6.8 กระบวนการและเธรด

ทั้งคอมพิวเตอร์ CISC และ RISC มีกระบวนการ กระบวนการอยู่บนซอฟต์แวร์ โปรแกรมที่กำลังรัน (รัน) อยู่เป็นกระบวนการ ระบบปฏิบัติการมาพร้อมกับโปรแกรมของตัวเอง ขณะที่คอมพิวเตอร์กำลังทำงาน โปรแกรมต่างๆ ของระบบปฏิบัติการที่ช่วยให้คอมพิวเตอร์ทำงานได้ก็กำลังทำงานอยู่เช่นกัน เหล่านี้เป็นกระบวนการของระบบปฏิบัติการ ผู้ใช้หรือโปรแกรมเมอร์สามารถเขียนโปรแกรมของตนเองได้ เมื่อโปรแกรมของผู้ใช้กำลังทำงานอยู่ มันเป็นกระบวนการ ไม่สำคัญว่าโปรแกรมจะเขียนด้วยภาษาแอสเซมบลีหรือภาษาระดับสูงเช่น C หรือ C++ กระบวนการทั้งหมด (ผู้ใช้หรือระบบปฏิบัติการ) ได้รับการจัดการโดยกระบวนการอื่นที่เรียกว่า “ตัวกำหนดเวลา”

เธรดเป็นเหมือนกระบวนการย่อยที่เป็นของกระบวนการ กระบวนการสามารถเริ่มต้นและแยกออกเป็นเธรด จากนั้นยังคงดำเนินต่อไปเป็นกระบวนการเดียว กระบวนการที่ไม่มีเธรดถือได้ว่าเป็นเธรดหลัก กระบวนการและเธรดได้รับการจัดการโดยตัวกำหนดเวลาเดียวกัน ตัวกำหนดตารางเวลานั้นเป็นโปรแกรมเมื่ออยู่ในดิสก์ระบบปฏิบัติการ เมื่อทำงานในหน่วยความจำ ตัวกำหนดเวลาจะเป็นกระบวนการ

6.9 การประมวลผลหลายตัว

เธรดได้รับการจัดการเกือบเหมือนกับกระบวนการ การประมวลผลหลายตัวหมายถึงการรันมากกว่าหนึ่งกระบวนการในเวลาเดียวกัน มีคอมพิวเตอร์ที่มีไมโครโปรเซสเซอร์เพียงตัวเดียว มีคอมพิวเตอร์ที่มีไมโครโปรเซสเซอร์มากกว่าหนึ่งตัว ด้วยไมโครโปรเซสเซอร์ตัวเดียว กระบวนการและ/หรือเธรดจะใช้ไมโครโปรเซสเซอร์ตัวเดียวกันในลักษณะที่มีการสลับกัน (หรือการแบ่งเวลา) นั่นหมายความว่ากระบวนการใช้โปรเซสเซอร์และหยุดทำงานโดยไม่เสร็จสิ้น กระบวนการหรือเธรดอื่นใช้ตัวประมวลผลและหยุดทำงานโดยไม่เสร็จสิ้น จากนั้น กระบวนการหรือเธรดอื่นจะใช้ไมโครโปรเซสเซอร์และหยุดทำงานโดยไม่เสร็จสิ้น สิ่งนี้จะดำเนินต่อไปจนกว่ากระบวนการและเธรดทั้งหมดที่ถูกจัดคิวโดยตัวกำหนดตารางเวลาจะมีส่วนแบ่งของตัวประมวลผล สิ่งนี้เรียกว่าการประมวลผลหลายตัวพร้อมกัน

เมื่อมีไมโครโปรเซสเซอร์มากกว่าหนึ่งตัว จะมีการประมวลผลหลายตัวแบบขนาน ซึ่งตรงข้ามกับการทำงานพร้อมกัน ในกรณีนี้ โปรเซสเซอร์แต่ละตัวจะรันกระบวนการหรือเธรดเฉพาะ แตกต่างจากที่โปรเซสเซอร์อื่นกำลังทำงานอยู่ โปรเซสเซอร์ทั้งหมดบนเมนบอร์ดเดียวกันรันกระบวนการที่แตกต่างกันและ/หรือเธรดที่แตกต่างกันในเวลาเดียวกันในการประมวลผลหลายตัวแบบขนาน กระบวนการและเธรดในการประมวลผลหลายตัวแบบขนานยังคงได้รับการจัดการโดยตัวกำหนดตารางเวลา การประมวลผลหลายตัวแบบขนานนั้นเร็วกว่าการประมวลผลหลายตัวพร้อมกัน

ณ จุดนี้ ผู้อ่านอาจสงสัยว่าการประมวลผลแบบขนานนั้นเร็วกว่าการประมวลผลพร้อมกันอย่างไร เนื่องจากโปรเซสเซอร์แชร์ (ต้องใช้ในเวลาต่างกัน) หน่วยความจำและพอร์ตอินพุต/เอาท์พุตเดียวกัน ด้วยการใช้แคชทำให้การทำงานโดยรวมของเมนบอร์ดเร็วขึ้น

6.10 เพจจิ้ง

Memory Management Unit (MMU) เป็นวงจรที่อยู่ใกล้กับไมโครโปรเซสเซอร์หรือในชิปไมโครโปรเซสเซอร์ จะจัดการแมปหน่วยความจำหรือเพจและปัญหาหน่วยความจำอื่นๆ ทั้งคอมพิวเตอร์ 6502 µP และ Commodore-64 ไม่มี MMU ในตัว (แม้ว่าจะยังคงมีการจัดการหน่วยความจำบางส่วนใน Commodore-64) Commodore-64 จัดการหน่วยความจำโดยการแบ่งหน้าโดยแต่ละหน้าคือ 256 10 ไบต์ยาว (100 16 ยาวเป็นไบต์) ไม่จำเป็นต้องจัดการหน่วยความจำโดยการเพจ มันยังคงมีแผนที่หน่วยความจำและโปรแกรมที่พอดีกับพื้นที่ที่กำหนดที่แตกต่างกัน เพจจิ้งเป็นวิธีหนึ่งในการใช้หน่วยความจำอย่างมีประสิทธิภาพโดยไม่ต้องมีส่วนหน่วยความจำจำนวนมากที่ไม่สามารถมีข้อมูลหรือโปรแกรมได้

สถาปัตยกรรมคอมพิวเตอร์ x86 386 เปิดตัวในปี 1985 แอดเดรสบัสมีความกว้าง 32 บิต ดังนั้นรวมเป็น 2 32 = พื้นที่ที่อยู่ 4,294,967,296 เป็นไปได้ พื้นที่ที่อยู่นี้แบ่งออกเป็น 1,048,576 หน้า = 1,024 KB หน้า ด้วยจำนวนเพจนี้ หนึ่งเพจจะประกอบด้วย 4,096 ไบต์ = 4 KB ตารางต่อไปนี้แสดงเพจที่อยู่จริงสำหรับสถาปัตยกรรม x86 32 บิต:

ตารางที่ 6.10.1
หน้าที่อยู่ทางกายภาพสำหรับสถาปัตยกรรม x86
ที่อยู่ฐาน 16 หน้า ที่อยู่ฐาน 10
FFFFF000 – FFFFFFFF หน้า 1,048,575 4,294,963,200 – 4,294,967,295
FFFFE000 – FFFFFFFF หน้า 1,044,479 4,294,959,104 – 4,294,963,199
FFFFD000 – FFFFDFFF หน้า 1,040,383 4,294,955,008 – 4,294,959,103
|
|
|
|
|
|
|
|
|
00002000 – 00002FFF หน้า 2 8,192 – 12,288
00001000 – 00001FFF หน้า 1 4,096 – 8,191
00000000 – 00000FFF หน้า 0 0 – 4,095

แอปพลิเคชันในปัจจุบันประกอบด้วยมากกว่าหนึ่งโปรแกรม โปรแกรมหนึ่งอาจใช้เวลาน้อยกว่าหนึ่งเพจ (น้อยกว่า 4096) หรืออาจใช้เวลาสองเพจขึ้นไป ดังนั้น แอปพลิเคชันสามารถรับหนึ่งเพจขึ้นไปโดยแต่ละเพจมีความยาว 4096 ไบต์ แต่ละคนสามารถเขียนใบสมัครได้ โดยแต่ละคนจะได้รับมอบหมายให้ทำหน้าตั้งแต่หนึ่งหน้าขึ้นไป

โปรดสังเกตว่าหน้า 0 อยู่ระหว่าง 00000000H ถึง 00000FFF
หน้าที่ 1 คือตั้งแต่ 00001000H ถึง 00001FFFH หน้าที่ 2 คือตั้งแต่ 00002000 ชม – 00002FFF ชม และอื่นๆ สำหรับคอมพิวเตอร์ 32 บิต มีรีจิสเตอร์ 32 บิตสองตัวในโปรเซสเซอร์สำหรับการกำหนดแอดเดรสเพจจริง: อันหนึ่งสำหรับที่อยู่ฐานและอีกอันสำหรับที่อยู่ดัชนี ในการเข้าถึงตำแหน่งไบต์ของเพจ 2 เช่น การลงทะเบียนสำหรับที่อยู่ฐานควรเป็น 00002 ชม ซึ่งเป็น 20 บิตแรก (จากซ้าย) สำหรับที่อยู่เริ่มต้นของหน้าที่ 2 บิตที่เหลือในช่วง 000 ชม ถึง FFF ชม อยู่ในทะเบียนที่เรียกว่า “ทะเบียนดัชนี” ดังนั้น สามารถเข้าถึงไบต์ทั้งหมดในเพจได้โดยเพียงแค่เพิ่มเนื้อหาในการลงทะเบียนดัชนีจาก 000 ชม ถึง FFF ชม . เนื้อหาในการลงทะเบียนดัชนีจะถูกเพิ่มเข้าไปในเนื้อหาซึ่งไม่มีการเปลี่ยนแปลงในการลงทะเบียนฐานเพื่อให้ได้ที่อยู่ที่มีประสิทธิภาพ รูปแบบการกำหนดที่อยู่ดัชนีนี้ใช้ได้กับหน้าอื่นๆ

อย่างไรก็ตาม นี่ไม่ใช่วิธีการเขียนโปรแกรมภาษาแอสเซมบลีสำหรับแต่ละหน้าจริงๆ สำหรับแต่ละหน้าโปรแกรมเมอร์จะเขียนโค้ดเริ่มต้นจากหน้า 000 ชม ไปที่หน้า FFF ชม . เนื่องจากโค้ดในหน้าต่างๆ เชื่อมต่อกัน คอมไพเลอร์จึงใช้การกำหนดแอดเดรสดัชนีเพื่อเชื่อมต่อที่อยู่ที่เกี่ยวข้องทั้งหมดในหน้าต่างๆ ตัวอย่างเช่น สมมติว่าเพจ 0, เพจ 1 และเพจ 2 มีไว้สำหรับแอปพลิเคชันเดียว และแต่ละแอปพลิเคชันมี 555 ชม ที่อยู่ที่เชื่อมต่อถึงกันคอมไพลเลอร์จะคอมไพล์ในลักษณะที่เมื่อ 555 ชม ของหน้า 0 จะต้องเข้าถึงได้ 00000 ชม จะอยู่ในทะเบียนฐานและ 555 ชม จะอยู่ในทะเบียนดัชนี เมื่อ 555 ชม ของหน้าที่ 1 จะต้องเข้าถึงได้ 00001 ชม จะอยู่ในทะเบียนฐานและ 555 ชม จะอยู่ในทะเบียนดัชนี เมื่อ 555 ชม ของหน้าที่ 2 จะสามารถเข้าถึงได้ 00002 ชม จะอยู่ในการลงทะเบียนฐานและ 555H จะอยู่ในการลงทะเบียนดัชนี สิ่งนี้เป็นไปได้เนื่องจากที่อยู่สามารถระบุได้โดยใช้ป้ายกำกับ (ตัวแปร) โปรแกรมเมอร์ที่แตกต่างกันจะต้องตกลงเกี่ยวกับชื่อของป้ายกำกับที่จะใช้สำหรับที่อยู่การเชื่อมต่อที่แตกต่างกัน

หน่วยความจำเสมือนเพจ
เพจตามที่อธิบายไว้ก่อนหน้านี้สามารถแก้ไขได้เพื่อเพิ่มขนาดของหน่วยความจำในเทคนิคที่เรียกว่า 'Page Virtual Memory' สมมติว่าเพจหน่วยความจำฟิสิคัลทั้งหมดตามที่อธิบายไว้ก่อนหน้านี้ มีบางอย่าง (คำแนะนำและข้อมูล) ไม่ใช่ทุกเพจที่ใช้งานอยู่ในปัจจุบัน เพจที่ไม่ได้ใช้งานอยู่ในปัจจุบันจะถูกส่งไปยังฮาร์ดดิสก์และถูกแทนที่ด้วยเพจจากฮาร์ดดิสก์ที่ต้องใช้งาน ด้วยวิธีนี้ขนาดของหน่วยความจำจะเพิ่มขึ้น ในขณะที่คอมพิวเตอร์ทำงานต่อไป เพจที่ไม่ได้ใช้งานจะถูกสลับกับเพจในฮาร์ดดิสก์ซึ่งอาจยังคงเป็นเพจที่ถูกส่งจากหน่วยความจำไปยังดิสก์ ทั้งหมดนี้ทำโดย Memory Management Unit (MMU)

6.11 ปัญหา

ผู้อ่านควรแก้ไขปัญหาทั้งหมดในบทก่อนที่จะไปยังบทถัดไป

1) ให้ความเหมือนและความแตกต่างของสถาปัตยกรรมคอมพิวเตอร์ CISC และ RISC ตั้งชื่อตัวอย่างหนึ่งของคอมพิวเตอร์ SISC และ RISC แต่ละเครื่อง

2) a) ชื่อต่อไปนี้สำหรับคอมพิวเตอร์ CISC ในรูปของบิต: ไบต์, คำ, ดับเบิลเวิร์ด, ควอดเวิร์ด และควอดเวิร์ดคู่
b) ชื่อต่อไปนี้สำหรับคอมพิวเตอร์ RISC ในรูปของบิต: ไบต์, ฮาล์ฟเวิร์ด, คำ และดับเบิลเวิร์ด
c) ใช่หรือไม่ใช่ doubleword และ quadword มีความหมายเหมือนกันในสถาปัตยกรรม CISC และ RISC หรือไม่

3 a) สำหรับ x64 จำนวนไบต์สำหรับคำสั่งภาษาแอสเซมบลีมีตั้งแต่อะไรถึงอะไร?
b) จำนวนไบต์สำหรับคำสั่งภาษาแอสเซมบลีทั้งหมดสำหรับ ARM 64 คงที่หรือไม่ ถ้าใช่ จำนวนไบต์สำหรับคำสั่งทั้งหมดคือเท่าใด

4) แสดงรายการคำแนะนำภาษาแอสเซมบลีที่ใช้บ่อยที่สุดสำหรับ x64 และความหมาย

5) แสดงรายการคำแนะนำภาษาแอสเซมบลีที่ใช้บ่อยที่สุดสำหรับ ARM 64 และความหมาย

6) วาดแผนภาพบล็อกที่มีป้ายกำกับของคอมพิวเตอร์เครื่องเก่า Harvard Architecture อธิบายว่าคำแนะนำและคุณลักษณะข้อมูลถูกนำมาใช้ในแคชของคอมพิวเตอร์สมัยใหม่อย่างไร

7) แยกความแตกต่างระหว่างกระบวนการและเธรด และตั้งชื่อกระบวนการที่จัดการกระบวนการและเธรดในระบบคอมพิวเตอร์ส่วนใหญ่

8) อธิบายสั้นๆ ว่ามัลติโพรเซสซิงคืออะไร

9) a) อธิบายเพจจิ้งที่ใช้กับสถาปัตยกรรมคอมพิวเตอร์ x86 386 µP
b) เพจนี้สามารถปรับเปลี่ยนเพื่อเพิ่มขนาดของหน่วยความจำทั้งหมดได้อย่างไร