บทที่ 5: ระบบปฏิบัติการ Commodore-64 ในภาษา Assembly

Bth Thi 5 Rabb Ptibati Kar Commodore 64 Ni Phas A Assembly



5.1 บทนำ

ระบบปฏิบัติการสำหรับคอมพิวเตอร์ Commodore-64 มาพร้อมกับคอมพิวเตอร์ใน Read Only Memory (ROM) จำนวนตำแหน่งไบต์หน่วยความจำสำหรับ Commodore-64 มีตั้งแต่ 0,000 ดอลลาร์ถึง FFFF (เช่น 000016 ถึง FFFF16 ซึ่งก็คือ 010 ถึง 65,53510) ระบบปฏิบัติการมีตั้งแต่ $E000 ถึง $FFFF (เช่น 57,34410 ถึง 65,53610)

ทำไมต้องศึกษาระบบปฏิบัติการ Commodore-64
ทำไมต้องศึกษาระบบปฏิบัติการ Commodore-64 ในปัจจุบัน ในเมื่อเป็นระบบปฏิบัติการของคอมพิวเตอร์ที่เปิดตัวในปี 1982 คอมพิวเตอร์ Commodore-64 ใช้หน่วยประมวลผลกลาง 6510 ซึ่งเป็นการอัพเกรด (แม้ว่าจะไม่ใช่การอัพเกรดครั้งใหญ่) ของ 6502 µP







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



65C02 µP ซึ่งยังคงเป็นคลาสไมโครโปรเซสเซอร์ 6502 มีคำสั่งภาษาแอสเซมบลี 66 คำสั่ง ซึ่งทั้งหมดนี้สามารถเรียนรู้ได้ด้วยใจจริง ไมโครโปรเซสเซอร์สมัยใหม่มีคำสั่งภาษาแอสเซมบลีมากมายและไม่สามารถเรียนรู้ได้ด้วยใจ µP แต่ละตัวมีภาษาแอสเซมบลีของตัวเอง ระบบปฏิบัติการใดๆ ไม่ว่าจะเป็นระบบปฏิบัติการใหม่หรือเก่าเป็นภาษาแอสเซมบลี ด้วยเหตุนี้ ภาษาแอสเซมบลี 6502 จึงเหมาะที่จะใช้สอนระบบปฏิบัติการสำหรับผู้เริ่มต้น หลังจากเรียนรู้ระบบปฏิบัติการ เช่น ระบบปฏิบัติการสำหรับ Commodore-64 แล้ว ระบบปฏิบัติการสมัยใหม่ก็สามารถเรียนรู้ได้อย่างง่ายดายโดยใช้ระบบปฏิบัติการนั้นเป็นพื้นฐาน



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





บันทึก : Commodore-64 OS (Kernal) ยังคงทำงานได้ดีกับอุปกรณ์อินพุตและเอาต์พุตสมัยใหม่ (ไม่ใช่ทั้งหมด)

คอมพิวเตอร์แปดบิต
ในไมโครคอมพิวเตอร์ขนาด 8 บิต เช่น Commodore 64 ข้อมูลจะถูกจัดเก็บ ถ่ายโอน และจัดการในรูปแบบของรหัสไบนารี่ 8 บิต



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

แผนที่หน่วยความจำ (เค้าโครง) ในบทที่แล้วมีรายละเอียดไม่เพียงพอ มันค่อนข้างง่าย แผนที่หน่วยความจำของคอมพิวเตอร์ Commodore-64 สามารถแสดงรายละเอียดได้สามระดับ เมื่อแสดงในระดับกลาง คอมพิวเตอร์ Commodore-64 จะมีแผนผังหน่วยความจำที่แตกต่างกัน แผนที่หน่วยความจำเริ่มต้นของคอมพิวเตอร์ Commodore-64 ในระดับกลางคือ:


มะเดื่อ 5.11 แผนที่หน่วยความจำ Commodore-64

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

โปรดสังเกตว่าหน่วยความจำส่วนใหญ่ถูกใช้โดย BASIC ในแผนผังหน่วยความจำเริ่มต้น BASIC มีคำสั่ง (คำแนะนำ) ซึ่งดำเนินการโดยสิ่งที่เรียกว่า BASIC Interpreter ในความเป็นจริงล่าม BASIC อยู่ใน ROM จากตำแหน่ง $A000 ถึง $BFFF (รวม) ซึ่งควรจะเป็นพื้นที่ RAM นี่คือ 8 Kbytes ซึ่งค่อนข้างใหญ่ในขณะนั้น! ที่จริงแล้วมันอยู่ใน ROM ณ ตำแหน่งนั้นของหน่วยความจำทั้งหมด มีขนาดเท่ากับระบบปฏิบัติการตั้งแต่ $E000 ถึง $FFFF (รวม) โปรแกรมที่เขียนด้วยภาษา BASIC ก็อยู่ในช่วง $0200 ถึง $BFFF เช่นกัน

RAM สำหรับโปรแกรมภาษาแอสเซมบลีของผู้ใช้มีราคาตั้งแต่ $C000 ถึง $CFFF เพียง 4 Kbytes จาก 64 Kbytes แล้วทำไมเราถึงใช้หรือเรียนรู้ภาษาแอสเซมบลี? ระบบปฏิบัติการใหม่และเก่าเป็นภาษาแอสเซมบลี ระบบปฏิบัติการของ Commodore-64 อยู่ใน ROM ตั้งแต่ $E000 ถึง $FFFF เขียนด้วยภาษาแอสเซมบลี 65C02 µP (6510 µP) ประกอบด้วยรูทีนย่อย โปรแกรมผู้ใช้ในภาษาแอสเซมบลีจำเป็นต้องเรียกรูทีนย่อยเหล่านี้เพื่อโต้ตอบกับอุปกรณ์ต่อพ่วง (อุปกรณ์อินพุตและเอาต์พุต) การทำความเข้าใจระบบปฏิบัติการ Commodore-64 ในภาษาแอสเซมบลีช่วยให้นักเรียนเข้าใจระบบปฏิบัติการได้อย่างรวดเร็ว ในลักษณะที่น่าเบื่อน้อยกว่ามาก ขอย้ำอีกครั้งว่าในสมัยนั้น โปรแกรมผู้ใช้จำนวนมากสำหรับ Commodore-64 เขียนด้วยภาษาเบสิก ไม่ใช่ภาษาแอสเซมบลี ภาษาแอสเซมบลีในสมัยนั้นถูกใช้โดยโปรแกรมเมอร์เองมากขึ้นเพื่อจุดประสงค์ทางเทคนิค

Kernal ซึ่งสะกดว่า K-e-r-n-a-l เป็นระบบปฏิบัติการของ Commodore-64 มันมาพร้อมกับคอมพิวเตอร์ Commodore-64 ใน ROM ไม่ใช่ในดิสก์ (หรือดิสเก็ตต์) Kernal ประกอบด้วยรูทีนย่อย ในการเข้าถึงอุปกรณ์ต่อพ่วง โปรแกรมผู้ใช้ในภาษาแอสเซมบลี (ภาษาเครื่อง) ต้องใช้รูทีนย่อยเหล่านี้ ไม่ควรสับสนระหว่าง Kernal กับ Kernel ซึ่งสะกดเป็น K-e-r-n-e-l ของระบบปฏิบัติการสมัยใหม่ แม้ว่าจะแทบจะเป็นสิ่งเดียวกันก็ตาม

พื้นที่หน่วยความจำตั้งแต่ $C000 (49,15210) ถึง $CFFF (6324810) จาก 4 Kbytes10 ของหน่วยความจำเป็น RAM หรือ ROM เมื่อเป็น RAM จะใช้เข้าถึงอุปกรณ์ต่อพ่วง เมื่อเป็น ROM จะใช้พิมพ์ตัวอักษรบนหน้าจอ (จอภาพ) ซึ่งหมายความว่ากำลังพิมพ์อักขระบนหน้าจอหรือเข้าถึงอุปกรณ์ต่อพ่วงโดยใช้หน่วยความจำส่วนนี้ มี ROM จำนวนมาก (ROM อักขระ) ในยูนิตระบบ (มาเธอร์บอร์ด) ซึ่งสลับเข้าและออกจากพื้นที่หน่วยความจำทั้งหมดเพื่อให้บรรลุเป้าหมายดังกล่าว ผู้ใช้อาจไม่สังเกตเห็นการสลับ

พื้นที่หน่วยความจำเริ่มต้นที่ 0100 ดอลลาร์ (256 10 ) ถึง $01FF (511 10 ) คือสแต็ก มันถูกใช้โดยทั้งระบบปฏิบัติการและโปรแกรมผู้ใช้ บทบาทของกลุ่มได้อธิบายไว้ในบทที่แล้วของหลักสูตรอาชีพออนไลน์นี้ พื้นที่ของหน่วยความจำตั้งแต่ $0,000 (0 10 ) ถึง $00FF (255 10 ) ถูกใช้โดยระบบปฏิบัติการ มีการกำหนดพอยน์เตอร์หลายตัวไว้ที่นั่น

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

ที่อยู่แรกของรายการมีคำสั่ง JSR ที่อยู่สองรายการถัดไปประกอบด้วยตัวชี้แบบสองไบต์ ตัวชี้แบบสองไบต์นี้คือที่อยู่ (หรือที่อยู่ใหม่) ของรูทีนจริงซึ่งยังอยู่ใน OS ROM เนื้อหาตัวชี้อาจเปลี่ยนแปลงได้ด้วยระบบปฏิบัติการเวอร์ชันใหม่ แต่ที่อยู่สามรายการสำหรับรายการ Jump Table แต่ละรายการจะไม่เปลี่ยนแปลง ตัวอย่างเช่น พิจารณาที่อยู่ $FF81, $FF82 และ $FF83 ที่อยู่ทั้งสามนี้มีไว้สำหรับรูทีนในการเริ่มต้นวงจรหน้าจอและคีย์บอร์ด (รีจิสเตอร์) ของเมนบอร์ด ที่อยู่ $FF81 จะมีรหัส op (หนึ่งไบต์) ของ JSR เสมอ ที่อยู่ $FF82 และ $FF83 มีที่อยู่เก่าหรือใหม่ของรูทีนย่อย (ยังอยู่ใน OS ROM) เพื่อดำเนินการเริ่มต้น ครั้งหนึ่ง ที่อยู่ $FF82 และ $FF83 มีเนื้อหา (ที่อยู่) เป็น $FF5B ซึ่งสามารถเปลี่ยนแปลงได้ในระบบปฏิบัติการเวอร์ชันถัดไป อย่างไรก็ตาม ที่อยู่ $FF81, $FF82 และ $FF83 ของตารางข้ามจะไม่เปลี่ยนแปลง

สำหรับแต่ละรายการในสามที่อยู่ ที่อยู่แรกที่มี JSR จะมีป้ายกำกับ (ชื่อ) ป้ายราคา $FF81 คือ PCINT PCINT ไม่เคยเปลี่ยนแปลง ดังนั้น ในการเริ่มต้นการลงทะเบียนหน้าจอและคีย์บอร์ด โปรแกรมเมอร์สามารถพิมพ์ “JSR PCINT” ซึ่งใช้ได้กับ Commodore-64 OS ทุกเวอร์ชัน ตำแหน่ง (ที่อยู่เริ่มต้น) ของรูทีนย่อยจริง เช่น $FF5B อาจเปลี่ยนแปลงเมื่อเวลาผ่านไปด้วยระบบปฏิบัติการที่แตกต่างกัน ใช่ มีคำสั่ง JSR อย่างน้อยสองคำสั่งที่เกี่ยวข้องกับโปรแกรมผู้ใช้ที่ใช้ ROM OS ในโปรแกรมผู้ใช้ มีคำสั่ง JSR ที่ข้ามไปยังรายการในตารางการข้าม ยกเว้นที่อยู่หกรายการสุดท้ายในตารางข้าม ที่อยู่แรกของรายการในตารางข้ามจะมีคำสั่ง JSR ใน Kernal รูทีนย่อยบางรูทีนสามารถเรียกรูทีนย่อยอื่นได้

ตารางข้าม Kernal เริ่มต้นจาก $FF81 (รวม) ขึ้นไปในกลุ่มละสามกลุ่ม ยกเว้นหกไบต์สุดท้ายซึ่งเป็นพอยน์เตอร์สามตัวที่มีที่อยู่ไบต์ต่ำกว่า: $FFFA, $FFFC และ $FFFE รูทีน ROM OS ทั้งหมดเป็นรหัสที่นำมาใช้ซ้ำได้ ดังนั้นผู้ใช้จึงไม่จำเป็นต้องเขียนใหม่

แผนภาพบล็อกของหน่วยระบบ Commodore-64
แผนภาพต่อไปนี้มีรายละเอียดมากกว่าแผนภาพในบทที่แล้ว:


รูปที่ 5.12 บล็อกไดอะแกรมของหน่วยระบบ Commodore_64

ROM และ RAM จะแสดงเป็นบล็อกเดียวที่นี่ Video Interface Chip (IC) สำหรับจัดการข้อมูลไปยังหน้าจอซึ่งไม่ได้แสดงในบทที่แล้วแสดงไว้ที่นี่ บล็อกเดียวสำหรับอุปกรณ์อินพุต/เอาท์พุต ซึ่งแสดงในบทที่แล้ว จะแสดงที่นี่เป็นสองบล็อก: CIA #1 และ CIA #2 CIA ย่อมาจาก Complex Interface Adapter แต่ละพอร์ตมีพอร์ตขนานแปดบิตสองพอร์ต (เพื่อไม่ให้สับสนกับพอร์ตภายนอกบนพื้นผิวแนวตั้งของยูนิตระบบ) เรียกว่าพอร์ต A และพอร์ต B CIA เชื่อมต่อกับอุปกรณ์ภายนอกห้าเครื่องในสถานการณ์เช่นนี้ อุปกรณ์ได้แก่ แป้นพิมพ์ จอยสติ๊ก ดิสก์ไดรฟ์/เครื่องพิมพ์ และโมเด็ม เครื่องพิมพ์เชื่อมต่ออยู่ที่ด้านหลังของดิสก์ไดรฟ์ นอกจากนี้ยังมีวงจรอุปกรณ์อินเทอร์เฟซเสียงและวงจรอาเรย์ลอจิกแบบตั้งโปรแกรมได้ที่ไม่แสดง

ยังมี ROM อักขระซึ่งสามารถสลับกับ CIA ทั้งสองได้เมื่ออักขระถูกส่งไปยังหน้าจอและไม่ได้แสดงในบล็อกไดอะแกรม

ที่อยู่ RAM ตั้งแต่ $D000 ถึง $DFFF สำหรับวงจรอินพุต/เอาท์พุตในกรณีที่ไม่มี ROM ตัวอักษร มีแผนผังหน่วยความจำโดยละเอียดดังต่อไปนี้:

ตารางที่ 5.11
แผนที่หน่วยความจำโดยละเอียดตั้งแต่ $D000 ถึง $DFFF
ช่วงที่อยู่ย่อย เซอร์กิต ขนาด (ไบต์)
D000 – D3FF VIC (ตัวควบคุมอินเทอร์เฟซวิดีโอ (ชิป)) 1ก
D400 – D7FF SID (วงจรเสียง) 1ก
D800 – DBFF แรมสี 1K แทะ
DC00 – DCFF CIA #1 (คีย์บอร์ด, จอยสติ๊ก) 256
DD00 – DDFF CIA #2 (บัสอนุกรม, พอร์ตผู้ใช้/RS-232) 256
DE00 – ป้องกัน เปิดสล็อต I/O #1 256
DF00 – DFFF เปิดสล็อต I/O #2 256

5.2 อะแดปเตอร์อินเทอร์เฟซที่ซับซ้อนสองตัว

มีวงจรรวม (IC) เฉพาะสองตัวในยูนิตระบบ Commodore-64 และแต่ละวงจรเรียกว่า Complex Interface Adapter ชิปทั้งสองนี้ใช้เพื่อเชื่อมต่อแป้นพิมพ์และอุปกรณ์ต่อพ่วงอื่นๆ กับไมโครโปรเซสเซอร์ ยกเว้น VIC และหน้าจอ สัญญาณอินพุต/เอาท์พุตทั้งหมดระหว่างไมโครโปรเซสเซอร์และอุปกรณ์ต่อพ่วงจะผ่านไอซีทั้งสองนี้ Commodore-64 ไม่มีการสื่อสารโดยตรงระหว่างหน่วยความจำและอุปกรณ์ต่อพ่วงใดๆ การสื่อสารระหว่างหน่วยความจำและอุปกรณ์ต่อพ่วงใดๆ จะถูกส่งผ่านตัวสะสมไมโครโปรเซสเซอร์ และหนึ่งในนั้นคืออะแดปเตอร์ CIA (IC) ไอซีเรียกว่า CIA #1 และ CIA #2 CIA ย่อมาจาก Complex Interface Adapter

CIA แต่ละแห่งมีทะเบียน 16 แห่ง ยกเว้นรีจิสเตอร์ตัวจับเวลา/ตัวนับใน CIA แต่ละรีจิสเตอร์จะมีความกว้าง 8 บิตและมีที่อยู่หน่วยความจำ ที่อยู่การลงทะเบียนหน่วยความจำสำหรับ CIA #1 มาจาก $DC00 (56320 10 ) ถึง $DC0F (56335 10 ). ที่อยู่การลงทะเบียนหน่วยความจำสำหรับ CIA #2 มาจาก $DD00 (56576 10 ) ถึง $DD0F (56591 10 ). แม้ว่ารีจิสเตอร์เหล่านี้จะไม่ได้อยู่ในหน่วยความจำไอซี แต่ก็เป็นส่วนหนึ่งของหน่วยความจำ ในแผนผังหน่วยความจำระดับกลาง พื้นที่ I/O ตั้งแต่ $D000 ถึง $DFFF จะรวมที่อยู่ CIA ตั้งแต่ $DC00 ถึง $DC0F และจาก $DD00 ถึง $DD0F พื้นที่หน่วยความจำ RAM I/O ส่วนใหญ่ตั้งแต่ $D000 ถึง $DFFF สามารถสลับกับคลังหน่วยความจำของ ROM ตัวอักษรสำหรับอักขระบนหน้าจอได้ นั่นคือเหตุผลว่าทำไมเมื่อตัวละครถูกส่งไปยังหน้าจอ อุปกรณ์ต่อพ่วงจึงไม่สามารถทำงานได้ แม้ว่าผู้ใช้อาจไม่สังเกตเห็นสิ่งนี้เนื่องจากการสลับไปมาทำได้รวดเร็ว

มีทะเบียนสองแห่งใน CIA #1 ที่เรียกว่าพอร์ต A และพอร์ต B ที่อยู่ของพวกเขาคือ $DC00 และ $DC01 ตามลำดับ นอกจากนี้ยังมีทะเบียนสองแห่งใน CIA #2 ที่เรียกว่าพอร์ต A และพอร์ต B แน่นอนว่าที่อยู่ต่างกัน คือ $DD00 และ $DD01 ตามลำดับ

พอร์ต A หรือพอร์ต B ใน CIA เป็นพอร์ตขนาน ซึ่งหมายความว่าสามารถส่งข้อมูลไปยังอุปกรณ์ต่อพ่วงได้แปดบิตในคราวเดียวหรือรับข้อมูลจากไมโครโปรเซสเซอร์ในแปดบิตในคราวเดียว

เชื่อมโยงกับพอร์ต A หรือพอร์ต B คือ Data Direction Register (DDR) รีจิสเตอร์ทิศทางข้อมูลสำหรับพอร์ต A ของ CIA #1 (DDRA1) อยู่ที่ตำแหน่งไบต์หน่วยความจำที่ $DC02 รีจิสเตอร์ทิศทางข้อมูลสำหรับพอร์ต B ของ CIA #1 (DDRB1) อยู่ที่ตำแหน่งไบต์หน่วยความจำที่ $DC03 การลงทะเบียนทิศทางข้อมูลสำหรับพอร์ต A ของ CIA #2 (DDRA2) อยู่ที่ตำแหน่งไบต์หน่วยความจำที่ $DD02 การลงทะเบียนทิศทางข้อมูลสำหรับพอร์ต B ของ CIA #2 (DDRB2) อยู่ที่ตำแหน่งไบต์หน่วยความจำที่ $DD03

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

ถ้าจะป้อนเซลล์ของพอร์ต (รีจิสเตอร์) บิตที่สอดคล้องกันในรีจิสเตอร์ทิศทางข้อมูลจะเป็น 0 ถ้าเซลล์ของพอร์ต (รีจิสเตอร์) จะถูกส่งออก บิตที่สอดคล้องกันในรีจิสเตอร์ทิศทางข้อมูลจะเป็น 1 ในกรณีส่วนใหญ่ พอร์ตทั้ง 8 บิตจะถูกตั้งโปรแกรมให้เป็นอินพุตหรือเอาต์พุต เมื่อคอมพิวเตอร์เปิดอยู่ พอร์ต A จะถูกตั้งโปรแกรมไว้สำหรับเอาต์พุต และพอร์ต B จะถูกตั้งโปรแกรมไว้สำหรับอินพุต รหัสต่อไปนี้ทำให้พอร์ต CIA #1 A เป็นเอาต์พุต และพอร์ต CIA #1 B เป็นอินพุต:

แอลดีเอ #$FF
สต้า DDRA1 ; $DC00 กำกับโดย $DC02
LDA #$00
สตาท DDRB1 ; $DC01 กำกับโดย $DC03

DDRA1 คือเลเบล (ชื่อตัวแปร) สำหรับตำแหน่งไบต์หน่วยความจำของ $DC02 และ DDRB1 คือเลเบล (ชื่อตัวแปร) สำหรับตำแหน่งไบต์หน่วยความจำของ $DC03 คำสั่งแรกโหลด 11111111 ไปยังตัวสะสมของ µP คำสั่งที่สองคัดลอกสิ่งนี้ไปยังรีจิสเตอร์ทิศทางข้อมูลของพอร์ต A ของ CIA หมายเลข 1. คำสั่งที่สามโหลด 00000000 ไปยังตัวสะสมของ µP คำสั่งที่สี่คัดลอกสิ่งนี้ไปยังรีจิสเตอร์ทิศทางข้อมูลของพอร์ต B ของ CIA หมายเลข 1. รหัสนี้อยู่ในรูทีนย่อยหนึ่งในระบบปฏิบัติการที่ทำการเริ่มต้นนี้เมื่อเปิดเครื่องคอมพิวเตอร์

CIA แต่ละแห่งมีสายคำขอบริการขัดจังหวะไปยังไมโครโปรเซสเซอร์ คนจาก CIA #1 ไปที่ IRQ พินของ µP คนจาก CIA #2 ไปที่ เอ็นเอ็มไอ พินของ µP จำไว้ เอ็นเอ็มไอ มีลำดับความสำคัญสูงกว่า IRQ .

5.3 การเขียนโปรแกรมภาษาชุดคีย์บอร์ด

การขัดจังหวะที่เป็นไปได้เพียงสามครั้งสำหรับ Commodore-64: IRQ , BRK และ เอ็นเอ็มไอ . ตัวชี้ตารางกระโดดสำหรับ IRQ อยู่ที่ที่อยู่ $FFFE และ $FFFF ใน ROM (ระบบปฏิบัติการ) ซึ่งสอดคล้องกับรูทีนย่อยที่ยังอยู่ใน OS (ROM) ตัวชี้ตารางกระโดดสำหรับ BRK อยู่ที่ที่อยู่ $FFFC และ $FFFD ใน OS ซึ่งสอดคล้องกับรูทีนย่อยที่ยังคงอยู่ใน OS (ROM) ตัวชี้ตารางกระโดดสำหรับ เอ็นเอ็มไอ อยู่ที่ที่อยู่ $FFFA และ $FFFB ใน OS ซึ่งสอดคล้องกับรูทีนย่อยที่ยังอยู่ใน OS (ROM) สำหรับ IRQ จริงๆ แล้วมีรูทีนย่อยสองรูทีน ดังนั้นซอฟต์แวร์ BRK ขัดจังหวะ (คำสั่ง) จึงมีตัวชี้ตารางกระโดดของตัวเอง ตัวชี้ตารางกระโดดสำหรับ IRQ นำไปสู่โค้ดที่ตัดสินใจว่าเป็นการขัดจังหวะฮาร์ดแวร์หรือซอฟต์แวร์ขัดจังหวะที่มีส่วนร่วม ถ้าเป็นการขัดจังหวะฮาร์ดแวร์ รูทีนสำหรับ IRQ ถูกเรียก. หากเป็นซอฟต์แวร์ขัดจังหวะ (BRK) จะมีการเรียกรูทีนสำหรับ BRK ในระบบปฏิบัติการเวอร์ชันใดเวอร์ชันหนึ่ง รูทีนย่อยสำหรับ IRQ อยู่ที่ $EA31 และรูทีนย่อยสำหรับ BRK อยู่ที่ $FE66 ที่อยู่เหล่านี้ต่ำกว่า $FF81 ดังนั้นจึงไม่สามารถข้ามรายการตารางและสามารถเปลี่ยนแปลงได้ตามเวอร์ชันของระบบปฏิบัติการ มีกิจวัตรที่น่าสนใจสามประการในหัวข้อนี้: กิจวัตรที่ตรวจสอบว่ามีการกดคีย์หรือ BRK, กิจวัตรที่ราคา $FE43 และอีกอันที่อาจเปลี่ยนแปลงตามเวอร์ชันของระบบปฏิบัติการ

คอมพิวเตอร์ Commodore-64 มีลักษณะเหมือนเครื่องพิมพ์ดีดขนาดใหญ่ (ด้านบน) โดยมีลักษณะไม่มีส่วนการพิมพ์ (หัวและกระดาษ) แป้นพิมพ์เชื่อมต่อกับ CIA #1 CIA #1 สแกนคีย์บอร์ดทุกๆ 1/60 วินาทีด้วยตัวมันเองโดยไม่มีการรบกวนการเขียนโปรแกรมใดๆ ตามค่าเริ่มต้น ดังนั้น ทุกๆ 1/60 วินาที CIA #1 จะส่ง IRQ ถึง µP มีเพียงหนึ่งเดียว IRQ ปักหมุดที่ µP ซึ่งมาจาก CIA #1 เท่านั้น ขาอินพุตหนึ่งของ เอ็นเอ็มไอ ของ µP ซึ่งแตกต่างจาก IRQ มาจาก CIA #2 เท่านั้น (โปรดดูภาพประกอบต่อไปนี้) BRK จริงๆ แล้วเป็นคำสั่งภาษาแอสเซมบลีที่ถูกเข้ารหัสในโปรแกรมผู้ใช้

ดังนั้นทุกๆ 1/60 วินาที IRQ รูทีนที่ $FFFE และ $FFFF ชี้ไปจะถูกเรียก รูทีนจะตรวจสอบว่ามีการกดปุ่มหรือพบคำสั่ง BRK หรือไม่ หากมีการกดปุ่ม ระบบจะเรียกรูทีนในการจัดการกับการกดปุ่ม หากเป็นคำสั่ง BRK จะมีการเรียกรูทีนเพื่อจัดการ BRK หากไม่เป็นเช่นนั้นก็ไม่มีอะไรเกิดขึ้น อาจไม่เกิดขึ้น แต่ CIA #1 ส่ง IRQ เป็น µP ทุกๆ 1/60 วินาที

คิวแป้นพิมพ์หรือที่เรียกว่าบัฟเฟอร์แป้นพิมพ์คือช่วงของตำแหน่งไบต์ RAM ตั้งแต่ 0277 ดอลลาร์ถึง 0280 ดอลลาร์โดยรวม ทั้งหมด 1,010 ไบต์ นี่คือบัฟเฟอร์เข้าก่อน-ออกก่อน นั่นหมายความว่าตัวละครตัวแรกที่เข้ามาคือคนแรกที่ออกไป อักขระยุโรปตะวันตกใช้เวลาหนึ่งไบต์

ดังนั้น แม้ว่าโปรแกรมจะไม่ใช้อักขระใดๆ เมื่อกดปุ่ม แต่โค้ดคีย์จะเข้าสู่บัฟเฟอร์นี้ (คิว) บัฟเฟอร์จะถูกเติมไปเรื่อยๆ จนกว่าจะมีอักขระสิบตัว อักขระใดๆ ที่ถูกกดหลังจากอักขระตัวที่สิบจะไม่ถูกบันทึก มันจะถูกละเว้นจนกว่าจะได้รับ (ใช้) อักขระอย่างน้อยหนึ่งตัวจากคิว ตารางการข้ามมีรายการสำหรับรูทีนย่อยซึ่งรับอักขระตัวแรกจากคิวไปยังไมโครโปรเซสเซอร์ นั่นหมายความว่าจะนำอักขระตัวแรกที่เข้าไปในคิวและวางลงในตัวสะสมของ µP รูทีนย่อย Jump Table เพื่อทำสิ่งนี้เรียกว่า GETIN (สำหรับ Get-In) ไบต์แรกสำหรับรายการสามไบต์ในตารางข้ามจะมีป้ายกำกับว่า GETIN (ที่อยู่ $FFE4) สองไบต์ถัดไปคือตัวชี้ (ที่อยู่) ที่ชี้ไปยังรูทีนจริงใน ROM (OS) เป็นความรับผิดชอบของโปรแกรมเมอร์ที่จะเรียกรูทีนนี้ มิฉะนั้น บัฟเฟอร์ของแป้นพิมพ์จะยังคงเต็ม และปุ่มที่กดล่าสุดทั้งหมดจะถูกละเว้น ค่าที่เข้าสู่ตัวสะสมคือค่า ASCII ที่สำคัญที่สอดคล้องกัน

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

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

เข้าไป

หากบัฟเฟอร์ของแป้นพิมพ์ว่างเปล่า จะมีการวาง $00 ไว้ในตัวสะสม โปรดจำไว้ว่ารหัส ASCII สำหรับศูนย์ไม่ใช่ $00; มันคือ $30 $00 หมายถึงค่าว่าง ในโปรแกรมอาจมีจุดที่โปรแกรมต้องรอการกดปุ่ม รหัสสำหรับสิ่งนี้คือ:

รอ JSR GETIN
ซีเอ็มพี #$00
กบรอก่อน

ในบรรทัดแรก “WAIT” คือป้ายกำกับที่ระบุที่อยู่ RAM ที่ใส่ (พิมพ์) คำสั่ง JSR ไว้ GETIN ก็เป็นที่อยู่เช่นกัน เป็นที่อยู่ของไบต์แรกจากสามไบต์ที่สอดคล้องกันในตารางข้าม รายการ GETIN รวมถึงรายการทั้งหมดในตารางข้าม (ยกเว้นสามรายการสุดท้าย) ประกอบด้วยสามไบต์ ไบต์แรกของรายการคือคำสั่ง JSR สองไบต์ถัดไปคือที่อยู่ของเนื้อความของรูทีนย่อย GETIN จริงซึ่งยังอยู่ใน ROM (OS) แต่อยู่ใต้ตารางข้าม ดังนั้นรายการบอกว่าให้ข้ามไปที่รูทีนย่อย GETIN หากคิวแป้นพิมพ์ไม่ว่างเปล่า GETIN จะใส่โค้ดคีย์ ASCII ของคิวเข้าก่อนออกก่อนลงในตัวสะสม หากคิวว่างเปล่า ค่า Null ($00) จะถูกใส่เข้าไปในตัวสะสม

คำสั่งที่สองเปรียบเทียบค่าตัวสะสมกับ $00 หากเป็น $00 แสดงว่าคิวคีย์บอร์ดว่างเปล่า และคำสั่ง CMP จะส่ง 1 ไปยังแฟล็ก Z ของรีจิสเตอร์สถานะโปรเซสเซอร์ (เรียกง่ายๆ ว่ารีจิสเตอร์สถานะ) หากค่าใน A ไม่ใช่ $00 คำสั่ง CMP จะส่ง 0 ไปยังแฟล็ก Z ของรีจิสเตอร์สถานะ

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

บันทึก : แป้นพิมพ์เป็นอุปกรณ์อินพุตเริ่มต้นและหน้าจอเป็นอุปกรณ์เอาต์พุตเริ่มต้น

5.4 ช่อง หมายเลขอุปกรณ์ และหมายเลขไฟล์โลจิคัล

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

ช่องสัญญาณประกอบด้วยบัฟเฟอร์ หมายเลขอุปกรณ์ หมายเลขไฟล์ลอจิคัล และที่อยู่รอง (ไม่บังคับ) คำอธิบายของข้อกำหนดเหล่านี้มีดังนี้:

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

หมายเลขอุปกรณ์
สำหรับ Commodore-64 อุปกรณ์ต่อพ่วงใดๆ จะได้รับหมายเลขอุปกรณ์ ตารางต่อไปนี้แสดงอุปกรณ์ต่างๆ และหมายเลขของอุปกรณ์:

ตารางที่ 5.41
หมายเลขอุปกรณ์ Commodore 64 และอุปกรณ์
ตัวเลข อุปกรณ์
0 คีย์บอร์ด
1 เทปไดรฟ์
2 อินเทอร์เฟซ RS 232C เช่น โมเด็ม
3 หน้าจอ
4 เครื่องพิมพ์ #1
5 เครื่องพิมพ์ #2
6 พลอตเตอร์ #1
7 พลอตเตอร์ #2
8 ดิสก์ไดรฟ์
9
¦
¦
¦
30
จาก 8 (รวม) มากถึง 22 อุปกรณ์จัดเก็บข้อมูลเพิ่มเติม

พอร์ตสำหรับคอมพิวเตอร์มีสองประเภท ประเภทหนึ่งคือภายนอก บนพื้นผิวแนวตั้งของยูนิตระบบ อีกประเภทคือภายใน พอร์ตภายในนี้เป็นรีจิสเตอร์ Commodore-64 มีพอร์ตภายในสี่พอร์ต: พอร์ต A และพอร์ต B สำหรับ CIA 1 และพอร์ต A และพอร์ต B สำหรับ CIA 2 มีพอร์ตภายนอกหนึ่งพอร์ตสำหรับ Commodore-64 ซึ่งเรียกว่าพอร์ตอนุกรม อุปกรณ์ที่มีหมายเลข 3 ขึ้นไปเชื่อมต่อกับพอร์ตอนุกรม เชื่อมต่อกันแบบเดซี่เชน (อันหนึ่งเชื่อมต่อกันด้านหลัง) ซึ่งแต่ละอันสามารถระบุได้ด้วยหมายเลขอุปกรณ์ อุปกรณ์ที่มีหมายเลข 8 ขึ้นไป โดยทั่วไปจะเป็นอุปกรณ์จัดเก็บข้อมูล

บันทึก : อุปกรณ์อินพุตเริ่มต้นคือแป้นพิมพ์ที่มีหมายเลขอุปกรณ์เป็น 0 อุปกรณ์เอาต์พุตเริ่มต้นคือหน้าจอที่มีหมายเลขอุปกรณ์เป็น 3

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

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

บันทึก : หมายเลขอุปกรณ์เรียกอีกอย่างว่าที่อยู่อุปกรณ์ และหมายเลขรองเรียกอีกอย่างว่าที่อยู่รอง

การระบุเป้าหมายอุปกรณ์ต่อพ่วง
สำหรับแผนที่หน่วยความจำ Commodore เริ่มต้น ที่อยู่หน่วยความจำตั้งแต่ $0200 ถึง $02FF (หน้า 2) ถูกใช้โดยระบบปฏิบัติการใน ROM (Kernal) เท่านั้น และไม่ใช่โดยระบบปฏิบัติการบวกกับภาษา BASIC แม้ว่า BASIC จะยังสามารถใช้งานตำแหน่งผ่าน ROM OS ได้

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

$0259 — $0262: ตารางที่มีป้ายกำกับ, LAT, สูงสุดสิบหมายเลขไฟล์ลอจิคัลที่ใช้งานอยู่
$0263 — $026C: ตารางที่มีป้ายกำกับ, FAT ของหมายเลขอุปกรณ์ที่เกี่ยวข้องสูงสุดสิบหมายเลข
$026D — $0276: ตารางที่มีป้ายกำกับ, SAT, ของที่อยู่รองที่เกี่ยวข้องสิบรายการ

ในที่นี้ “—” หมายถึง “ถึง” และตัวเลขหนึ่งใช้หนึ่งไบต์

ผู้อ่านอาจถามว่า “เหตุใดบัฟเฟอร์สำหรับแต่ละอุปกรณ์จึงไม่รวมอยู่ในการระบุช่องสัญญาณ” คำตอบก็คือสำหรับ Commodore-64 อุปกรณ์ภายนอกแต่ละตัว (อุปกรณ์ต่อพ่วง) จะมีชุดไบต์คงที่ใน RAM (แผนที่หน่วยความจำ) หากไม่มีช่องใดเปิดอยู่ ตำแหน่งของพวกเขาจะยังคงอยู่ในหน่วยความจำ ตัวอย่างเช่น บัฟเฟอร์สำหรับคีย์บอร์ดได้รับการแก้ไขจาก $0277 ถึง $0280 (รวม) สำหรับแผนผังหน่วยความจำเริ่มต้น

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

ในการเรียกรูทีน SETLFS โปรแกรมผู้ใช้จะต้องข้าม (JSR) ไปยังที่อยู่ $FFBA ของตารางการข้ามของ OS ใน ROM สำหรับแมปหน่วยความจำเริ่มต้น โปรดจำไว้ว่า ยกเว้นหกไบต์สุดท้ายของตารางกระโดด แต่ละรายการจะประกอบด้วยสามไบต์ ไบต์แรกคือคำสั่ง JSR ซึ่งจากนั้นข้ามไปยังรูทีนย่อย โดยเริ่มต้นที่แอดเดรสในอีกสองไบต์ถัดไป ในการเรียกรูทีน SETNAM โปรแกรมผู้ใช้จะต้องข้าม (JSR) ไปยังที่อยู่ $FFBD ของตารางการข้ามของ OS ใน ROM การใช้รูทีนทั้งสองนี้จะแสดงอยู่ในการสนทนาต่อไปนี้

5.5 การเปิดช่อง การเปิดไฟล์โลจิคัล การปิดไฟล์โลจิคัล และการปิดช่อง I/O ทั้งหมด

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

กิจวัตร OS SETLFS
OS SETLFS Routine ซึ่งเข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFBA จะตั้งค่าช่องสัญญาณ จำเป็นต้องใส่หมายเลขไฟล์ลอจิคัลในตารางไฟล์ซึ่งเป็น LAT ($0259 — $0262) จำเป็นต้องใส่หมายเลขอุปกรณ์ที่เกี่ยวข้องในตารางไฟล์ซึ่งเป็น FAT ($0263 — $026C) หากการเข้าถึงไฟล์ (อุปกรณ์) จำเป็นต้องมีหมายเลขรอง จะต้องใส่ที่อยู่รอง (หมายเลข) ที่เกี่ยวข้องในตารางไฟล์ซึ่งก็คือ SAT ($026D — $0276)

เพื่อดำเนินการ รูทีนย่อย SETLFS จำเป็นต้องได้รับหมายเลขโลจิคัลไฟล์จาก µP accumulator จำเป็นต้องได้รับหมายเลขอุปกรณ์จากรีจิสเตอร์ µP X หากช่องจำเป็น จะต้องได้รับที่อยู่รองจากรีจิสเตอร์ µP Y

โปรแกรมเมอร์จะเป็นผู้กำหนดหมายเลขไฟล์ลอจิคัล หมายเลขไฟล์ลอจิคัลที่อ้างอิงถึงอุปกรณ์ที่แตกต่างกันจะแตกต่างกัน ในตอนนี้ ก่อนที่จะเรียกใช้รูทีน SETLFS โปรแกรมเมอร์ควรใส่หมายเลขสำหรับโลจิคัลไฟล์ลงในตัวสะสม µP หมายเลขอุปกรณ์จะอ่านจากตาราง (เอกสาร) เช่นในตาราง 5.41 โปรแกรมเมอร์ควรต้องใส่หมายเลขอุปกรณ์ลงในรีจิสเตอร์ µP X ด้วย ซัพพลายเออร์สำหรับอุปกรณ์ เช่น เครื่องพิมพ์ ดิสก์ไดรฟ์ ฯลฯ จะให้ที่อยู่รองที่เป็นไปได้และความหมายสำหรับอุปกรณ์ หากช่องสัญญาณต้องการที่อยู่สำรอง โปรแกรมเมอร์จำเป็นต้องได้รับจากเอกสารที่มาพร้อมกับอุปกรณ์ (อุปกรณ์ต่อพ่วง) หากจำเป็นต้องใช้ที่อยู่สำรอง (หมายเลข) โปรแกรมเมอร์จะต้องใส่ไว้ในรีจิสเตอร์ µP Y ก่อนที่จะเรียกใช้รูทีนย่อย SETLFS หากไม่จำเป็นต้องมีที่อยู่รอง โปรแกรมเมอร์จะต้องใส่หมายเลข $FF ลงในรีจิสเตอร์ µP Y ก่อนที่จะเรียกใช้รูทีนย่อย SETLFS

รูทีนย่อย SETLFS ถูกเรียกโดยไม่มีอาร์กิวเมนต์ใดๆ อาร์กิวเมนต์มีอยู่แล้วในสามรีจิสเตอร์ของ 6502 µP หลังจากใส่ตัวเลขที่เหมาะสมลงในรีจิสเตอร์แล้ว รูทีนจะถูกเรียกในโปรแกรมโดยแยกบรรทัดดังนี้:

เจเอสอาร์ เซทล์ฟส์

รูทีนจะใส่ตัวเลขที่แตกต่างกันอย่างเหมาะสมลงในตารางไฟล์

กิจวัตร OS SETNAM
OS SETNAM Routine เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFBD ปลายทางบางแห่งไม่มีชื่อไฟล์ สำหรับผู้ที่มีปลายทาง (เช่น ไฟล์ในดิสก์) ควรตั้งชื่อไฟล์ สมมติว่าชื่อไฟล์คือ 'mydocum' ซึ่งประกอบด้วย 7 ไบต์โดยไม่มีเครื่องหมายคำพูด สมมติว่าชื่อนี้อยู่ที่ตำแหน่ง $C101 ถึง $C107 (รวม) และความยาว $07 อยู่ที่ตำแหน่ง $C100 ที่อยู่เริ่มต้นของอักขระสตริงคือ $C101 ไบต์ล่างของที่อยู่เริ่มต้นคือ $01 และไบต์ที่สูงกว่าคือ $C1

ก่อนที่จะเรียกรูทีน SETNAM โปรแกรมเมอร์ต้องใส่ตัวเลข $07 (ความยาวของสตริง) ลงในตัวสะสม µP ไบต์ล่างของที่อยู่เริ่มต้นของสตริงที่ $01 จะถูกใส่ไว้ในรีจิสเตอร์ µP X ไบต์ที่สูงกว่าของที่อยู่เริ่มต้นของสตริง $C1 จะถูกใส่ไว้ในการลงทะเบียน µP Y รูทีนย่อยถูกเรียกง่ายๆ ดังต่อไปนี้:

เจเอสอาร์ เซทนาม

รูทีน SETNAM เชื่อมโยงค่าจากรีจิสเตอร์ทั้งสามตัวเข้ากับช่องสัญญาณ ค่าไม่จำเป็นต้องคงอยู่ในรีจิสเตอร์หลังจากนั้น หากช่องสัญญาณไม่ต้องการชื่อไฟล์ โปรแกรมเมอร์จะต้องใส่ $00 ในตัวสะสม µP ในกรณีนี้ ค่าที่อยู่ในการลงทะเบียน X และ Y จะถูกละเว้น

กิจวัตร OS OPEN
OS OPEN Routine เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFC0 รูทีนนี้ใช้หมายเลขไฟล์ลอจิคัล หมายเลขอุปกรณ์ (และบัฟเฟอร์) ที่อยู่สำรองที่เป็นไปได้ และชื่อไฟล์ที่เป็นไปได้ เพื่อให้การเชื่อมต่อระหว่างคอมพิวเตอร์ Commodore และไฟล์ในอุปกรณ์ภายนอกหรืออุปกรณ์ภายนอกเอง

รูทีนนี้เหมือนกับรูทีน Commodore OS ROM อื่นๆ ที่ไม่มีข้อโต้แย้ง แม้ว่าจะใช้รีจิสเตอร์ µP แต่ก็ไม่มีรีจิสเตอร์ใดที่ต้องโหลดอาร์กิวเมนต์ (ค่า) ไว้ล่วงหน้า หากต้องการโค้ด เพียงพิมพ์ข้อความต่อไปนี้หลังจากเรียกใช้ SETLFS และ SETNAM:

เจเอสอาร์ เปิด

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

ตารางที่ 5.51
หมายเลขข้อผิดพลาด Kernal และความหมายสำหรับ OS ROM OPEN Routine
หมายเลขข้อผิดพลาด คำอธิบาย ตัวอย่าง
1 มีไฟล์มากเกินไป เปิดเมื่อเปิดไฟล์สิบไฟล์แล้ว
2 เปิดไฟล์ เปิด 1,3: เปิด 1,4
3 ไฟล์ไม่เปิด พิมพ์ #5 โดยไม่ต้องเปิด
4 ไม่พบไฟล์ โหลด 'ไม่มีอยู่จริง',8
5 ไม่มีอุปกรณ์อยู่ เปิด 11,11: พิมพ์#11
6 ไม่ใช่ไฟล์อินพุต เปิด “SEQ,S,W”: GET#8,X$
7 ไม่ใช่ไฟล์เอาท์พุต เปิด 1,0: พิมพ์#1
8 ไม่มีชื่อไฟล์ โหลด “”,8
9 หมายเลขอุปกรณ์ที่ผิดกฎหมาย โหลด “โปรแกรม”,3

ตารางนี้นำเสนอในลักษณะที่ผู้อ่านมักจะเห็นในที่อื่นๆ มากมาย

กิจวัตร OS CHKIN
OS CHKIN Routine เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFC6 หลังจากเปิดไฟล์ (ไฟล์โลจิคัล) จะต้องตัดสินใจว่าเป็นการเปิดสำหรับอินพุตหรือเอาต์พุต รูทีน CHKIN ทำให้การเปิดช่องสัญญาณเข้า รูทีนนี้จำเป็นต้องอ่านหมายเลขไฟล์ลอจิคัลจากรีจิสเตอร์ µP X ดังนั้นโปรแกรมเมอร์จะต้องใส่หมายเลขไฟล์ลอจิคัลลงใน X register ก่อนที่จะเรียกรูทีนนี้ เรียกง่ายๆว่า:

เจเอสอาร์ ซีคิน

กิจวัตร OS CHKOUT
OS CHKOUT Routine เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFC9 หลังจากเปิดไฟล์ (ไฟล์โลจิคัล) จะต้องตัดสินใจว่าเป็นการเปิดสำหรับอินพุตหรือเอาต์พุต รูทีน CHKOUT ทำให้การเปิดช่องสัญญาณเอาท์พุต รูทีนนี้จำเป็นต้องอ่านหมายเลขไฟล์ลอจิคัลจากรีจิสเตอร์ µP X ดังนั้นโปรแกรมเมอร์จะต้องใส่หมายเลขไฟล์ลอจิคัลลงใน X register ก่อนที่จะเรียกรูทีนนี้ เรียกง่ายๆว่า:

เจเอสอาร์ CHKOUT

กิจวัตรการปิด OS
OS CLOSE Routine เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFC3 หลังจากเปิดไฟล์ลอจิคัลและส่งไบต์แล้ว จะต้องปิดไฟล์ลอจิคัล การปิดไฟล์โลจิคัลจะทำให้บัฟเฟอร์ในยูนิตระบบว่างเพื่อนำไปใช้โดยไฟล์โลจิคัลอื่นซึ่งยังคงเปิดอยู่ พารามิเตอร์ที่เกี่ยวข้องในตารางไฟล์ทั้งสามจะถูกลบเช่นกัน ตำแหน่ง RAM สำหรับจำนวนไฟล์ที่เปิดจะลดลง 1

เมื่อเปิดเครื่องคอมพิวเตอร์ จะมีการรีเซ็ตฮาร์ดแวร์สำหรับไมโครโปรเซสเซอร์และชิปหลักอื่นๆ (วงจรรวม) บนเมนบอร์ด ตามด้วยการเริ่มต้นตำแหน่งหน่วยความจำ RAM บางส่วนและการลงทะเบียนบางส่วนในชิปบางตัวบนเมนบอร์ด ในกระบวนการเริ่มต้น ตำแหน่งหน่วยความจำไบต์ของที่อยู่ $0098 ในเพจศูนย์จะถูกกำหนดพร้อมกับป้ายกำกับ NFILES หรือ LDTND ขึ้นอยู่กับเวอร์ชันของระบบปฏิบัติการ ในขณะที่คอมพิวเตอร์กำลังทำงาน ตำแหน่งหนึ่งไบต์ขนาด 8 บิตนี้จะเก็บจำนวนไฟล์ลอจิคัลที่ถูกเปิด และดัชนีที่อยู่เริ่มต้นของตารางไฟล์สามไฟล์ที่ติดกัน กล่าวอีกนัยหนึ่ง ไบต์นี้มีจำนวนไฟล์ที่เปิด ซึ่งจะลดลง 1 เมื่อปิดไฟล์ลอจิคัล เมื่อปิดไฟล์ลอจิคัล การเข้าถึงอุปกรณ์เทอร์มินัล (ปลายทาง) หรือไฟล์จริงในดิสก์จะไม่สามารถทำได้อีกต่อไป

หากต้องการปิดไฟล์ลอจิคัล โปรแกรมเมอร์ต้องใส่หมายเลขไฟล์ลอจิคัลลงในตัวสะสม µP นี่เป็นหมายเลขไฟล์ลอจิคัลเดียวกันกับที่ใช้ในการเปิดไฟล์ รูทีน CLOSE จำเป็นต้องใช้เพื่อปิดไฟล์นั้น เช่นเดียวกับรูทีน OS ROM อื่นๆ รูทีน CLOSE จะไม่รับอาร์กิวเมนต์ แม้ว่าค่าที่ใช้จากตัวสะสมจะค่อนข้างเป็นอาร์กิวเมนต์ก็ตาม บรรทัดคำสั่งภาษาแอสเซมบลีเป็นเพียง:

เจเอสอาร์ ปิด

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

กิจวัตร CLRCHN
OS CLRCHN Routine เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFCC CLRCHN ย่อมาจาก CLeaR CHanneL เมื่อปิดไฟล์ลอจิคัล พารามิเตอร์ของหมายเลขไฟล์ลอจิคัล หมายเลขอุปกรณ์ และที่อยู่รองที่เป็นไปได้จะถูกลบ ดังนั้น ช่องสำหรับโลจิคัลไฟล์จึงถูกล้าง

คู่มือระบุว่ารูทีน OS CLRCHN จะล้างช่องสัญญาณที่เปิดอยู่ทั้งหมด และเรียกคืนหมายเลขอุปกรณ์เริ่มต้นและค่าเริ่มต้นอื่นๆ หมายความว่าหมายเลขอุปกรณ์สำหรับอุปกรณ์ต่อพ่วงสามารถเปลี่ยนแปลงได้ใช่หรือไม่ ก็ไม่เชิง ในระหว่างการเริ่มต้นระบบปฏิบัติการ ตำแหน่งไบต์ของที่อยู่ $0099 จะได้รับพร้อมกับป้าย DFLTI เพื่อเก็บหมายเลขอุปกรณ์อินพุตปัจจุบันเมื่อคอมพิวเตอร์ทำงาน พลเรือจัตวา-64 สามารถเข้าถึงอุปกรณ์ต่อพ่วงได้ครั้งละหนึ่งเครื่องเท่านั้น ในระหว่างการเริ่มต้นระบบปฏิบัติการ ตำแหน่งไบต์ของที่อยู่ $009A จะได้รับพร้อมกับป้ายกำกับ DFLTO เพื่อเก็บหมายเลขอุปกรณ์เอาต์พุตปัจจุบันเมื่อคอมพิวเตอร์ทำงาน

เมื่อรูทีนย่อย CLRCHN ถูกเรียก จะตั้งค่าตัวแปร DFLTI เป็น 0 ($00) ซึ่งเป็นหมายเลขอุปกรณ์อินพุตดีฟอลต์ (คีย์บอร์ด) โดยตั้งค่าตัวแปร DFLTO เป็น 3 ($03) ซึ่งเป็นหมายเลขอุปกรณ์เอาต์พุตเริ่มต้น (หน้าจอ) ตัวแปรหมายเลขอุปกรณ์อื่นๆ จะถูกรีเซ็ตในทำนองเดียวกัน นั่นคือความหมายของการรีเซ็ต (หรือการกู้คืน) อุปกรณ์อินพุต/เอาท์พุตให้เป็นปกติ (ค่าเริ่มต้น)

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

5.6 การส่งตัวละครขึ้นหน้าจอ

วงจรรวมหลัก (IC) เพื่อจัดการการแสดงอักขระและกราฟิกบนหน้าจอเรียกว่า Video Interface Controller (ชิป) ซึ่งย่อว่า VIC ใน Commodore-64 (จริงๆ แล้วคือ VIC II สำหรับ VIC ​​เวอร์ชัน 2) ข้อมูล (ค่า) เพื่อไปที่หน้าจอจะต้องผ่าน VIC II ก่อนจึงจะถึงหน้าจอ

หน้าจอประกอบด้วยเซลล์อักขระ 25 แถวและ 40 คอลัมน์ ทำให้มีอักขระ 40 x 25 = 1,000 ตัวที่สามารถแสดงบนหน้าจอได้ VIC II อ่านตำแหน่งไบต์ต่อเนื่องกันของ RAM หน่วยความจำ 1,000 ตำแหน่งสำหรับอักขระ สถานที่ 1,000 แห่งรวมกันนี้เรียกว่าหน่วยความจำหน้าจอ สิ่งที่รวมอยู่ใน 1,000 ตำแหน่งนี้คือรหัสอักขระ สำหรับ Commodore-64 รหัสอักขระจะแตกต่างจากรหัส ASCII

รหัสอักขระไม่ใช่รูปแบบอักขระ นอกจากนี้ยังมีสิ่งที่เรียกว่า ROM ตัวอักษร ROM อักขระประกอบด้วยรูปแบบอักขระทุกประเภท ซึ่งบางรูปแบบจะสอดคล้องกับรูปแบบอักขระบนแป้นพิมพ์ ROM ตัวอักษรจะแตกต่างจากหน่วยความจำหน้าจอ เมื่อแสดงอักขระบนหน้าจอ รหัสอักขระจะถูกส่งไปยังตำแหน่งหนึ่งใน 1,000 ตำแหน่งในหน่วยความจำหน้าจอ จากนั้น รูปแบบที่สอดคล้องกันจะถูกเลือกจาก ROM ตัวอักษรที่จะแสดงบนหน้าจอ การเลือกรูปแบบที่ถูกต้องใน ROM อักขระจากโค้ดอักขระจะกระทำโดย VIC II (ฮาร์ดแวร์)

ตำแหน่งหน่วยความจำจำนวนมากระหว่าง $D000 ถึง $DFFF มีวัตถุประสงค์สองประการ: ใช้เพื่อจัดการการดำเนินการอินพุต/เอาต์พุตอื่นที่ไม่ใช่หน้าจอ หรือใช้เป็น ROM อักขระสำหรับหน้าจอ เกี่ยวข้องกับหน่วยความจำสองบล็อก อันหนึ่งคือ RAM และอีกอันคือ ROM สำหรับ ROM ตัวอักษร การสลับช่องเพื่อจัดการอินพุต/เอาท์พุตหรือรูปแบบอักขระ (ROM อักขระ) ทำได้โดยซอฟต์แวร์ (รูทีนของระบบปฏิบัติการใน ROM จาก $F000 ถึง $FFFF)

บันทึก : VIC มีรีจิสเตอร์ที่จ่าหน้าด้วยที่อยู่ของพื้นที่หน่วยความจำภายในช่วง $D000 และ $DFFF

กิจวัตร CHROUT
OS CHROUT Routine เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFD2 เมื่อเรียกรูทีนนี้ จะใช้ไบต์ที่โปรแกรมเมอร์ใส่ไว้ในตัวสะสม µP และพิมพ์ที่หน้าจอตรงตำแหน่งเคอร์เซอร์ ตัวอย่างเช่นส่วนของรหัสที่จะพิมพ์อักขระ 'E' คือ:

แอลดีเอ #$05
โครต

0516 ไม่ใช่รหัส ASCII สำหรับ “E” Commodore-64 มีรหัสอักขระของตัวเองสำหรับหน้าจอ โดยที่ $05 หมายถึง 'E' หมายเลข #$05 จะถูกวางไว้ในหน่วยความจำหน้าจอก่อนที่ VIC จะส่งไปที่หน้าจอ บรรทัดการเข้ารหัสทั้งสองบรรทัดนี้ควรมาหลังจากตั้งค่าช่องสัญญาณแล้ว เปิดไฟล์ลอจิคัล และรูทีน CHKOUT ถูกเรียกสำหรับเอาต์พุต รหัสที่สมบูรณ์คือ:

; ตั้งค่าช่อง
แอลดีเอ #$40 ; หมายเลขไฟล์โลจิคัล
LDX #$03 ; หมายเลขอุปกรณ์สำหรับหน้าจอคือ $03
แอลดี #$FF ; ไม่มีที่อยู่สำรอง
เจเอสอาร์ เซทล์ฟส์ ; ตั้งค่าช่องให้เหมาะสม
; ไม่มี SETNAM เนื่องจากหน้าจอไม่ต้องการชื่อ
;
; เปิดไฟล์โลจิคัล
เจเอสอาร์ เปิด
; ตั้งค่าช่องสัญญาณออก
LDX #$40 ; หมายเลขไฟล์โลจิคัล
เจเอสอาร์ CHKOUT
;
; ส่งออกถ่านไปที่หน้าจอ
แอลดีเอ #$05
เจเอสอาร์ CHROUT
; ปิดไฟล์ลอจิคัล
LDA #$40
เจเอสอาร์ ปิด

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

; ตั้งค่าช่อง
แอลดีเอ #$40 ; หมายเลขไฟล์โลจิคัล
LDX #$03 ; หมายเลขอุปกรณ์สำหรับหน้าจอคือ $03
แอลดี #$FF ; ไม่มีที่อยู่สำรอง
เจเอสอาร์ เซทล์ฟส์ ; ตั้งค่าช่องให้เหมาะสม
; ไม่มี SETNAM เนื่องจากหน้าจอไม่ต้องการชื่อ
;
; เปิดไฟล์โลจิคัล
เจเอสอาร์ เปิด
; ตั้งค่าช่องสัญญาณออก
LDX #$40 ; หมายเลขไฟล์โลจิคัล
เจเอสอาร์ CHKOUT
;
; ป้อนถ่านจากแป้นพิมพ์
รอ JSR GETIN ; ใส่ $00 ใน A หากคิวคีย์บอร์ดว่างเปล่า
ซีเอ็มพี #$00 ; หาก $00 ไปที่ A แล้ว Z จะเป็น 1 เมื่อเปรียบเทียบ
รอก่อน ; GETIN จากคิวอีกครั้งหาก 0 ไปที่ตัวสะสม
บีเอ็นอี พรนสCRN ; ไปที่ PRNSCRN หาก Z เป็น 0 เนื่องจาก A ไม่มี $00 อีกต่อไป
; ส่งออกถ่านไปที่หน้าจอ
PRNSCRN JSR CHROUT ; ส่งถ่านใน A ไปที่หน้าจอ
; ปิดไฟล์ลอจิคัล
LDA #$40
เจเอสอาร์ ปิด

บันทึก : WAIT และ PRNSCRN คือป้ายกำกับที่ระบุที่อยู่ ไบต์จากแป้นพิมพ์ที่มาถึงตัวสะสม µP คือรหัส ASCII รหัสที่เกี่ยวข้องที่จะส่งไปยังหน้าจอโดย Commodore-64 จะต้องแตกต่างออกไป นั่นไม่ได้นำมาพิจารณาในโปรแกรมก่อนหน้าเพื่อความเรียบง่าย

5.7 การส่งและรับไบต์สำหรับดิสก์ไดรฟ์

มีอะแดปเตอร์อินเทอร์เฟซที่ซับซ้อนสองตัวในยูนิตระบบ (มาเธอร์บอร์ด) ของ Commodore-64 ที่เรียกว่า VIA #1 และ CIA #2 CIA แต่ละแห่งมีพอร์ตขนานสองพอร์ตซึ่งเรียกว่าพอร์ต A และพอร์ต B มีพอร์ตภายนอกที่พื้นผิวแนวตั้งที่ด้านหลังของยูนิตระบบ Commodre-64 ซึ่งเรียกว่าเป็นพอร์ตอนุกรม พอร์ตนี้มี 6 พิน หนึ่งในนั้นใช้สำหรับข้อมูล ข้อมูลเข้าหรือออกจากยูนิตระบบเป็นอนุกรม ทีละบิต

บิตขนานแปดบิตจากพอร์ตภายใน A ของ CIA #2 สามารถออกจากยูนิตระบบผ่านพอร์ตอนุกรมภายนอก หลังจากถูกแปลงเป็นข้อมูลอนุกรมโดย shift register ใน CIA ข้อมูลอนุกรมแปดบิตจากพอร์ตอนุกรมภายนอกสามารถเข้าสู่พอร์ตภายใน A ของ CIA #2 หลังจากถูกแปลงเป็นข้อมูลแบบขนานโดย shift register ใน CIA

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

การส่งหรือรับข้อมูลสำหรับดิสก์ไดรฟ์ทำตามขั้นตอนเดียวกับที่อธิบายไว้ก่อนหน้านี้ นั่นคือ:

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

ต้องปิดไฟล์ลอจิคัล การปิดไฟล์โลจิคัลจะปิดช่องสัญญาณนั้นอย่างมีประสิทธิภาพ เมื่อตั้งค่าช่องสัญญาณสำหรับดิสก์ไดรฟ์ โปรแกรมเมอร์จะเป็นผู้กำหนดหมายเลขไฟล์ลอจิคัล เป็นตัวเลขระหว่าง $00 ถึง $FF (รวม) ไม่ควรเป็นตัวเลขที่เลือกไว้แล้วสำหรับอุปกรณ์อื่น (หรือไฟล์จริง) หมายเลขอุปกรณ์คือ 8 หากมีดิสก์ไดรฟ์เพียงตัวเดียว ที่อยู่สำรอง (หมายเลข) ได้มาจากคู่มือของดิสก์ไดรฟ์ โปรแกรมต่อไปนี้ใช้ 2 โปรแกรมเขียนตัวอักษร “E” (ASCII) ลงในไฟล์ในดิสก์ชื่อ “mydoc.doc” ชื่อนี้จะถือว่าเริ่มต้นที่ที่อยู่หน่วยความจำที่ $C101 ดังนั้น ไบต์ล่างของ $01 จะต้องอยู่ใน X register และไบต์ที่สูงกว่าของ $C1 จะต้องอยู่ใน Y register ก่อนที่จะเรียกใช้รูทีน SETNAM รีจิสเตอร์ A ควรมีหมายเลข $09 ก่อนที่จะเรียกใช้รูทีน SETNAM

; ตั้งค่าช่อง
แอลดีเอ #$40 ; หมายเลขไฟล์โลจิคัล
LDX #$08 ; หมายเลขอุปกรณ์สำหรับดิสก์ไดรฟ์แรก
LDY #$02 ; ที่อยู่รอง
เจเอสอาร์ เซทล์ฟส์ ; ตั้งค่าช่องให้เหมาะสม
;
; ไฟล์ในดิสก์ไดรฟ์ต้องมีชื่อ (อยู่ในหน่วยความจำแล้ว)
แอลดีเอ #$09
LDX #$01
แอลดี #$C1
เจเอสอาร์ เซทนาม
; เปิดไฟล์โลจิคัล
เจเอสอาร์ เปิด
; ตั้งค่าช่องสัญญาณออก
LDX #$40 ; หมายเลขไฟล์โลจิคัล
JSR CHKOUT ; สำหรับการเขียน
;
; ถ่านส่งออกไปยังดิสก์
แอลดีเอ #$45
เจเอสอาร์ CHROUT
; ปิดไฟล์ลอจิคัล
LDA #$40
เจเอสอาร์ ปิด

หากต้องการอ่านไบต์จากดิสก์ลงในรีจิสเตอร์ µP Y ให้ทำซ้ำโปรแกรมก่อนหน้าโดยมีการเปลี่ยนแปลงต่อไปนี้: แทนที่จะเป็น “JSR CHKOUT ; สำหรับการเขียน” ให้ใช้ “JSR CHKIN ; เพื่อการอ่าน” แทนที่ส่วนรหัสสำหรับ “; ส่งออกถ่านไปยังดิสก์” โดยมีดังต่อไปนี้:

; ป้อนถ่านจากดิสก์
เจเอสอาร์ คริส

รูทีน OS CHRIN เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFCF เมื่อเรียกรูทีนนี้ จะได้รับไบต์จากช่องสัญญาณที่ตั้งค่าเป็นช่องสัญญาณอินพุตแล้ว และใส่ลงในรีจิสเตอร์ µP A รูทีน GETIN ROM OS สามารถใช้แทน CHRIN ได้เช่นกัน

การส่งไบต์ไปยังเครื่องพิมพ์
การส่งไบต์ไปยังเครื่องพิมพ์ทำได้ในลักษณะเดียวกันกับการส่งไบต์ไปยังไฟล์ในดิสก์

5.8 กิจวัตร OS SAVE

OS SAVE Routine เข้าถึงได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFD8 รูทีน OS SAVE ใน ROM จะบันทึก (ดัมพ์) ส่วนของหน่วยความจำลงในดิสก์เป็นไฟล์ (พร้อมชื่อ) ต้องทราบที่อยู่เริ่มต้นของส่วนในหน่วยความจำ ต้องทราบที่อยู่สิ้นสุดของส่วนด้วย ไบต์ล่างของที่อยู่เริ่มต้นจะอยู่ในหน้าศูนย์ใน RAM ที่ที่อยู่ $002B ไบต์ที่สูงกว่าของที่อยู่เริ่มต้นจะถูกวางไว้ในตำแหน่งหน่วยความจำไบต์ถัดไปที่ที่อยู่ $002C ในหน้าศูนย์ ป้ายกำกับ TXTTAB อ้างถึงที่อยู่ทั้งสองนี้ แม้ว่าจริงๆ แล้ว TXTTAB จะหมายถึงที่อยู่ $002B ก็ตาม ไบต์ล่างของที่อยู่ปลายทางจะอยู่ในรีจิสเตอร์ µP X ไบต์ที่สูงกว่าของที่อยู่ปลายทางบวก 1 จะถูกวางไว้ในรีจิสเตอร์ µP Y รีจิสเตอร์ µP A รับค่า $2B สำหรับ TXTTAB ($002B) ด้วยเหตุนี้จึงสามารถเรียกใช้รูทีน SAVE ได้ดังต่อไปนี้:

เจเอสอาร์ บันทึก

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

  • ตั้งค่าช่องโดยใช้รูทีน SETLFS
  • ตั้งชื่อโลจิคัลไฟล์ (หมายเลข) ซึ่งเหมือนกับชื่อดิสก์ไฟล์จริงโดยใช้รูทีน SETNAM
  • เปิดไฟล์โลจิคัลโดยใช้รูทีน OPEN
  • ทำให้เป็นไฟล์สำหรับเอาต์พุตโดยใช้ CHKOUT
  • รหัสสำหรับการบันทึกไฟล์อยู่ที่นี่ซึ่งลงท้ายด้วย “JSR SAVE”
  • ปิดโลจิคัลไฟล์โดยใช้รูทีน CLOSE

โปรแกรมต่อไปนี้จะบันทึกไฟล์ที่เริ่มต้นจากตำแหน่งหน่วยความจำที่ $C101 ถึง $C200:

; ตั้งค่าช่อง
แอลดีเอ #$40 ; หมายเลขไฟล์โลจิคัล
LDX #$08 ; หมายเลขอุปกรณ์สำหรับดิสก์ไดรฟ์แรก
LDY #$02 ; ที่อยู่รอง
เจเอสอาร์ เซทล์ฟส์ ; ตั้งค่าช่องให้เหมาะสม
;
; ชื่อไฟล์ในดิสก์ไดรฟ์ (มีอยู่ในหน่วยความจำแล้วที่ $C301)
แอลดีเอ #$09 ; ความยาวของชื่อไฟล์
LDX #$01
แอลดี #$C3
เจเอสอาร์ เซทนาม
; เปิดไฟล์โลจิคัล
เจเอสอาร์ เปิด
; ตั้งค่าช่องสัญญาณออก
LDX #$40 ; หมายเลขไฟล์โลจิคัล
JSR CHKOUT ; สำหรับการเขียน
;
; ไฟล์เอาท์พุตลงดิสก์
แอลดีเอ #$01
STA $2B ; TXTTAB
แอลดีเอ #$C1
STA $2C
LDX #$00
แอลดี#$C2
แอลดีเอ #$2B
เจเอสอาร์ บันทึก
; ปิดไฟล์ลอจิคัล
LDA #$40
เจเอสอาร์ ปิด

โปรดทราบว่านี่เป็นโปรแกรมที่บันทึกส่วนอื่นของหน่วยความจำ (ไม่ใช่ส่วนของโปรแกรม) ลงในดิสก์ (ดิสเก็ตต์สำหรับ Commodore-64)

5.9 กิจวัตรโหลด OS

เข้าถึง OS LOAD Routine ได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFD5 เมื่อส่วน (พื้นที่ขนาดใหญ่) ของหน่วยความจำถูกบันทึกลงในดิสก์ ส่วนนั้นจะถูกบันทึกด้วยส่วนหัวซึ่งมีที่อยู่เริ่มต้นของส่วนนั้นในหน่วยความจำ รูทีนย่อย OS LOAD โหลดไบต์ของไฟล์ลงในหน่วยความจำ ด้วยการดำเนินการ LOAD นี้ ค่าของตัวสะสมจะต้องเป็น 010 ($00) เพื่อให้การดำเนินการ LOAD อ่านที่อยู่เริ่มต้นในส่วนหัวของไฟล์ในดิสก์และใส่ไบต์ของไฟล์ใน RAM โดยเริ่มต้นจากที่อยู่นั้น ที่อยู่รองสำหรับช่องสัญญาณจะต้องเป็น 1 หรือ 2 (โปรแกรมต่อไปนี้ใช้ 2) รูทีนนี้จะส่งคืนที่อยู่บวก 1 ตำแหน่ง RAM สูงสุดที่โหลด ซึ่งหมายความว่าไบต์ต่ำของที่อยู่สุดท้ายของไฟล์ใน RAM บวก 1 จะถูกใส่ไว้ในรีจิสเตอร์ µP X และไบต์สูงของที่อยู่สุดท้ายของไฟล์ใน RAM บวก 1 จะถูกใส่ไว้ในรีจิสเตอร์ µP Y

หากการโหลดไม่สำเร็จ รีจิสเตอร์ µP A จะเก็บหมายเลขข้อผิดพลาดไว้ (อาจเป็น 4, 5, 8 หรือ 9) การตั้งค่าสถานะ C ของการลงทะเบียนสถานะไมโครโปรเซสเซอร์ก็ถูกตั้งค่าเช่นกัน (สร้าง 1) หากการโหลดสำเร็จ ค่าสุดท้ายของรีจิสเตอร์ A ก็ไม่สำคัญ

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

เจเอสอาร์ สตาร์ท

“JSR START” อยู่ในโปรแกรมภาษาแอสเซมบลีที่โหลดโปรแกรมที่จะรัน ภาษาแอสเซมบลีที่โหลดไฟล์ภาษาแอสเซมบลีอื่นและเรียกใช้ไฟล์ที่โหลดมีขั้นตอนรหัสต่อไปนี้:

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

โปรแกรมต่อไปนี้โหลดไฟล์จากดิสก์และรัน:

; ตั้งค่าช่อง
แอลดีเอ #$40 ; หมายเลขไฟล์โลจิคัล
LDX #$08 ; หมายเลขอุปกรณ์สำหรับดิสก์ไดรฟ์แรก
LDY #$02 ; ที่อยู่รอง
เจเอสอาร์ เซทล์ฟส์ ; ตั้งค่าช่องให้เหมาะสม
;
; ชื่อไฟล์ในดิสก์ไดรฟ์ (มีอยู่ในหน่วยความจำแล้วที่ $C301)
แอลดีเอ #$09 ; ความยาวของชื่อไฟล์
LDX #$01
แอลดี #$C3
เจเอสอาร์ เซทนาม
; เปิดไฟล์โลจิคัล
เจเอสอาร์ เปิด
; กำหนดช่องสัญญาณเข้า
LDX #$40 ; หมายเลขไฟล์โลจิคัล
เจเอสอาร์ CHKIN ; สำหรับการอ่าน
;
; อินพุตไฟล์จากดิสก์
LDA #$00
โหลด JSR
; ปิดไฟล์ลอจิคัล
LDA #$40
เจเอสอาร์ ปิด
; เริ่มโหลดโปรแกรม
เจเอสอาร์ สตาร์ท

5.10 โมเด็มและมาตรฐาน RS-232

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

จำเป็นต้องเชื่อมต่อโมเด็มกับคอมพิวเตอร์ที่พอร์ตภายนอก (ที่พื้นผิวแนวตั้งของคอมพิวเตอร์) มาตรฐาน RS-232 หมายถึงตัวเชื่อมต่อประเภทใดชนิดหนึ่งซึ่งเชื่อมต่อโมเด็มเข้ากับคอมพิวเตอร์ (ในอดีต) กล่าวอีกนัยหนึ่ง คอมพิวเตอร์จำนวนมากในอดีตมีพอร์ตภายนอกที่เป็นขั้วต่อ RS-232 หรือขั้วต่อที่รองรับ RS-232

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

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

ด้านล่างของหน่วยความจำ
คำว่า “Bottom of Memory” ไม่ได้หมายถึงตำแหน่งไบต์หน่วยความจำของที่อยู่ $0000 หมายถึงตำแหน่ง RAM ต่ำสุดที่ผู้ใช้สามารถเริ่มวางข้อมูลและโปรแกรมของตนได้ โดยค่าเริ่มต้นคือ $0800 จำจากการสนทนาก่อนหน้านี้ว่าตำแหน่งจำนวนมากระหว่าง $0800 ถึง $BFFF ถูกใช้โดยภาษาคอมพิวเตอร์ BASIC และโปรแกรมเมอร์ (ผู้ใช้) เหลือเพียงตำแหน่งที่อยู่ $C000 ถึง $CFFF สำหรับใช้สำหรับโปรแกรมและข้อมูลภาษาแอสเซมบลี นี่คือ 4Kbytes จาก 64 Kbytes ของหน่วยความจำ

ด้านบนของหน่วยความจำ
ในสมัยนั้น เมื่อลูกค้าซื้อคอมพิวเตอร์ Commodore-64 คอมพิวเตอร์บางเครื่องไม่ได้มาพร้อมกับตำแหน่งหน่วยความจำทั้งหมด คอมพิวเตอร์ดังกล่าวมี ROM พร้อมระบบปฏิบัติการตั้งแต่ $E000 ถึง $FFFF พวกเขามี RAM ตั้งแต่ $0,000 ถึงขีดจำกัด ซึ่งไม่ใช่ $DFFF ถัดจาก $E000 ขีดจำกัดนั้นต่ำกว่า $DFFF และขีดจำกัดนั้นเรียกว่า 'ด้านบนของหน่วยความจำ' ดังนั้นหน่วยความจำระดับบนสุดไม่ได้อ้างอิงถึงตำแหน่ง $FFFF

บัฟเฟอร์ Commodore-64 สำหรับการสื่อสาร RS-232
การส่งบัฟเฟอร์
บัฟเฟอร์สำหรับการส่ง RS-232 (เอาต์พุต) ใช้เวลา 256 ไบต์จากหน่วยความจำบนลงล่าง ตัวชี้สำหรับบัฟเฟอร์การส่งนี้มีป้ายกำกับว่า ROBUF ตัวชี้นี้อยู่ในหน้าศูนย์โดยมีที่อยู่ $00F9 ตามด้วย $00FA ROBUF ระบุ $00F9 จริงๆ ดังนั้น หากที่อยู่สำหรับการเริ่มต้นบัฟเฟอร์คือ $BE00 ไบต์ล่างของ $BE00 ซึ่งก็คือ $00 จะอยู่ในตำแหน่ง $00F9 และไบต์ที่สูงกว่าของ $BE00 ซึ่งก็คือ $BE จะอยู่ใน $00FA ที่ตั้ง.

การรับบัฟเฟอร์
บัฟเฟอร์เพื่อรับ RS-232 ไบต์ (อินพุต) ใช้เวลา 256 ไบต์จากด้านล่างของบัฟเฟอร์การส่งสัญญาณ ตัวชี้สำหรับบัฟเฟอร์การรับนี้มีป้ายกำกับว่า RIBUF ตัวชี้นี้อยู่ในหน้าศูนย์โดยมีที่อยู่ $00F7 ตามด้วย $00F8 RIBUF ระบุ $00F7 จริงๆ ดังนั้น หากที่อยู่สำหรับการเริ่มต้นบัฟเฟอร์คือ $BF00 ไบต์ล่างของ $BF00 ซึ่งก็คือ $00 จะอยู่ในตำแหน่ง $00F7 และไบต์ที่สูงกว่าของ $BF00 ซึ่งก็คือ $BF จะอยู่ในตำแหน่ง $00F8 ที่ตั้ง. ดังนั้น 512 ไบต์จากหน่วยความจำบนสุดจึงถูกใช้เป็นบัฟเฟอร์ RS-232 RAM ทั้งหมด

ช่อง RS-232
เมื่อโมเด็มเชื่อมต่อกับพอร์ตผู้ใช้ (ภายนอก) การสื่อสารกับโมเด็มจะเป็นเพียงการสื่อสาร RS-232 ขั้นตอนการมีช่อง RS-232 ที่สมบูรณ์นั้นเกือบจะเหมือนกับในการสนทนาครั้งก่อน แต่มีข้อแตกต่างที่สำคัญอย่างหนึ่ง: ชื่อไฟล์คือรหัสและไม่ใช่สตริงในหน่วยความจำ รหัส $0610 เป็นตัวเลือกที่ดี หมายถึงอัตรารับส่งข้อมูล 300 บิต/วินาที และพารามิเตอร์ทางเทคนิคอื่นๆ นอกจากนี้ยังไม่มีที่อยู่สำรอง โปรดทราบว่าหมายเลขอุปกรณ์คือ 2 ขั้นตอนการตั้งค่าช่อง RS-232 ให้สมบูรณ์คือ:

  • การตั้งค่าช่องสัญญาณโดยใช้รูทีน SETLFS
  • การตั้งชื่อโลจิคัลไฟล์ $0610
  • การเปิดไฟล์โลจิคัลโดยใช้รูทีน OPEN
  • ทำให้เป็นไฟล์สำหรับเอาต์พุตโดยใช้ CHKOUT หรือไฟล์สำหรับอินพุตโดยใช้ CHKIN
  • การส่งไบต์เดี่ยวด้วย CHROUT หรือการรับไบต์เดี่ยวด้วย GETIN
  • การปิดโลจิคัลไฟล์โดยใช้รูทีน CLOSE

เข้าถึง OS GETIN Routine ได้โดยการกระโดด (JSR) ไปยังตารางการข้าม OS ROM ที่ $FFE4 เมื่อเรียกใช้รูทีนนี้ จะนำไบต์ที่ส่งไปยังบัฟเฟอร์ตัวรับ และวาง (ส่งคืน) ไบต์นั้นไปในตัวสะสม µP

โปรแกรมต่อไปนี้จะส่งไบต์ “E” (ASCII) ไปยังโมเด็มซึ่งเชื่อมต่อกับพอร์ตที่รองรับ RS-232 ของผู้ใช้:

; ตั้งค่าช่อง
แอลดีเอ #$40 ; หมายเลขไฟล์โลจิคัล
LDX #$02 ; หมายเลขอุปกรณ์สำหรับ RS-232
แอลดี #$FF ; ไม่มีที่อยู่สำรอง
เจเอสอาร์ เซทล์ฟส์ ; ตั้งค่าช่องให้เหมาะสม
;
; ชื่อ RS-232 เป็นรหัส เช่น 0610 ดอลลาร์
แอลดีเอ #$02 ; ความยาวของโค้ดคือ 2 ไบต์
LDX #$10
แอลดี#$06
เจเอสอาร์ เซทนาม
;
; เปิดไฟล์โลจิคัล
เจเอสอาร์ เปิด
; ตั้งค่าช่องสัญญาณออก
LDX #$40 ; หมายเลขไฟล์โลจิคัล
เจเอสอาร์ CHKOUT
;
; ถ่านเอาท์พุทเป็น RS-232 เช่น โมเด็ม
แอลดีเอ #$45
เจเอสอาร์ CHROUT
; ปิดไฟล์ลอจิคัล
LDA #$40
เจเอสอาร์ ปิด

ในการรับไบต์ รหัสจะคล้ายกันมาก ยกเว้นว่า 'JSR CHKOUT' จะถูกแทนที่ด้วย 'JSR CHKIN' และ:

แอลดีเอ #$45
เจเอสอาร์ CHROUT

ถูกแทนที่ด้วย “JSR GETIN” โดยผลลัพธ์จะถูกวางไว้ในทะเบียน A

การส่งหรือรับไบต์อย่างต่อเนื่องทำได้โดยการวนซ้ำสำหรับการส่งหรือรับส่วนของโค้ดตามลำดับ

โปรดทราบว่าอินพุตและเอาต์พุตด้วย Commodore จะคล้ายกันในกรณีส่วนใหญ่ ยกเว้นคีย์บอร์ดที่โปรแกรมเมอร์ไม่ได้เรียกรูทีนบางรูทีน แต่ถูกเรียกโดยระบบปฏิบัติการ

5.11 การนับและการจับเวลา

พิจารณาลำดับการนับถอยหลังซึ่งก็คือ:

2, 1, 0

นี่คือการนับถอยหลังจาก 2 ถึง 0 ทีนี้ ลองพิจารณาลำดับการนับถอยหลังซ้ำ:

2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0

นี่คือการนับถอยหลังซ้ำของลำดับเดียวกัน ลำดับซ้ำสี่ครั้ง สี่ครั้งหมายถึงเวลาคือ 4 ภายในหนึ่งลำดับจะมีการนับ การทำซ้ำลำดับเดียวกันคือจังหวะเวลา

มีอะแดปเตอร์อินเทอร์เฟซที่ซับซ้อนสองตัวในยูนิตระบบของ Commodore-64 CIA แต่ละแห่งมีวงจรตัวนับ/ตัวจับเวลาสองตัวชื่อ Timer A (TA) และ Timer B (TB) วงจรการนับไม่แตกต่างจากวงจรไทม์มิ่ง ตัวนับหรือตัวจับเวลาใน Commodore-64 อ้างถึงสิ่งเดียวกัน ในความเป็นจริง ทั้งสองอย่างโดยพื้นฐานแล้วอ้างถึงรีจิสเตอร์ 16 บิตหนึ่งตัวซึ่งจะนับถอยหลังถึง 0 เสมอที่พัลส์นาฬิกาของระบบ สามารถตั้งค่าต่างๆ ลงในรีจิสเตอร์ 16 บิตได้ ยิ่งค่ามากเท่าไร การนับถอยหลังถึงศูนย์ก็จะใช้เวลานานขึ้นเท่านั้น แต่ละครั้งที่ตัวจับเวลาตัวใดตัวหนึ่งผ่านไปเลยศูนย์ IRQ สัญญาณขัดจังหวะจะถูกส่งไปยังไมโครโปรเซสเซอร์ เมื่อการนับถอยหลังผ่านศูนย์ เรียกว่าอันเดอร์โฟลว์

ตัวจับเวลาสามารถทำงานในโหมดครั้งเดียวหรือในโหมดต่อเนื่อง ทั้งนี้ขึ้นอยู่กับวิธีการตั้งโปรแกรมวงจรตัวจับเวลา จากภาพประกอบก่อนหน้านี้ โหมดครั้งเดียวหมายถึง 'ทำ 2, 1, 0' และหยุดในขณะที่นาฬิกายังเต้นต่อเนื่อง โหมดต่อเนื่องจะเป็นเช่น “2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, ฯลฯ” ซึ่งดำเนินต่อไปตามจังหวะนาฬิกา นั่นหมายความว่าเมื่อมันเลยศูนย์ไปแล้ว หากไม่มีคำสั่งใดๆ ลำดับการนับถอยหลังจะวนซ้ำ จำนวนที่มากที่สุดมักจะมากกว่า 2 มาก

ตัวจับเวลา A (TA) ของ CIA #1 สร้างขึ้น IRQ เป็นระยะๆ (ระยะเวลา) เพื่อให้บริการคีย์บอร์ด อันที่จริงนี่คือทุกๆ 1/60 วินาทีตามค่าเริ่มต้น IRQ ถูกส่งไปยังไมโครโปรเซสเซอร์ทุกๆ 1/60 วินาที มันเป็นเพียงเมื่อ IRQ ถูกส่งไปว่าโปรแกรมสามารถอ่านค่าคีย์จากคิวคีย์บอร์ด (บัฟเฟอร์) โปรดจำไว้ว่าไมโครโปรเซสเซอร์มีพินเพียงอันเดียวสำหรับ IRQ สัญญาณ. ไมโครโปรเซสเซอร์ยังมีพินเพียงอันเดียวสำหรับ เอ็นเอ็มไอ สัญญาณ. สัญญาณ §NMI ที่ส่งไปยังไมโครโปรเซสเซอร์จะมาจาก CIA #2 เสมอ

รีจิสเตอร์ตัวจับเวลา 16 บิตมีที่อยู่หน่วยความจำสองที่อยู่: หนึ่งรายการสำหรับไบต์ล่างและอีกรายการหนึ่งสำหรับไบต์ที่สูงกว่า CIA แต่ละแห่งมีวงจรจับเวลาสองวงจร CIA ทั้งสองคนเหมือนกัน สำหรับ CIA #1 ที่อยู่สำหรับตัวจับเวลาสองตัวคือ: DC04 และ DC05 สำหรับ TA และ DC06 และ DC07 สำหรับ TB สำหรับ CIA #2 ที่อยู่สำหรับตัวจับเวลาสองตัวคือ: DD04 และ DD05 สำหรับ TA และ DD06 และ DD07 สำหรับ TB

สมมติว่าจะต้องส่งหมายเลข 25510 ไปยังเครื่องจับเวลา TA ของ CIA #2 เพื่อนับถอยหลัง 25510 = 00000000111111112 อยู่ในสิบหกบิต 00000000111111112 = $000FFF อยู่ในรูปเลขฐานสิบหก ในกรณีนี้ $FF จะถูกส่งไปยังเครื่องบันทึกที่ที่อยู่ $DD04 และ $00 จะถูกส่งไปยังเครื่องบันทึกที่ที่อยู่ $DD05 ซึ่งเป็นจุดสิ้นสุดเล็กน้อย ส่วนรหัสต่อไปนี้ส่งหมายเลขไปที่การลงทะเบียน:

แอลดีเอ #$FF
รัฐ $DD04
LDA #$00
รัฐ $DD05

แม้ว่าการลงทะเบียนใน CIA จะมีที่อยู่ RAM แต่จริงๆ แล้วพวกมันอยู่ใน CIA และ CIA ก็เป็น IC แยกจาก RAM หรือ ROM

นั่นไม่ใช่ทั้งหมด! เมื่อตัวจับเวลาได้รับตัวเลขสำหรับการนับถอยหลัง เช่น ด้วยรหัสก่อนหน้า การนับถอยหลังจะไม่เริ่ม การนับถอยหลังจะเริ่มต้นเมื่อมีการส่งไบต์ขนาด 8 บิตไปยังรีจิสเตอร์ควบคุมที่เกี่ยวข้องสำหรับตัวจับเวลา บิตแรกของไบต์นี้สำหรับรีจิสเตอร์ควบคุมจะระบุว่าการนับถอยหลังควรเริ่มต้นหรือไม่ ค่า 0 สำหรับบิตแรกนี้หมายถึงการหยุดนับถอยหลัง ในขณะที่ค่า 1 หมายถึงการเริ่มนับถอยหลัง นอกจากนี้ ไบต์จะต้องระบุว่าการนับถอยหลังอยู่ในโหมดช็อตเดียว (ครั้งเดียว) หรือในโหมดทำงานอิสระ (โหมดต่อเนื่อง) โหมด One-shot จะนับถอยหลังและหยุดเมื่อค่าของรีจิสเตอร์ตัวจับเวลากลายเป็นศูนย์ ในโหมดการทำงานอิสระ การนับถอยหลังจะทำซ้ำหลังจากถึง 0 บิตที่สี่ (ดัชนี 3) ของไบต์ที่ถูกส่งไปยังรีจิสเตอร์ควบคุมระบุโหมด: 0 หมายถึงโหมดการทำงานอิสระ และ 1 หมายถึงโหมดการถ่ายภาพครั้งเดียว

ตัวเลขที่เหมาะสมในการเริ่มนับในโหมดช็อตเดียวคือ 000010012 = 09 ดอลลาร์ในรูปแบบเลขฐานสิบหก จำนวนที่เหมาะสมในการเริ่มนับในโหมดวิ่งอิสระคือ 000000012 = $01 ในรูปแบบเลขฐานสิบหก รีจิสเตอร์แต่ละตัวมีรีจิสเตอร์ควบคุมของตัวเอง ใน CIA #1 รีจิสเตอร์ควบคุมสำหรับตัวจับเวลา A มีที่อยู่ RAM เป็น DC0E16 และรีจิสเตอร์ควบคุมสำหรับตัวจับเวลา B มีที่อยู่ RAM เป็น DC0F16 ใน CIA #2 รีจิสเตอร์ควบคุมสำหรับตัวจับเวลา A มีที่อยู่ RAM เป็น DD0E16 และรีจิสเตอร์ควบคุมสำหรับตัวจับเวลา B มีที่อยู่ RAM เป็น DD0F16 หากต้องการเริ่มนับถอยหลังจำนวน 16 บิตใน TA ของ CIA #2 ในโหมด one-shot ให้ใช้โค้ดต่อไปนี้:

แอลดีเอ #$09
STA $DD0E

หากต้องการเริ่มนับถอยหลังจำนวน 16 บิตใน TA ของ CIA #2 ในโหมดทำงานอย่างอิสระ ให้ใช้รหัสต่อไปนี้:

แอลดีเอ #$01
STA $DD0E

5.12 ต IRQ และ เอ็นเอ็มไอ คำขอ

ไมโครโปรเซสเซอร์ 6502 มี IRQ และ เอ็นเอ็มไอ เส้น (หมุด) ทั้ง CIA #1 และ CIA #2 ต่างมี IRQ พินสำหรับไมโครโปรเซสเซอร์ ที่ IRQ พินของ CIA #2 เชื่อมต่อกับ เอ็นเอ็มไอ พินของ µP ที่ IRQ พินของ CIA #1 เชื่อมต่อกับ IRQ พินของ µP นี่เป็นเพียงสองบรรทัดขัดจังหวะที่เชื่อมต่อไมโครโปรเซสเซอร์ ดังนั้น IRQ หมุดของ CIA #2 คือ เอ็นเอ็มไอ แหล่งที่มาและยังสามารถมองเห็นได้ว่าเป็นเส้น §NMI

CIA #1 มีแหล่งที่เป็นไปได้ห้าแหล่งในการสร้าง IRQ สัญญาณสำหรับ µP CIA #2 มีโครงสร้างเหมือนกับ CIA #1 ดังนั้น CIA #2 จึงมีแหล่งที่มาที่เป็นไปได้ทันทีห้าแหล่งที่เป็นไปได้ในการสร้างสัญญาณขัดจังหวะในครั้งนี้ ซึ่งก็คือ เอ็นเอ็มไอ สัญญาณ. โปรดจำไว้ว่าเมื่อ µP ได้รับ เอ็นเอ็มไอ สัญญาณถ้ามันกำลังจัดการ IRQ ร้องขอ มันจะระงับสิ่งนั้นและจัดการ เอ็นเอ็มไอ ขอ. เมื่อจัดการเสร็จแล้ว. เอ็นเอ็มไอ ร้องขอ จากนั้นจะดำเนินการจัดการต่อ IRQ ขอ.

โดยปกติแล้ว CIA #1 จะเชื่อมต่อภายนอกเข้ากับคีย์บอร์ดและอุปกรณ์เกม เช่น จอยสติ๊ก แป้นพิมพ์ใช้พอร์ต A ของ CIA #1 มากกว่าพอร์ต B อุปกรณ์เกมใช้พอร์ต CIA #1 B มากกว่าพอร์ต A โดยปกติ CIA #2 จะเชื่อมต่อภายนอกเข้ากับดิสก์ไดรฟ์ (เดซี่ผูกมัดกับเครื่องพิมพ์) และโมเด็ม ดิสก์ไดรฟ์ใช้พอร์ต A ของ CIA #2 (แม้ว่าจะผ่านพอร์ตอนุกรมภายนอกก็ตาม) มากกว่าพอร์ต B โมเด็ม (RS-232) ใช้พอร์ต CIA #2 B มากกว่าพอร์ต A

ด้วยเหตุนี้ยูนิตระบบจะรู้ได้อย่างไรว่าอะไรเป็นสาเหตุของ IRQ หรือ เอ็นเอ็มไอ ขัดจังหวะ? CIA #1 และ CIA #2 มีแหล่งที่มาของการขัดจังหวะทันทีห้าแหล่ง หากสัญญาณขัดจังหวะไปที่ µP เป็น เอ็นเอ็มไอ แหล่งที่มาเป็นหนึ่งในห้าแหล่งจาก CIA #2 หากสัญญาณขัดจังหวะไปที่ µP เป็น IRQ แหล่งที่มาเป็นหนึ่งในห้าแหล่งข้อมูลทันทีจาก CIA #1

คำถามต่อไปคือ “หน่วยระบบจะแยกความแตกต่างระหว่างแหล่งข้อมูลเฉพาะหน้าทั้งห้าของ CIA แต่ละรายการได้อย่างไร” CIA แต่ละตัวมีรีจิสเตอร์ 8 บิตซึ่งเรียกว่า Interrupt Control Register (ICR) ICR ให้บริการทั้งสองพอร์ตของ CIA ตารางต่อไปนี้แสดงความหมายของแปดบิตของรีจิสเตอร์ควบคุมอินเตอร์รัปต์ โดยเริ่มจากบิต 0:

ตารางที่ 5.13
การลงทะเบียนการควบคุมการขัดจังหวะ
ดัชนีบิต ความหมาย
0 ตั้งค่า (สร้าง 1) โดยอันเดอร์โฟลว์ของตัวจับเวลา A
1 กำหนดโดยอันเดอร์โฟลว์ของตัวจับเวลา B
2 ตั้งค่าเมื่อนาฬิกาบอกเวลาเท่ากับนาฬิกาปลุก
3 ตั้งค่าเมื่อพอร์ตอนุกรมเต็ม
4 ตั้งค่าโดยอุปกรณ์ภายนอก
5 ไม่ได้ใช้ (สร้าง 0)
6 ไม่ได้ใช้ (สร้าง 0)
7 ตั้งค่าเมื่อตั้งค่าห้าบิตแรกใด ๆ

ดังที่เห็นได้จากตาราง แต่ละแหล่งที่มาทันทีจะแสดงด้วยหนึ่งในห้าบิตแรก ดังนั้น เมื่อได้รับสัญญาณอินเทอร์รัปต์ที่ µP จะต้องดำเนินการโค้ดเพื่ออ่านเนื้อหาของรีจิสเตอร์ควบคุมอินเทอร์รัปต์ เพื่อทราบแหล่งที่มาที่แน่นอนของการอินเทอร์รัปต์ ที่อยู่ RAM สำหรับ ICR ของ CIA #1 คือ DC0D16 ที่อยู่ RAM สำหรับ ICR ของ CIA #2 คือ DD0D16 หากต้องการอ่าน (ส่งคืน) เนื้อหาของ ICR ของ CIA #1 ไปยัง µP accumulator ให้พิมพ์คำสั่งต่อไปนี้:

LDA$DC0D

หากต้องการอ่าน (ส่งคืน) เนื้อหาของ ICR ของ CIA #2 ไปยัง µP accumulator ให้พิมพ์คำสั่งต่อไปนี้:

LDA $DD0D

5.13 โปรแกรมเบื้องหลังที่ขับเคลื่อนด้วยอินเตอร์รัปต์

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

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

ตัวชี้สำหรับคำสั่ง BRK
ที่ตำแหน่ง RAM ที่ต่อเนื่องกันของที่อยู่ $0316 และ $0317 คือตัวชี้ (เวกเตอร์) สำหรับรูทีนคำสั่ง BRK จริง ตัวชี้เริ่มต้นจะวางไว้ตรงนั้นเมื่อคอมพิวเตอร์เปิดทำงานโดยระบบปฏิบัติการใน ROM ตัวชี้เริ่มต้นนี้เป็นที่อยู่ที่ยังคงชี้ไปยังตัวจัดการคำสั่ง BRK เริ่มต้นใน OS ROM ตัวชี้เป็นที่อยู่ 16 บิต ไบต์ล่างของตัวชี้จะถูกวางไว้ในตำแหน่งไบต์ของที่อยู่ $0306 และไบต์ที่สูงกว่าของตัวชี้จะถูกวางไว้ในตำแหน่งไบต์ $0317

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

ง่ายต่อการแก้ไขปัญหานี้: ทุกครั้งที่คอมพิวเตอร์ต้องรอคีย์จากคีย์บอร์ด ให้แทรกคำสั่ง BRK ในโค้ดและแทนที่ตัวชี้ที่ $0316 (และ $0317) ด้วยตัวชี้ของรูทีนย่อยถัดไปของวินาที ( กำหนดเอง) โปรแกรม ด้วยวิธีนี้ทั้งสองโปรแกรมจะทำงานในช่วงเวลาที่ไม่นานกว่าโปรแกรมหลักที่รันเพียงอย่างเดียว

5.14 การประกอบและการรวบรวม

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

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

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

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

5.15 การบันทึก การโหลด และการรันโปรแกรม

โดยปกติภาษาแอสเซมบลีจะถูกเขียนในโปรแกรมแก้ไขบางโปรแกรม (ซึ่งอาจมาพร้อมกับโปรแกรมแอสเซมเบลอร์) โปรแกรมแก้ไขจะระบุตำแหน่งที่โปรแกรมเริ่มต้นและสิ้นสุดในหน่วยความจำ (RAM) รูทีน Kernal SAVE ของ OS ROM ของ Commodore-64 สามารถบันทึกโปรแกรมในหน่วยความจำลงดิสก์ได้ มันเพียงแค่ทิ้งส่วน (บล็อก) ของหน่วยความจำซึ่งอาจมีการเรียกคำสั่งไปยังดิสก์ ขอแนะนำให้มีคำสั่งเรียก SAVE แยกออกจากโปรแกรมที่กำลังบันทึก เพื่อว่าเมื่อโปรแกรมถูกโหลดจากดิสก์ลงในหน่วยความจำ มันจะไม่บันทึกตัวเองอีกเมื่อถูกเรียกใช้ การโหลดโปรแกรมภาษาแอสเซมบลีจากดิสก์เป็นความท้าทายที่แตกต่างออกไป เนื่องจากโปรแกรมไม่สามารถโหลดตัวเองได้

โปรแกรมไม่สามารถโหลดตัวเองจากดิสก์ไปยังตำแหน่งที่เริ่มต้นและสิ้นสุดใน RAM โดยปกติแล้ว Commodore-64 ในสมัยนั้นจะมีล่าม BASIC มาให้เพื่อใช้งานโปรแกรมภาษา BASIC เมื่อเครื่อง (คอมพิวเตอร์) เปิดอยู่ เครื่องจะจัดการด้วยพร้อมท์คำสั่ง: READY จากนั้นคุณสามารถพิมพ์คำสั่งพื้นฐานหรือคำแนะนำได้โดยการกดปุ่ม 'Enter' หลังจากพิมพ์ คำสั่งพื้นฐาน (คำสั่ง) เพื่อโหลดไฟล์คือ:

โหลด “ชื่อไฟล์”,8,1

คำสั่งเริ่มต้นด้วยคำสงวน BASIC ซึ่งก็คือ LOAD ตามด้วยช่องว่าง ตามด้วยชื่อไฟล์ด้วยเครื่องหมายคำพูดคู่ ตามด้วยหมายเลขอุปกรณ์ 8 ซึ่งนำหน้าด้วยเครื่องหมายจุลภาค ที่อยู่สำรองสำหรับดิสก์ซึ่งก็คือ 1 ตามด้วยเครื่องหมายจุลภาคนำหน้า ด้วยไฟล์ดังกล่าว ที่อยู่เริ่มต้นของโปรแกรมภาษาแอสเซมบลีจะอยู่ในส่วนหัวของไฟล์ในดิสก์ เมื่อ BASIC โหลดโปรแกรมเสร็จแล้ว ที่อยู่ RAM สุดท้ายบวก 1 ของโปรแกรมจะถูกส่งกลับ คำว่า 'ส่งคืน' ในที่นี้หมายความว่าไบต์ล่างของที่อยู่สุดท้ายบวก 1 จะถูกใส่ไว้ในรีจิสเตอร์ µP X และไบต์ที่สูงกว่าของที่อยู่สุดท้ายบวก 1 จะอยู่ในรีจิสเตอร์ µP Y

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

สมมติว่าจุดเริ่มต้นของการดำเนินการ (กำลังทำงาน) ที่อยู่ RAM สำหรับโปรแกรมภาษาแอสเซมบลีคือ C12316, C123 จะถูกแปลงเป็นฐานสิบก่อนที่จะใช้กับคำสั่ง SYS การแปลง C12316 เป็นฐานสิบมีดังนี้:

ดังนั้นคำสั่ง BASIC SYS คือ:

เอสไอเอส 49443

5.16 การบูตสำหรับ Commodore-64

การบูต Commodore-64 ประกอบด้วยสองขั้นตอน: ขั้นตอนการรีเซ็ตฮาร์ดแวร์และขั้นตอนการเริ่มต้นระบบปฏิบัติการ ระบบปฏิบัติการคือ Kernal ใน ROM (ไม่ใช่ในดิสก์) มีเส้นรีเซ็ต(จริงๆ เรส ) ที่เชื่อมต่อกับพินที่ 6502 µP และกับชื่อพินเดียวกันในเรือรบพิเศษทุกลำ เช่น CIA 1, CIA 2 และ VIC II ในขั้นตอนการรีเซ็ต เนื่องจากบรรทัดนี้ รีจิสเตอร์ทั้งหมดใน µP และในชิปพิเศษจะถูกรีเซ็ตเป็น 0 (ทำให้เป็นศูนย์สำหรับแต่ละบิต) ถัดไป โดยฮาร์ดแวร์ไมโครโปรเซสเซอร์ ตัวชี้สแต็กและการลงทะเบียนสถานะโปรเซสเซอร์จะได้รับค่าเริ่มต้นในไมโครโปรเซสเซอร์ ตัวนับโปรแกรมจะได้รับค่า (ที่อยู่) ในตำแหน่ง $FFFC และ $FFFD โปรดจำไว้ว่าตัวนับโปรแกรมเก็บที่อยู่ของคำสั่งถัดไป เนื้อหา (ที่อยู่) ที่จัดขึ้นที่นี่มีไว้สำหรับรูทีนย่อยที่เริ่มต้นการเริ่มต้นซอฟต์แวร์ ทุกสิ่งทุกอย่างทำโดยฮาร์ดแวร์ไมโครโปรเซสเซอร์ หน่วยความจำทั้งหมดไม่ได้สัมผัสในระยะนี้ ขั้นต่อไปของการเริ่มต้นจึงเริ่มต้นขึ้น

การเริ่มต้นทำได้โดยบางรูทีนใน ROM OS การเริ่มต้นหมายถึงการให้ค่าเริ่มต้นหรือค่าเริ่มต้นแก่รีจิสเตอร์บางตัวในชิปพิเศษ การเริ่มต้นเริ่มต้นด้วยการให้ค่าเริ่มต้นหรือค่าเริ่มต้นแก่รีจิสเตอร์บางตัวในชิปพิเศษ IRQ เช่น ต้องเริ่มออกทุกๆ 1/60 วินาที ดังนั้นตัวจับเวลาที่สอดคล้องกันใน CIA #1 จะต้องตั้งค่าเป็นค่าเริ่มต้น

จากนั้น Kernal จะทำการทดสอบ RAM โดยจะทดสอบแต่ละตำแหน่งโดยการส่งไบต์ไปยังตำแหน่งนั้นและอ่านกลับ หากมีความแตกต่างอย่างน้อยตำแหน่งนั้นก็แย่ Kernal ยังระบุส่วนบนของหน่วยความจำและด้านล่างของหน่วยความจำ และตั้งค่าพอยน์เตอร์ที่สอดคล้องกันในหน้าที่ 2 หากด้านบนของหน่วยความจำคือ $DFFF ระบบจะใส่ $FF ไว้ที่ตำแหน่ง $0283 และ $DF จะถูกวางไว้ในตำแหน่ง $0284 ไบต์ ทั้ง $0283 และ $0284 มีป้าย HIRAM หากด้านล่างสุดของหน่วยความจำคือ $0800 ค่า $00 จะถูกใส่ในตำแหน่ง $0281 และ $08 จะถูกใส่ในตำแหน่ง $0282 ทั้ง $0281 และ $0282 มีป้าย LORAM การทดสอบ RAM เริ่มต้นที่ 0300 เหรียญสหรัฐฯ ไปจนถึงระดับบนสุดของหน่วยความจำ (RAM)

สุดท้าย เวกเตอร์อินพุต/เอาท์พุต (พอยน์เตอร์) จะถูกตั้งค่าเป็นค่าเริ่มต้น การทดสอบ RAM เริ่มต้นที่ 0300 เหรียญสหรัฐฯ ไปจนถึงระดับบนสุดของหน่วยความจำ (RAM) ซึ่งหมายความว่าเพจ 0, เพจ 1 และเพจ 2 ได้รับการเตรียมใช้งานแล้ว โดยเฉพาะหน้า 0 มีพอยน์เตอร์ OS ROM จำนวนมาก และหน้า 2 มีพอยน์เตอร์พื้นฐานจำนวนมาก พอยน์เตอร์เหล่านี้เรียกว่าตัวแปร โปรดจำไว้ว่าหน้า 1 คือสแต็ก พอยน์เตอร์ถูกเรียกว่าตัวแปรเนื่องจากมีชื่อ (ป้ายกำกับ) ในขั้นตอนนี้ หน่วยความจำหน้าจอจะถูกล้างสำหรับหน้าจอ (จอภาพ) นี่หมายถึงการส่งรหัส $20 สำหรับพื้นที่ (ซึ่งบังเอิญเหมือนกับ ASCII $20) ไปยังตำแหน่งหน้าจอ RAM 1,000 ตำแหน่ง สุดท้าย Kernal เริ่มล่าม BASIC เพื่อแสดงพรอมต์คำสั่ง BASIC ซึ่งพร้อมอยู่ที่ด้านบนของจอภาพ (หน้าจอ)

5.17 ปัญหา

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

  1. เขียนโค้ดภาษาแอสเซมบลีที่ทำให้บิตทั้งหมดของ CIA #2 พอร์ต A เป็นเอาต์พุต และ CIA #2 พอร์ต B เป็นอินพุต
  2. เขียนรหัสภาษาแอสเซมบลี 6502 ที่รอแป้นคีย์บอร์ดจนกว่าจะกด
  3. เขียนโปรแกรมภาษาแอสเซมบลี 6502 ที่ส่งอักขระ 'E' ไปที่หน้าจอ Commodore-64
  4. เขียนโปรแกรมภาษาแอสเซมบลี 6502 ที่รับอักขระจากแป้นพิมพ์และส่งไปที่หน้าจอ Commodore-64 โดยไม่สนใจรหัสคีย์และเวลา
  5. เขียนโปรแกรมภาษาแอสเซมบลี 6502 ที่ได้รับไบต์จากดิสเก็ตต์ Commodore-64
  6. เขียนโปรแกรมภาษาแอสเซมบลี 6502 ที่จะบันทึกไฟล์ลงในดิสเก็ตต์ Commodore-64
  7. เขียนโปรแกรมภาษาแอสเซมบลี 6502 ที่โหลดไฟล์โปรแกรมจากดิสเก็ตต์ Commodore-64 และเริ่มต้นใช้งาน
  8. เขียนโปรแกรมภาษาแอสเซมบลี 6502 ที่ส่งไบต์ 'E' (ASCII) ไปยังโมเด็มซึ่งเชื่อมต่อกับพอร์ตที่รองรับ RS-232 ของผู้ใช้ของ Commodore-64
  9. อธิบายวิธีการนับและกำหนดเวลาในคอมพิวเตอร์ Commodore-64
  10. อธิบายว่ายูนิตระบบ Commodore-64 สามารถระบุแหล่งที่มาของคำขอขัดจังหวะทันทีที่แตกต่างกัน 10 แหล่ง รวมถึงคำขอขัดจังหวะที่ไม่สามารถปกปิดได้
  11. อธิบายว่าโปรแกรมพื้นหลังสามารถทำงานด้วยโปรแกรมเบื้องหน้าในคอมพิวเตอร์ Commodore-64 ได้อย่างไร
  12. อธิบายโดยย่อว่าโปรแกรมภาษาแอสเซมบลีสามารถรวบรวมเป็นแอปพลิเคชันเดียวสำหรับคอมพิวเตอร์ Commodore-64 ได้อย่างไร
  13. อธิบายขั้นตอนการบู๊ตสำหรับคอมพิวเตอร์ Commodore-64 โดยย่อ