บทที่ 4: บทช่วยสอนภาษาชุดไมโครโปรเซสเซอร์ 6502

Bth Thi 4 Bth Chwy Sxn Phas A Chud Mikhor Porsessexr 6502



บทที่ 4: บทช่วยสอนภาษาชุดไมโครโปรเซสเซอร์ 6502

4.1 บทนำ

ไมโครโปรเซสเซอร์ 6502 เปิดตัวในปี พ.ศ. 2518 มันถูกใช้เป็นไมโครโปรเซสเซอร์สำหรับคอมพิวเตอร์ส่วนบุคคลบางรุ่นเช่น Apple II, Commodore 64 และ BBC Micro







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



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



คอมพิวเตอร์ที่มีชื่อเสียงในอดีตมีชื่อว่า Commodore_64 6502 เป็นไมโครโปรเซสเซอร์ในตระกูล 6500 คอมพิวเตอร์ commodore_64 ใช้ไมโครโปรเซสเซอร์ 6510 ไมโครโปรเซสเซอร์ 6510 มีค่าเท่ากับ 6500 µP ชุดคำสั่งของ 6502 µP เป็นคำสั่งเกือบทั้งหมดของ 6510 µP ความรู้ในบทนี้และบทถัดไปจะขึ้นอยู่กับคอมพิวเตอร์ commodore_64 ความรู้นี้ใช้เป็นฐานในการอธิบายสถาปัตยกรรมคอมพิวเตอร์สมัยใหม่และระบบปฏิบัติการสมัยใหม่ในหลักสูตรอาชีพออนไลน์ส่วนนี้





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

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



บล็อกไดอะแกรมของมาเธอร์บอร์ด Commodore 64
แผนภาพบล็อกของมาเธอร์บอร์ด Commodore 64 คือ:


รูปที่ 4.1 แผนผังบล็อกของหน่วยระบบ Commodore_64

ลองนึกภาพไมโครโปรเซสเซอร์ 6510 เป็นไมโครโปรเซสเซอร์ 6502 หน่วยความจำทั้งหมดเป็นชุดไบต์ (8 บิตต่อไบต์) มีหน่วยความจำเข้าถึงโดยสุ่ม (อ่าน/เขียน) ซึ่งสามารถเขียนหรือลบไบต์ได้ เมื่อปิดเครื่องคอมพิวเตอร์ ข้อมูลทั้งหมดใน Random-access Memory (RAM) จะถูกลบ นอกจากนี้ยังมีหน่วยความจำแบบอ่านอย่างเดียว (ROM) เมื่อปิดเครื่องคอมพิวเตอร์ ข้อมูลใน ROM จะยังคงอยู่ (ไม่ถูกลบ)

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

มีบัสสามตัว (กลุ่มของตัวนำไฟฟ้าที่มีขนาดเล็กมาก) ในแผนภาพ แต่ละสายสามารถถ่ายโอนบิต 1 หรือบิต 0 บัสข้อมูลสำหรับการถ่ายโอนไบต์แปดบิตในแต่ละครั้ง (หนึ่งพัลส์นาฬิกา) ไปยัง RAM และพอร์ตอินพุต/เอาท์พุต (อุปกรณ์อินพุต/เอาท์พุต) เป็นแบบสองทิศทาง บัสข้อมูลมีความกว้างแปดบิต

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

มีรถบัสควบคุม ตัวนำบางตัวของบัสควบคุมจะถ่ายโอนหนึ่งบิตจากไมโครโปรเซสเซอร์ไปยังส่วนประกอบอื่นๆ บรรทัดควบคุมสองสามบรรทัดจะนำบิตจากพอร์ตอินพุต/เอาท์พุต (IO) ไปยังไมโครโปรเซสเซอร์

หน่วยความจำคอมพิวเตอร์
RAM และ ROM ถือเป็นชุดหน่วยความจำชุดเดียว แอสเซมบลีนี้แสดงเป็นแผนภาพดังนี้ โดยที่เลขฐานสิบหกมีคำนำหน้า “$”:


รูปที่ 4.11 เค้าโครงหน่วยความจำสำหรับคอมพิวเตอร์ Commodore 64

RAM อยู่ที่ 0000 16 ถึง DFFF 16 ซึ่งเขียนเป็นตั้งแต่ $0000 ถึง $DFFF ในภาษาแอสเซมบลี 6502 µP เลขฐานสิบหกจะขึ้นต้นด้วย “$” และไม่ต้องต่อท้าย (ตัวห้อย) ด้วย 16 หรือ H หรือฐานสิบหก ข้อมูลใดๆ ใน RAM ดับลงเมื่อปิดคอมพิวเตอร์ ROM เริ่มต้นที่ $E000 ถึง $FFFF มีรูทีนย่อยที่ไม่ดับเมื่อปิดคอมพิวเตอร์ รูทีนย่อยเหล่านี้เป็นรูทีนที่ใช้กันทั่วไปซึ่งช่วยในการเขียนโปรแกรม โปรแกรมผู้ใช้เรียกพวกเขา (ดูบทถัดไป)

พื้นที่ (ไบต์) ตั้งแต่ $0200 ถึง $D000 มีไว้สำหรับโปรแกรมผู้ใช้ ช่องว่างตั้งแต่ $D000 ถึง $DFFF ใช้สำหรับข้อมูลที่เกี่ยวข้องโดยตรงกับอุปกรณ์ต่อพ่วง (อุปกรณ์อินพุต/เอาต์พุต) นี่เป็นส่วนหนึ่งของระบบปฏิบัติการ ดังนั้น ระบบปฏิบัติการของคอมพิวเตอร์ Commodore-64 จึงแบ่งออกเป็นสองส่วนหลัก: ส่วนใน ROM ที่ไม่เคยดับ และส่วนตั้งแต่ $D000 ถึง $DFFF ที่จะดับลงเมื่อปิดเครื่อง ข้อมูล IO (อินพุต/เอาท์พุต) นี้จะต้องโหลดจากดิสก์ทุกครั้งที่เปิดคอมพิวเตอร์ ปัจจุบันข้อมูลดังกล่าวเรียกว่าไดรเวอร์อุปกรณ์ต่อพ่วง อุปกรณ์ต่อพ่วงเริ่มต้นจากพอร์ตอุปกรณ์อินพุต/เอาท์พุตผ่านการเชื่อมต่อบนเมนบอร์ดไปยังพอร์ตที่ระบุได้บนพื้นผิวแนวตั้งของคอมพิวเตอร์ที่จอภาพ แป้นพิมพ์ ฯลฯ เชื่อมต่ออยู่และเข้ากับอุปกรณ์ต่อพ่วง (จอภาพ แป้นพิมพ์ ฯลฯ .)

หน่วยความจำประกอบด้วย 2 16 = ตำแหน่ง 65,536 ไบต์ ในรูปแบบเลขฐานสิบหก ได้แก่ 10,000 16 = 10,000 ชม = 10,000 ฐานสิบหก = ที่ตั้ง 10,000 ดอลลาร์ ในการคำนวณ การนับเลขฐานสอง ฐานสิบ ฐานสิบหก ฯลฯ เริ่มจาก 0 ไม่ใช่ 1 ดังนั้น ตำแหน่งแรกจึงเป็นเลขตำแหน่ง 0000000000000000 2 = 0 10 = 0000 16 = 0,000 ดอลลาร์ ในภาษาแอสเซมบลี 6502 µP การระบุตำแหน่งที่อยู่จะขึ้นต้นด้วย $ และไม่มีส่วนต่อท้ายหรือตัวห้อย ตำแหน่งสุดท้ายคือหมายเลขตำแหน่ง 1111111111111111 2 = 65,535 10 = FFFF 16 = $FFFF และไม่ใช่ 10000000000000000 2 หรือ 65,536 10 หรือ 10,000 16 หรือ 10,000 ดอลลาร์ 10000000000000000 2 , 65,536 10 , 10,000 16 หรือ $10,000 ให้จำนวนตำแหน่งไบต์ทั้งหมด

ที่นี่ 2 16 = 65,536 = 64 x 1,024 = 64 x 2 10 = 64 กิโลไบต์ (กิโลไบต์) ส่วนต่อท้ายของ 64 ในชื่อ Commodore-64 หมายถึงหน่วยความจำทั้งหมด 64KB (RAM และ ROM) ไบต์คือ 8 บิต และ 8 บิตจะไปอยู่ในตำแหน่งหนึ่งไบต์ในหน่วยความจำ

หน่วยความจำขนาด 64 Kbytes แบ่งออกเป็นหน้าต่างๆ แต่ละหน้ามี 0100 16 = 256 10 ตำแหน่งไบต์ ตัวแรก 256 10 = 0100 แรก 16 ตำแหน่งคือหน้า 0 หน้าที่สองคือหน้า 1 หน้าที่สามคือหน้า 2 และอื่นๆ

เพื่อระบุตำแหน่ง 65,536 แห่ง จำเป็นต้องมี 16 บิตสำหรับแต่ละตำแหน่ง (ที่อยู่) ดังนั้นแอดเดรสบัสจากไมโครโปรเซสเซอร์ไปยังหน่วยความจำประกอบด้วย 16 บรรทัด หนึ่งบรรทัดต่อหนึ่งบิต บิตเป็น 1 หรือ 0

รีจิสเตอร์ 6502 µP
รีจิสเตอร์เปรียบเสมือนเซลล์ไบต์สำหรับตำแหน่งหน่วยความจำไบต์ 6502 µP มีรีจิสเตอร์ 6 ตัว: รีจิสเตอร์ 8 บิต 5 ตัว และรีจิสเตอร์ 16 บิต 1 ตัว รีจิสเตอร์ 16 บิตเรียกว่า Program Counter ซึ่งย่อว่า PC มันเก็บที่อยู่หน่วยความจำสำหรับคำสั่งถัดไป โปรแกรมภาษาแอสเซมบลีประกอบด้วยคำสั่งที่อยู่ในหน่วยความจำ จำเป็นต้องใช้บิตที่แตกต่างกันสิบหก (16) บิตเพื่อระบุตำแหน่งไบต์เฉพาะในหน่วยความจำ ที่พัลส์นาฬิกาเฉพาะ บิตเหล่านี้จะถูกส่งไปยังบรรทัดที่อยู่ 16 บิตของแอดเดรสบัสเพื่ออ่านคำสั่ง รีจิสเตอร์ทั้งหมดสำหรับ 6502 µP มีดังต่อไปนี้:


รูปที่ 4.12 6502 µP รีจิสเตอร์

Program Counter หรือ PC สามารถเห็นได้เป็นรีจิสเตอร์ 16 บิตในแผนภาพ แปดบิตที่มีนัยสำคัญต่ำกว่าจะมีป้ายกำกับเป็น PCL สำหรับ Program Counter Low แปดบิตที่มีนัยสำคัญสูงกว่าจะมีป้ายกำกับเป็น PCH สำหรับ Program Counter High คำสั่งในหน่วยความจำสำหรับ Commodore-64 สามารถประกอบด้วยหนึ่ง สอง หรือสามไบต์ 16 บิตในพีซีชี้ไปที่คำสั่งถัดไปที่จะดำเนินการในหน่วยความจำ ในบรรดาวงจรต่างๆ ในไมโครโปรเซสเซอร์ มี 2 วงจรที่เรียกว่า หน่วยลอจิกเลขคณิต และ ตัวถอดรหัสคำสั่ง หากคำสั่งปัจจุบันที่กำลังประมวลผลใน µP (ไมโครโปรเซสเซอร์) มีความยาวหนึ่งไบต์ วงจรทั้งสองนี้จะเพิ่ม PC สำหรับคำสั่งถัดไปขึ้น 1 หน่วย หากคำสั่งปัจจุบันที่กำลังประมวลผลใน µP มีความยาวสองไบต์ ซึ่งหมายความว่าคำสั่งนั้นใช้พื้นที่สองไบต์ติดต่อกันในหน่วยความจำ วงจรทั้งสองนี้จะเพิ่ม PC สำหรับคำสั่งถัดไปอีก 2 หน่วย หากคำสั่งปัจจุบันที่กำลังประมวลผลใน µP มีความยาวสามไบต์ หมายความว่าคำสั่งนั้นใช้พื้นที่สามไบต์ติดต่อกันในหน่วยความจำ วงจรทั้งสองนี้จะเพิ่ม PC สำหรับคำสั่งถัดไปอีก 3 หน่วย

แอคคิวมูเลเตอร์ “A” คือรีจิสเตอร์วัตถุประสงค์ทั่วไปแปดบิตที่เก็บผลลัพธ์ของการดำเนินการทางคณิตศาสตร์และตรรกะส่วนใหญ่

รีจิสเตอร์ 'X' และ 'Y' ใช้เพื่อนับขั้นตอนของโปรแกรม การนับในการเขียนโปรแกรมเริ่มต้นจาก 0 ดังนั้นจึงเรียกว่าเป็นการลงทะเบียนดัชนี พวกเขามีวัตถุประสงค์อื่นบางประการ

แม้ว่าการลงทะเบียน Stack Pointer แต่ 'S' มี 9 บิตซึ่งถือเป็นการลงทะเบียนแปดบิต เนื้อหาชี้ไปที่ตำแหน่งไบต์ในหน้า 1 ของ Random Access Memory (RAM) หน้าที่ 1 เริ่มต้นจากไบต์ $0100 (256 10 ) เป็นไบต์ $01FF (511 10 ). เมื่อโปรแกรมกำลังทำงานอยู่ โปรแกรมจะย้ายจากคำสั่งหนึ่งไปยังคำสั่งถัดไปในหน่วยความจำ อย่างไรก็ตาม นี่ไม่ใช่กรณีเสมอไป มีหลายครั้งที่มันจะข้ามจากพื้นที่หน่วยความจำหนึ่งไปยังอีกพื้นที่หน่วยความจำหนึ่งเพื่อดำเนินการตามคำแนะนำที่นั่นต่อไปอย่างต่อเนื่อง หน้าที่ 1 ใน RAM ถูกใช้เป็นสแต็ก สแต็กเป็นพื้นที่หน่วยความจำ RAM ขนาดใหญ่ที่มีที่อยู่ถัดไปสำหรับความต่อเนื่องของโค้ดจากจุดที่มีการข้าม รหัสที่มีคำแนะนำในการกระโดดไม่อยู่ในสแต็ก พวกเขาอยู่ที่อื่นในความทรงจำ อย่างไรก็ตาม หลังจากดำเนินการคำสั่งข้ามไปยัง ที่อยู่ต่อเนื่อง (ไม่ใช่ส่วนของโค้ด) จะอยู่ในสแต็ก พวกเขาถูกผลักไปที่นั่นอันเป็นผลมาจากคำสั่งการกระโดดหรือสาขา

รีจิสเตอร์สถานะตัวประมวลผลแปดบิตของ P เป็นรีจิสเตอร์ชนิดพิเศษ แต่ละบิตไม่เกี่ยวข้องหรือเชื่อมต่อถึงกัน แต่ละบิตเรียกว่าแฟล็กและมีการชื่นชมอย่างเป็นอิสระจากส่วนอื่นๆ ความหมายของธงมีดังต่อไปนี้เมื่อมีความจำเป็น

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

หน้าหน่วยความจำในรูปแบบไบนารี เลขฐานสิบหก และทศนิยม
ตารางต่อไปนี้แสดงจุดเริ่มต้นของเพจหน่วยความจำในรูปแบบไบนารี เลขฐานสิบหก และทศนิยม:

แต่ละหน้ามี 1,0000,0000 2 จำนวนไบต์ซึ่งเท่ากับ 100 ชม จำนวนไบต์ซึ่งเท่ากับ 256 10 จำนวนไบต์ ในแผนภาพหน่วยความจำก่อนหน้านี้ หน้าต่างๆ จะถูกระบุว่าเพิ่มขึ้นจากหน้า 0 และไม่ลดลงตามที่ระบุไว้ในตาราง

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

ส่วนที่เหลือของบทนี้จะอธิบายภาษาแอสเซมบลี 6502 µP โดยใช้ข้อมูลก่อนหน้านี้ทั้งหมด เพื่อให้เข้าใจภาษาได้อย่างรวดเร็ว ผู้อ่านต้องบวกและลบฐานสิบหกแทนฐานสิบ จริงๆ แล้วควรจะเป็นเลขฐานสอง แต่การคำนวณเลขฐานสองนั้นยุ่งยาก โปรดจำไว้ว่าเมื่อบวกเลขสองตัวในฐานสอง การยกยังคงเป็น 1 เช่นเดียวกับเลขฐานสิบ แต่เมื่อลบเลขสองตัวในฐานสอง การยืมจะเป็น 2 ไม่ใช่ 10 เหมือนเลขฐานสิบ เมื่อบวกเลขสองตัวในฐานสิบหก ตัวยกยังคงเป็น 1 เหมือนเลขฐานสิบ แต่เมื่อลบตัวเลขสองตัวในฐานสิบหก การยืมจะเป็นสิบหก และไม่ใช่สิบเหมือนในฐานสิบ

4.2 คำแนะนำในการถ่ายโอนข้อมูล

พิจารณาตารางคำแนะนำการถ่ายโอนข้อมูลภาษาแอสเซมบลีต่อไปนี้สำหรับ 6502 µP:

เมื่อไบต์ (8 บิต) ถูกคัดลอกจากตำแหน่งไบต์หน่วยความจำไปยัง Accumulator Register, X Register หรือ Y Register ที่กำลังโหลด เมื่อไบต์ถูกคัดลอกจากรีจิสเตอร์เหล่านี้ไปยังตำแหน่งไบต์หน่วยความจำ ที่กำลังถ่ายโอน เมื่อไบต์ถูกคัดลอกจากรีจิสเตอร์หนึ่งไปยังอีกรีจิสเตอร์หนึ่ง ไบต์นั้นยังคงถ่ายโอนอยู่ ในคอลัมน์ที่สองของตาราง ลูกศรจะแสดงทิศทางของการคัดลอกในหน่วยไบต์ คอลัมน์ที่เหลือในสี่คอลัมน์แสดงโหมดการกำหนดที่อยู่ที่แตกต่างกัน

รายการในคอลัมน์โหมดการกำหนดแอดเดรสคือรหัสไบต์จริงสำหรับส่วนช่วยจำที่สอดคล้องกันของคำสั่งในรูปแบบเลขฐานสิบหก ตัวอย่างเช่น AE คือโค้ดไบต์จริงสำหรับ LDX ซึ่งจะโหลดไบต์จากหน่วยความจำไปยัง X register ในโหมดการกำหนดแอดเดรสแบบสัมบูรณ์เช่น AE 16 = 10101110 2 . ดังนั้น บิตสำหรับ LDX ในตำแหน่งไบต์หน่วยความจำคือ 10101110

โปรดสังเกตว่าสำหรับส่วนช่วยจำ LDX ของคำสั่ง จะมีไบต์ที่เป็นไปได้สามไบต์ ได้แก่ A2, AE และ A6 และแต่ละไบต์สำหรับโหมดการกำหนดแอดเดรสเฉพาะ เมื่อไบต์ที่โหลดลงใน X register จะไม่ถูกคัดลอกจากตำแหน่งไบต์ของหน่วยความจำ ค่าจะต้องพิมพ์ด้วย (หลังจากนั้น) ตัวช่วยจำ LDX ในคำสั่งเป็นเลขฐานสิบหกหรือทศนิยม ในบทนี้ ค่าดังกล่าวจะพิมพ์เป็นเลขฐานสิบหก นี่เป็นการระบุที่อยู่ทันที ดังนั้นไบต์จริงในหน่วยความจำที่ใช้แทน LDX คือ A2 16 = 10100010 2 และไม่ใช่เออี 16 ซึ่งเท่ากับ 10101110 2 .

ในตาราง ไบต์ทั้งหมดภายใต้ส่วนหัวของโหมดการกำหนดแอดเดรสเรียกว่ารหัสการทำงานซึ่งเรียกโดยย่อว่า opcodes สามารถมีได้มากกว่าหนึ่ง opcode สำหรับหนึ่งช่วยในการจำ ขึ้นอยู่กับโหมดการกำหนดแอดเดรส

บันทึก: คำว่า 'โหลด' ในหน่วยระบบคอมพิวเตอร์อาจมีสองความหมาย: อาจหมายถึงการโหลดไฟล์จากดิสก์ไปยังหน่วยความจำของคอมพิวเตอร์หรืออาจหมายถึงการถ่ายโอนไบต์จากตำแหน่งไบต์หน่วยความจำไปยังการลงทะเบียนไมโครโปรเซสเซอร์ .

มีโหมดการระบุแอดเดรสมากกว่าโหมดสี่โหมดในตารางสำหรับ 6502 µP

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

หน่วยความจำ M และตัวสะสม A

หน่วยความจำในการสะสม

ที่อยู่ทันที
คำสั่งต่อไปนี้จะจัดเก็บหมายเลข FF 16 = 255 10 เข้าสู่ตัวสะสม:

แอลดีเอ #$FF

“$” ไม่ได้ใช้เพียงเพื่อระบุที่อยู่หน่วยความจำเท่านั้น โดยทั่วไปจะใช้เพื่อระบุว่าตัวเลขถัดไปที่ตามมาเป็นเลขฐานสิบหก ในกรณีนี้ $FF ไม่ใช่ที่อยู่ของตำแหน่งไบต์หน่วยความจำใดๆ มันคือหมายเลข 255 10 เป็นเลขฐานสิบหก เลขฐาน 16 หรือตัวห้อยอื่นๆ ที่เทียบเท่ากันจะต้องไม่เขียนในคำสั่งภาษาแอสเซมบลี เครื่องหมาย “#” บ่งชี้ว่าสิ่งใดก็ตามที่ตามมาถัดไปคือค่าที่จะใส่ลงในทะเบียนตัวสะสม ค่ายังสามารถเขียนเป็นฐานสิบได้ แต่ยังไม่ได้เขียนในบทนี้ “#” หมายถึงที่อยู่ทันที

ตัวช่วยในการจำมีความคล้ายคลึงกับวลีภาษาอังกฤษที่สอดคล้องกัน “LDA #$FF” หมายถึงโหลดหมายเลข 255 10 เข้าไปในตัวสะสม A เนื่องจากนี่เป็นการแก้ไขทันทีจากตารางก่อนหน้า LDA จึงเป็น A9 ไม่ใช่ AD หรือ A5 A9 ในไบนารี่คือ 101010001 ดังนั้น หาก A9 สำหรับ LDA อยู่ในแอดเดรส $0200 ในหน่วยความจำ $FF จะอยู่ในแอดเดรส $0301 = 0300 + 1 #$FF เป็นตัวถูกดำเนินการสำหรับตัวช่วยจำ LDA อย่างแน่นอน

ที่อยู่ที่แน่นอน
หากค่าของ $FF อยู่ในตำแหน่ง $0333 ในหน่วยความจำ คำสั่งก่อนหน้านี้คือ:

แอลดีเอ 0333 ดอลลาร์

สังเกตว่าไม่มี # ในกรณีนี้ การไม่มี # หมายความว่าสิ่งที่ตามมาคือที่อยู่หน่วยความจำ ไม่ใช่มูลค่าของดอกเบี้ย (ไม่ใช่ค่าที่จะใส่ลงในตัวสะสม) ดังนั้น opcode สำหรับ LDA ในครั้งนี้คือ AD ไม่ใช่ A9 หรือ A5 ตัวถูกดำเนินการสำหรับ LDA ในที่นี้คือที่อยู่ $0333 ไม่ใช่ค่า $FF $FF อยู่ในตำแหน่ง $0333 ซึ่งค่อนข้างไกล คำสั่ง “LDA $0333” ใช้ตำแหน่งสามตำแหน่งติดต่อกันในหน่วยความจำ ไม่ใช่สองตำแหน่ง ดังภาพประกอบก่อนหน้านี้ “AD” สำหรับ LDA อยู่ในตำแหน่ง $0200 ไบต์ล่างของ 0333 ซึ่งก็คือ 33 อยู่ในตำแหน่ง $0301 ไบต์ที่สูงกว่าของ $0333 ซึ่งก็คือ 03 อยู่ในตำแหน่ง $0302 นี่คือ endianness เล็กน้อยซึ่งใช้โดยภาษาแอสเซมบลี 6502 ภาษาแอสเซมบลีของไมโครโปรเซสเซอร์ที่แตกต่างกันจะแตกต่างกัน

นี่คือตัวอย่างหนึ่งของการระบุที่อยู่แบบสัมบูรณ์ $0333 คือที่อยู่ของตำแหน่งที่มี $FF คำสั่งประกอบด้วยสามไบต์ติดต่อกันและไม่รวม $FF หรือตำแหน่งไบต์จริง

การกำหนดที่อยู่เป็นศูนย์หน้า

สมมติว่าค่า $FF อยู่ในตำแหน่งหน่วยความจำ $0050 ในเพจศูนย์ ตำแหน่งไบต์สำหรับหน้าศูนย์เริ่มต้นที่ $0000 และสิ้นสุดที่ $00FF เหล่านี้คือ 256 10 สถานที่ทั้งหมด หน่วยความจำ Commodore-64 แต่ละหน้ามี 256 หน้า 10 ยาว. โปรดสังเกตว่าไบต์ที่สูงกว่าจะเป็นศูนย์สำหรับตำแหน่งที่เป็นไปได้ทั้งหมดในพื้นที่หน้าศูนย์ในหน่วยความจำ โหมดการกำหนดแอดเดรสเป็นศูนย์หน้าจะเหมือนกับโหมดการกำหนดแอดเดรสแบบสัมบูรณ์ แต่ไม่ได้พิมพ์ไบต์ที่สูงกว่า 00 ลงในคำสั่ง ดังนั้น เพื่อโหลด $FF จากตำแหน่ง $0050 ลงในตัวสะสม คำสั่งโหมดการกำหนดที่อยู่เป็นศูนย์หน้าคือ:

LDA $50

โดยที่ LDA เป็น A5 ไม่ใช่ A9 หรือ AD, A5 16 = 10100101 2 . โปรดจำไว้ว่าแต่ละไบต์ในหน่วยความจำมีขนาด 8 เซลล์ และแต่ละเซลล์จะมีขนาดเล็กน้อย คำสั่งที่นี่ประกอบด้วยสองไบต์ติดต่อกัน A5 สำหรับ LDA อยู่ในตำแหน่งหน่วยความจำ $0200 และที่อยู่ $50 โดยไม่มีไบต์ที่สูงกว่าคือ 00 จะอยู่ในตำแหน่ง $0301 การไม่มี 00 ซึ่งอาจต้องใช้ไบต์ในหน่วยความจำทั้งหมด 64K จะช่วยประหยัดพื้นที่หน่วยความจำ

สะสมไปยังหน่วยความจำ

ที่อยู่ที่แน่นอน
คำสั่งต่อไปนี้จะคัดลอกค่าไบต์ ไม่ว่าจะเป็นอะไรก็ตาม จากตัวสะสมไปยังตำแหน่งหน่วยความจำที่ $1444:

พวกเขาคือ $1,444

กล่าวกันว่าเป็นการถ่ายโอนจากตัวสะสมไปยังหน่วยความจำ มันโหลดไม่ได้ กำลังโหลดอยู่ตรงกันข้าม ไบต์ opcode สำหรับ STA คือ 8D 16 = 10001101 2 . คำสั่งนี้ประกอบด้วยไบต์สามไบต์ติดต่อกันในหน่วยความจำ 8D 16 อยู่ในตำแหน่ง $0200 44 16 ของที่อยู่ $1444 อยู่ในตำแหน่ง $0201 และ 14 16 อยู่ในตำแหน่ง $0202 – มีความเอนเอียงเล็กน้อย ไบต์จริงที่ถูกคัดลอกไม่ได้เป็นส่วนหนึ่งของคำสั่ง 8D และไม่ใช่ 85 สำหรับการกำหนดแอดเดรสเป็นศูนย์ (ในตาราง) ใช้สำหรับ STA ที่นี่

การกำหนดที่อยู่หน้าเป็นศูนย์
คำสั่งต่อไปนี้จะคัดลอกค่าไบต์ ไม่ว่าจะเป็นอะไรก็ตาม จากตัวสะสมไปยังตำแหน่งหน่วยความจำ $0050 ในหน้าศูนย์:

ค่าสเตตัส $0050

ไบต์ opcode สำหรับ STA ที่นี่คือ 85 16 = 10000101 2 . คำสั่งนี้ประกอบด้วยไบต์สองไบต์ติดต่อกันในหน่วยความจำ 85 16 อยู่ในตำแหน่ง $0200 50 16 ของที่อยู่ $0050 อยู่ในตำแหน่ง $0201 ปัญหาของ endianness ไม่ได้เกิดขึ้นที่นี่เนื่องจากที่อยู่มีเพียงไบต์เดียวซึ่งเป็นไบต์ล่าง ไบต์จริงที่ถูกคัดลอกไม่ได้เป็นส่วนหนึ่งของคำสั่ง ที่นี่ใช้ 85 และไม่ใช่ 8D สำหรับการกำหนดที่อยู่แบบหน้าศูนย์สำหรับ STA

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

LDX, STX, LDY และ STY ช่วยในการจำ
LDX และ STX นั้นคล้ายคลึงกับ LDA และ STA ตามลำดับ แต่ที่นี่ จะใช้การลงทะเบียน X ไม่ใช่การลงทะเบียน A (ตัวสะสม) LDY และ STY คล้ายคลึงกับ LDA และ STA ตามลำดับ แต่ที่นี่ จะใช้การลงทะเบียน Y ไม่ใช่การลงทะเบียน A โปรดดูตารางที่ 4.21 สำหรับแต่ละ opcode ในเลขฐานสิบหกที่สอดคล้องกับตัวช่วยจำเฉพาะและโหมดการกำหนดแอดเดรสเฉพาะ

การลงทะเบียนเพื่อลงทะเบียนการโอน
คำสั่งสองชุดก่อนหน้านี้ในตาราง 4.21 เกี่ยวข้องกับการคัดลอก (ถ่ายโอน) หน่วยความจำ/ไมโครโปรเซสเซอร์-รีจิสเตอร์ และการลงทะเบียน/รีจิสเตอร์ (ถ่ายโอน) คำสั่ง TAX, TXA, TAY, TYA, TSX และ TXS ทำการคัดลอก (ถ่ายโอน) จากรีจิสเตอร์ในไมโครโปรเซสเซอร์ไปยังรีจิสเตอร์อื่นของไมโครโปรเซสเซอร์ตัวเดียวกัน

ในการคัดลอกไบต์จาก A ถึง X คำสั่งคือ:

ภาษี

หากต้องการคัดลอกไบต์จาก X ไปยัง A คำสั่งคือ:

เท็กซัส

ในการคัดลอกไบต์จาก A ถึง Y คำสั่งคือ:

มือ

ในการคัดลอกไบต์จาก Y ไปยัง A คำสั่งคือ:

ทีวายเอ

สำหรับคอมพิวเตอร์ Commodore 64 สแต็กจะอยู่หน้า 1 หลังหน้า 0 ในหน่วยความจำ เช่นเดียวกับหน้าอื่นๆ ทั้งหมดประกอบด้วย 25610 10 ตำแหน่งไบต์ ตั้งแต่ $0100 ถึง $01FF โดยปกติโปรแกรมจะดำเนินการจากคำสั่งหนึ่งไปยังคำสั่งถัดไปที่ต่อเนื่องกันในหน่วยความจำ ในบางครั้งจะมีการข้ามไปยังส่วนรหัสหน่วยความจำอื่น (ชุดคำสั่ง) พื้นที่สแต็กในหน่วยความจำ (RAM) มีที่อยู่คำสั่งถัดไปจากตำแหน่งที่การข้าม (หรือสาขา) ค้างไว้เพื่อให้โปรแกรมทำงานต่อไป

ตัวชี้สแต็ก 'S' คือรีจิสเตอร์ 9 บิตใน 6502 µP บิตแรก (ซ้ายสุด) จะเป็น 1 เสมอ ที่อยู่ตำแหน่งไบต์ทั้งหมดในหน้าที่หนึ่งเริ่มต้นด้วย 1 ตามด้วย 8 บิตที่แตกต่างกันสำหรับ 256 10 สถานที่ ตัวชี้สแต็กมีที่อยู่ของตำแหน่งในหน้าที่ 1 ซึ่งมีที่อยู่ของคำสั่งถัดไปที่โปรแกรมจะต้องส่งคืนและดำเนินการต่อหลังจากดำเนินการส่วนของโค้ดปัจจุบัน (ข้ามไป) เนื่องจากบิตแรกของที่อยู่ทั้งหมดของสแต็ก (หน้าหนึ่ง) เริ่มต้นด้วย 1 รีจิสเตอร์ตัวชี้สแต็กจะต้องเก็บบิตที่เหลือเพียงแปดบิตเท่านั้น อย่างไรก็ตาม บิตแรกซึ่งเป็นบิตซ้ายสุด (บิตที่เก้านับจากด้านขวา) จะเป็น 1 เสมอ

หากต้องการคัดลอกไบต์จาก S ถึง X คำสั่งคือ:

ทีเอสเอ็กซ์

หากต้องการคัดลอกไบต์จาก X ถึง S คำสั่งคือ:

TXT

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

บันทึก: ไม่มีการถ่ายโอน X ถึง Y หรือ Y ถึง X (การคัดลอก)

4.3 การดำเนินการทางคณิตศาสตร์

วงจรซึ่งเป็นหน่วยลอจิกเลขคณิตใน 6502 µP สามารถเพิ่มตัวเลขแปดบิตได้ครั้งละสองตัวเท่านั้น มันไม่ลบ ไม่คูณ ก็ไม่หาร ตารางต่อไปนี้แสดง opcodes และโหมดการกำหนดแอดเดรสสำหรับการดำเนินการทางคณิตศาสตร์:

บันทึก: ตัวช่วยจำทั้งหมดสำหรับการดำเนินการทางคณิตศาสตร์และการดำเนินการประเภทอื่นๆ (เช่น ตัวช่วยจำทั้งหมด 6502 ตัว) ใช้โค้ดการดำเนินการ (op) หนึ่งไบต์ หากมีโหมดการกำหนดแอดเดรสมากกว่าหนึ่งโหมดสำหรับตัวช่วยจำ จะมี opcodes ที่แตกต่างกันสำหรับตัวช่วยจำเดียวกัน: หนึ่งโหมดต่อโหมดการกำหนดแอดเดรส C, D และ V ในตารางคือแฟล็กของการลงทะเบียนสถานะ ความหมายของพวกเขาจะได้รับในภายหลังเมื่อมีความจำเป็นเกิดขึ้น

การเพิ่มหมายเลขที่ไม่ได้ลงนาม
ด้วย 6502 µP ตัวเลขที่ลงนามจึงเป็นตัวเลขเสริมของทั้งสอง ตัวเลขที่ไม่ได้ลงนามคือตัวเลขบวกธรรมดาที่เริ่มต้นจากศูนย์ ดังนั้น สำหรับไบต์แปดบิต จำนวนที่น้อยที่สุดที่ไม่ได้ลงชื่อคือ 00000000 2 = 0 10 = 00 16 และหมายเลขที่ไม่ได้ลงชื่อที่ใหญ่ที่สุดคือ 11111111 2 = 255 10 = เอฟเอฟ 16 . สำหรับตัวเลขที่ไม่ได้ลงนามสองตัว การบวกคือ:

เอ+เอ็ม+ซี→เอ

นั่นหมายความว่าเนื้อหา 8 บิตของแอคคิวมูเลเตอร์จะถูกเพิ่มโดยหน่วยตรรกะทางคณิตศาสตร์เป็นไบต์ (8 บิต) จากหน่วยความจำ หลังจากการบวก A และ M แล้ว การยกไปยังบิตที่เก้าจะไปที่เซลล์แฟล็กพกพาในรีจิสเตอร์สถานะ Carry bit ก่อนหน้าใดๆ จากการเพิ่มครั้งก่อนซึ่งยังอยู่ในเซลล์แฟล็กพกพาในรีจิสเตอร์สถานะจะถูกเพิ่มเข้ากับผลรวมของ A และ M ด้วยเช่นกัน ทำให้ A+M+C→A ผลลัพธ์จะถูกนำกลับเข้าสู่ตัวสะสม

หากดอกเบี้ยเพิ่มคือ:

เอ + เอ็ม

และไม่จำเป็นต้องเพิ่มการพกพาใด ๆ ก่อนหน้านี้ จะต้องเคลียร์แฟล็กการพกพาซึ่งมีค่าเป็น 0 เพื่อให้การบวกคือ:

A+M+0→A เช่นเดียวกับ A+M→A

บันทึก: หากเพิ่ม M เข้ากับ A และมีค่ายก 1 เกิดขึ้นเนื่องจากผลลัพธ์มากกว่า 255 10 = 11111111 2 = เอฟเอฟ 16 นี่คือกระเป๋าพกพาใหม่ การพกพา 1 ใหม่นี้จะถูกส่งไปยังเซลล์แฟล็กพกพาโดยอัตโนมัติ ในกรณีที่คู่แปดบิตถัดไปจำเป็นที่จะรวมเข้าด้วยกัน (A + M อีกอัน)

รหัสเพื่อเพิ่มแปดบิตที่ไม่ได้ลงนามสองตัว
00111111 2 +00010101 2 ก็เหมือนกับ 3F 16 +15 16 ซึ่งก็เหมือนกับปี 63 10 +21 10 . ผลลัพธ์คือ 010101002 2 ซึ่งก็เหมือนกับปี 54 16 และ 84 10 . ผลลัพธ์จะต้องไม่เกินจำนวนสูงสุดสำหรับแปดบิตซึ่งก็คือ 255 10 = 11111111 2 = เอฟเอฟ 16 . ดังนั้นจึงไม่มีการพกพาผลลัพธ์ของ 1 กล่าวอีกนัยหนึ่งการพกพาผลลัพธ์คือ 0 ก่อนที่จะบวกไม่มีการพกพาก่อนหน้าของ 1 กล่าวอีกนัยหนึ่งการพกพาครั้งก่อนคือ 0 รหัสที่จะทำบวกนี้ เป็นไปได้:

ซีแอลซี
แอลดีเอ #$3F
ADC #$15

บันทึก: ขณะพิมพ์ภาษาแอสเซมบลี ปุ่ม 'Enter' ของแป้นพิมพ์จะถูกกดที่ส่วนท้ายของแต่ละคำสั่ง มีคำแนะนำสามประการในรหัสนี้ คำสั่งแรก (CLC) จะล้างแฟล็กพกพาในกรณีที่การเพิ่มก่อนหน้านี้มี 1 CLC สามารถทำได้ในโหมดการกำหนดแอดเดรสโดยนัยเท่านั้น ตัวช่วยจำสำหรับโหมดการกำหนดที่อยู่โดยนัยไม่มีตัวถูกดำเนินการ นี่เป็นการล้างเซลล์พกพาของการลงทะเบียนสถานะของ P การล้างหมายถึงการให้บิตเป็น 0 ให้กับเซลล์แฟล็กพกพา คำแนะนำสองคำสั่งถัดไปในโค้ดใช้โหมดการระบุที่อยู่ทันที เมื่อมีการระบุที่อยู่ทันที จะมีตัวถูกดำเนินการเพียงตัวเดียวสำหรับตัวช่วยจำซึ่งเป็นตัวเลข (และไม่มีทั้งหน่วยความจำหรือที่อยู่ลงทะเบียน) ดังนั้นตัวเลขจึงต้องนำหน้าด้วย “#” “$” หมายความว่าตัวเลขที่ตามมาเป็นเลขฐานสิบหก

คำสั่งที่สองโหลดหมายเลข 3F 16 เข้าไปในตัวสะสม สำหรับคำสั่งที่สาม วงจรหน่วยลอจิกทางคณิตศาสตร์ของ µP จะนำค่ายกก่อนหน้า (เคลียร์) ของ 0 (บังคับเป็น 0) ของเซลล์แฟล็กยกของของรีจิสเตอร์สถานะและเพิ่มเป็น 15 16 รวมถึงค่าที่มีอยู่แล้วใน 3F 16 สะสมและนำผลลัพธ์ที่สมบูรณ์กลับเข้าไปในตัวสะสม ในกรณีนี้ จะมีผลลัพธ์เป็น 0 ALU (Arithmetic Logic Unit) จะส่ง (ใส่) 0 ไปยังเซลล์แฟล็กพกพาของรีจิสเตอร์สถานะ การลงทะเบียนสถานะโปรเซสเซอร์และการลงทะเบียนสถานะมีความหมายเหมือนกัน หากผลการพกพาเท่ากับ 1 ALU จะส่ง 1 ไปยังธงพกพาของทะเบียนสถานะ

โค้ดก่อนหน้าสามบรรทัดจะต้องอยู่ในหน่วยความจำก่อนที่จะดำเนินการ opcode 1816 สำหรับ CLC (การกำหนดที่อยู่โดยนัย) อยู่ในตำแหน่งไบต์ 0200 ดอลลาร์ ออปโค้ด A9 16 สำหรับ LDA (ที่อยู่ทันที) อยู่ในตำแหน่งไบต์ $0201 หมายเลข 3F 10 อยู่ในตำแหน่ง $0202 ไบต์ รหัสประจำตัว 69 16 สำหรับ LDA (ที่อยู่ทันที) อยู่ในตำแหน่งไบต์ $0203 หมายเลข 15 10 อยู่ในตำแหน่งไบต์ $0204

บันทึก: LDA เป็นคำสั่งถ่ายโอน (โหลด) ไม่ใช่คำสั่งทางคณิตศาสตร์ (ช่วยในการจำ)

รหัสเพื่อเพิ่มสองบิตสิบหกที่ไม่ได้ลงนาม
รีจิสเตอร์ทั้งหมดใน 6502 µP นั้นเป็นรีจิสเตอร์แปดบิต ยกเว้น PC (ตัวนับโปรแกรม) ที่เป็น 16 บิต แม้แต่การลงทะเบียนสถานะก็กว้าง 8 บิต แม้ว่าแปดบิตจะทำงานร่วมกันไม่ได้ก็ตาม ในส่วนนี้ จะพิจารณาการเพิ่มบิตที่ไม่ได้ลงนามจำนวน 16 บิตจำนวน 2 บิต โดยมีการยกจากคู่แรกของแปดบิตไปยังคู่ที่สองจำนวนแปดบิต การดำเนินการที่น่าสนใจที่นี่คือการดำเนินการจากตำแหน่งบิตที่แปดไปยังตำแหน่งบิตที่เก้า

ให้ตัวเลขเป็น 0010101010111111 2 = 2ABF16 16 = 10,943 10 และ 0010101010010101 2 = 2A95 16 = 10,901 10 . ผลรวมคือ 0101010101010100 2 = 5554 16 = 21,844 10 .

การบวกตัวเลขที่ไม่ได้ลงนามสองตัวนี้เข้ากับฐานสองจะเป็นดังนี้:

ตารางต่อไปนี้แสดงการบวกแบบเดียวกันโดยยก 1 จากบิตที่แปดไปยังตำแหน่งบิตที่เก้า โดยเริ่มจากด้านขวา:

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

สำหรับการบวกไบต์สองคู่โดยสมบูรณ์ การเพิ่มครั้งแรกคือ:

เอ + เอ็ม + 0 -> ก

นอกจากนี้ที่สองคือ:

เอ + เอ็ม + 1 -> ก

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

ซีแอลซี
แอลดีเอ 0213 ดอลลาร์
ADC 0215 ดอลลาร์
; ไม่มีการหักล้างเนื่องจากจำเป็นต้องมีค่าแฟล็กพกพา
ค่าส่วนกลาง $0217
แอลดีเอ 0214 ดอลลาร์
ADC 0216 ดอลลาร์
ค่าส่วนกลาง $0218

โปรดทราบว่าในภาษาแอสเซมบลี 6502 อัฒภาคจะเริ่มต้นความคิดเห็น ซึ่งหมายความว่าในการทำงานของโปรแกรม อัฒภาคและทุกสิ่งที่อยู่ทางด้านขวาจะถูกละเว้น โปรแกรมที่เขียนไว้ก่อนหน้านี้อยู่ในไฟล์ข้อความจะถูกบันทึกด้วยชื่อที่โปรแกรมเมอร์เลือกและมีนามสกุล “.asm” โปรแกรมก่อนหน้านี้ไม่ใช่โปรแกรมที่แน่นอนที่ไปที่หน่วยความจำเพื่อดำเนินการ โปรแกรมที่เกี่ยวข้องในหน่วยความจำเรียกว่าโปรแกรมที่แปลโดยแทนที่ตัวช่วยจำด้วย opcodes (ไบต์) ความคิดเห็นใดๆ จะยังคงอยู่ในไฟล์ข้อความภาษาแอสเซมบลี และจะถูกลบออกก่อนที่โปรแกรมที่แปลจะเข้าถึงหน่วยความจำ จริงๆ แล้ว ปัจจุบันมีไฟล์สองไฟล์ที่ถูกบันทึกไว้ในดิสก์: ไฟล์ “.asm” และไฟล์ “.exe” ไฟล์ “.asm” เป็นไฟล์ในภาพประกอบก่อนหน้านี้ ไฟล์ “.exe” คือไฟล์ “.asm” ที่มีการถอดความคิดเห็นทั้งหมดออก และตัวช่วยจำทั้งหมดจะถูกแทนที่ด้วย opcodes เมื่อเปิดในโปรแกรมแก้ไขข้อความ ไฟล์ “.exe” จะไม่สามารถจดจำได้ ตามจุดประสงค์ของบทนี้ เว้นแต่จะระบุไว้เป็นอย่างอื่น ไฟล์ “.exe” จะถูกคัดลอกไปยังหน่วยความจำโดยเริ่มจากตำแหน่ง $0200 นี่คือความหมายอื่นของการโหลด

ตัวเลข 16 บิตสองตัวที่จะเพิ่มจะใช้พื้นที่สี่ไบต์ในหน่วยความจำสำหรับการกำหนดแอดเดรสแบบสัมบูรณ์: สองไบต์ต่อหมายเลข (หน่วยความจำคือลำดับของไบต์) ด้วยการระบุแอดเดรสแบบสัมบูรณ์ ตัวถูกดำเนินการของ opcode จะอยู่ในหน่วยความจำ ผลลัพธ์สรุปมีความกว้าง 2 ไบต์ และต้องใส่ไว้ในหน่วยความจำด้วย จะได้ทั้งหมด 6 อัน 10 = 6 16 ไบต์สำหรับอินพุตและเอาต์พุต อินพุตไม่ได้มาจากแป้นพิมพ์และเอาต์พุตไม่ได้มาจากจอภาพหรือเครื่องพิมพ์ อินพุตอยู่ในหน่วยความจำ (RAM) และเอาต์พุต (ผลรวม) จะกลับไปที่หน่วยความจำ (RAM) ในสถานการณ์นี้

ก่อนดำเนินการโปรแกรม เวอร์ชันที่แปลจะต้องอยู่ในหน่วยความจำก่อน เมื่อดูโค๊ดโปรแกรมก่อนหน้าจะเห็นว่าคำสั่งที่ไม่มีคอมเมนต์ประกอบขึ้นเป็น 19 10 = 13 16 ไบต์ ดังนั้น โปรแกรมจะใช้ตำแหน่งไบต์จาก $0200 ในหน่วยความจำไปเป็น $0200 + $13 – $1 = ตำแหน่งไบต์ $0212 (เริ่มจาก $0200 และไม่ใช่ $0201 ซึ่งหมายถึง – $1) การเพิ่ม 6 ไบต์สำหรับหมายเลขอินพุตและเอาต์พุตทำให้โปรแกรมทั้งหมดสิ้นสุดที่ $0212 + $6 = $0218 ความยาวรวมของโปรแกรมคือ 19 16 = 25 10 .

ไบต์ล่างของ augend ควรอยู่ในที่อยู่ $0213 และไบต์ที่สูงกว่าของ augend เดียวกันควรอยู่ในที่อยู่ $0214 – endianness เล็กน้อย ในทำนองเดียวกัน ไบต์ล่างของ addend ควรอยู่ในที่อยู่ $0215 และไบต์ที่สูงกว่าของ addend เดียวกันควรอยู่ในที่อยู่ $0216 – endianness เล็กน้อย ไบต์ล่างของผลลัพธ์ (ผลรวม) ควรอยู่ในที่อยู่ $0217 และไบต์ที่สูงกว่าของผลลัพธ์เดียวกันควรอยู่ในที่อยู่ $0218 – endianness เล็กน้อย

รหัสประจำตัว 18 16 สำหรับ CLC (การกำหนดแอดเดรสโดยนัย) อยู่ในตำแหน่งไบต์ที่ $0200 opcode สำหรับ “LDA $0213” เช่น AD 16 สำหรับ LDA (การกำหนดที่อยู่แบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ที่ $0201 ไบต์ล่างของ auend ซึ่งก็คือ 10111111 อยู่ในตำแหน่งไบต์หน่วยความจำที่ $0213 โปรดจำไว้ว่าแต่ละ opcode ใช้พื้นที่หนึ่งไบต์ ที่อยู่ “$0213” ของ “LDA $0213” อยู่ในตำแหน่งไบต์ที่ $0202 และ $0203 คำสั่ง “LDA $0213” จะโหลดไบต์ล่างของ augend ไปยังตัวสะสม

opcode สำหรับ “ADC $0215” เช่น 6D 16 สำหรับ ADC (การกำหนดแอดเดรสแบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ที่ $0204 ไบต์ล่างของส่วนเสริมซึ่งก็คือ 10010101 อยู่ในตำแหน่งไบต์ที่ $0215 ที่อยู่ “$0215” ของ “ADC $0215” อยู่ในตำแหน่งไบต์ที่ $0205 และ $0206 คำสั่ง “ADC $0215” จะเพิ่มไบต์ล่างของการบวกเข้ากับไบต์ล่างของ augend ซึ่งอยู่ในตัวสะสมอยู่แล้ว ผลลัพธ์จะถูกวางกลับเข้าไปในตัวสะสม การพกพาใดๆ หลังจากบิตที่แปดจะถูกส่งไปยังแฟล็กพกพาของการลงทะเบียนสถานะ ต้องไม่ล้างเซลล์แฟล็กพกพาก่อนที่จะเพิ่มไบต์ที่สูงกว่าครั้งที่สอง การพกพานี้จะถูกเพิ่มเข้ากับผลรวมของไบต์ที่สูงกว่าโดยอัตโนมัติ ในความเป็นจริง การพกพาที่เป็น 0 จะถูกเพิ่มเข้ากับผลรวมของไบต์ล่างโดยอัตโนมัติที่จุดเริ่มต้น (เทียบเท่ากับการไม่มีการเพิ่มการพกพา) เนื่องจาก CLC

ความคิดเห็นใช้เวลา 48 ถัดไป 10 = 30 16 ไบต์ อย่างไรก็ตาม สิ่งนี้จะยังคงอยู่ในไฟล์ข้อความ “.asm” เท่านั้น มันไปไม่ถึงความทรงจำ มันถูกลบออกโดยการแปลซึ่งทำโดยแอสเซมเบลอร์ (โปรแกรม)

สำหรับคำสั่งถัดไปซึ่งก็คือ “STA $0217” ซึ่งเป็น opcode ของ STA ซึ่งเป็น 8D 16 (การกำหนดที่อยู่แบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ที่ $0207 ที่อยู่ “$0217” ของ “STA $0217” อยู่ในตำแหน่งหน่วยความจำที่ $0208 และ $0209 คำสั่ง “STA $0217” จะคัดลอกเนื้อหาแปดบิตของตัวสะสมไปยังตำแหน่งหน่วยความจำที่ $0217

ไบต์ที่สูงกว่าของ auend ซึ่งก็คือ 00101010 อยู่ในตำแหน่งหน่วยความจำที่ $0214 และไบต์ที่สูงกว่าของการเพิ่มซึ่งก็คือ 00101010 อยู่ในตำแหน่งไบต์ที่ $02 16 . opcode สำหรับ “LDA $0214” ซึ่งเป็น AD16 สำหรับ LDA (การกำหนดแอดเดรสแบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ที่ $020A ที่อยู่ “$0214” ของ “LDA $0214” อยู่ในตำแหน่งของ $020B และ $020C คำสั่ง “LDA $0214” จะโหลดไบต์ที่สูงกว่าของ augend ไปยังตัวสะสม โดยจะลบสิ่งใดก็ตามที่อยู่ในตัวสะสม

opcode สำหรับ “ADC $0216” ซึ่งเป็น 6D 16 สำหรับ ADC (การกำหนดที่อยู่แบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ที่ $020D ที่อยู่ “$0216” ของ “ADC 0216” อยู่ในตำแหน่งไบต์ที่ $020E และ $020F คำสั่ง “ADC $0216” จะเพิ่มไบต์ที่สูงกว่าของการบวกเข้ากับไบต์ที่สูงกว่าของ augend ซึ่งอยู่ในตัวสะสมอยู่แล้ว ผลลัพธ์จะถูกวางกลับเข้าไปในตัวสะสม หากมีการพกพาเป็น 1 สำหรับการบวกครั้งที่สองนี้ มันจะถูกวางไว้ในช่องพกพาของการลงทะเบียนสถานะโดยอัตโนมัติ แม้ว่าไม่จำเป็นต้องใช้การพกพาเกินบิตที่สิบหก (ซ้าย) สำหรับปัญหานี้ แต่ก็เป็นการดีที่จะตรวจสอบว่าการพกพาเป็น 1 เกิดขึ้นหรือไม่โดยการตรวจสอบว่าแฟล็กการพกพากลายเป็น 1 หรือไม่

สำหรับคำสั่งถัดไปและสุดท้ายซึ่งก็คือ “STA $0218” opcode ของ STA ซึ่งเป็น 8D16 (การกำหนดแอดเดรสแบบสัมบูรณ์) จะอยู่ในตำแหน่งไบต์ที่ $0210 ที่อยู่ “$0218” ของ “STA $0218” อยู่ในตำแหน่งหน่วยความจำที่ $0211 และ $0212 คำสั่ง “STA $0218” จะคัดลอกเนื้อหาแปดบิตของตัวสะสมไปยังตำแหน่งหน่วยความจำที่ $0218 ผลลัพธ์ของการเพิ่มตัวเลขสิบหกบิตสองตัวคือ 0101010101010100 โดยมีไบต์ล่าง 01010100 ในตำแหน่งหน่วยความจำที่ 0217 ดอลลาร์ และไบต์ที่สูงกว่า 01010101 ในตำแหน่งหน่วยความจำที่ 0218 ดอลลาร์ ซึ่งถือว่ามีจุดสิ้นสุดเพียงเล็กน้อย

การลบ
ด้วย 6502 µP ตัวเลขที่ลงนามจึงเป็นตัวเลขเสริมของทั้งสอง หมายเลขเสริมของสองอาจเป็น 8 บิต 16 บิต หรือผลคูณใดๆ ของ 8 บิตก็ได้ ด้วยส่วนเสริมของ two บิตแรกจากซ้ายคือบิตเครื่องหมาย สำหรับจำนวนบวก บิตแรกนี้คือ 0 เพื่อระบุเครื่องหมาย บิตที่เหลือจะสร้างตัวเลขในลักษณะปกติ หากต้องการหาส่วนเติมเต็มของจำนวนลบทั้งสอง ให้กลับบิตทั้งหมดสำหรับจำนวนบวกที่สอดคล้องกัน แล้วบวก 1 เข้ากับผลลัพธ์จากปลายด้านขวา

หากต้องการลบจำนวนบวกหนึ่งจำนวนออกจากจำนวนบวกอีกจำนวนหนึ่ง ค่าลบจะถูกแปลงเป็นจำนวนลบเสริมของสอง จากนั้นค่า minuend และจำนวนลบใหม่จะถูกเพิ่มตามปกติ ดังนั้นการลบแปดบิตจึงกลายเป็น:

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

เมื่อลบตัวเลข 16 บิตสองตัว การลบจะทำสองครั้งเหมือนกับการบวกตัวเลข 16 บิตสองตัว เนื่องจากการลบเป็นรูปแบบของการบวกด้วย 6502 µP เมื่อลบตัวเลข 16 บิตสองตัว ธงดำเนินการจะถูกตั้งค่าเพียงครั้งเดียวสำหรับการลบครั้งแรก สำหรับการลบครั้งที่สอง การตั้งค่าใดๆ ของแฟล็กพกพาจะดำเนินการโดยอัตโนมัติ

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

การลบด้วยจำนวนบวกสิบหกบิต
พิจารณาการลบด้วยตัวเลขต่อไปนี้:

การลบนี้ไม่เกี่ยวข้องกับการเติมเต็มของสอง เนื่องจากการลบใน 6502 µP เสร็จสิ้นในส่วนเติมเต็มของ 2 การลบในฐาน 2 จึงทำได้ดังนี้:

ผลลัพธ์การเสริมของทั้งสองจะเหมือนกับผลลัพธ์ที่ได้จากการลบแบบธรรมดา อย่างไรก็ตาม โปรดทราบว่า 1 ที่ไปยังตำแหน่งบิตที่สิบเจ็ดจากด้านขวาจะถูกละเว้น minuend และ subtrahend แบ่งออกเป็นสองบิตละแปดบิต ส่วนเสริมทั้งสองของ 10010110 ของไบต์ล่างของ subtrahend นั้นถูกกำหนดโดยอิสระจากไบต์ที่สูงกว่าและการดำเนินการใดๆ ส่วนเสริมทั้งสองของ 11101011 ของไบต์ที่สูงกว่าของ subtrahend นั้นถูกกำหนดโดยอิสระจากไบต์ที่ต่ำกว่าและของการพกพาใดๆ

minuend ขนาด 16 บิตอยู่ในส่วนเสริมของ two แล้ว โดยเริ่มจาก 0 จากด้านซ้าย ดังนั้นจึงไม่จำเป็นต้องปรับเป็นบิตใดๆ ด้วย 6502 µP ไบต์ล่างของ minuend ที่ไม่มีการแก้ไขใดๆ จะถูกเพิ่มเข้าไปในไบต์ล่างของส่วนเสริมทั้งสองของ subtrahend ไบต์ล่างของ minuend จะไม่ถูกแปลงเป็นส่วนเติมเต็มของ two เนื่องจากบิตสิบหกบิตของ minuend ทั้งหมดจะต้องอยู่ในส่วนเติมเต็มของ two แล้ว (โดยมี 0 เป็นบิตแรกทางด้านซ้าย) ในการเพิ่มครั้งแรกนี้ มีการบวกค่าพกพาภาคบังคับเป็น 1 เนื่องจากคำสั่ง 1=0 SEC

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

สิ่งต่อไปคือเพียงเขียนโค้ดโครงร่างทั้งหมดดังนี้:

วินาที
แอลดีเอ 0213 ดอลลาร์
SBC 0215 ดอลลาร์
; ไม่มีการหักล้างเนื่องจากจำเป็นต้องใช้ค่าแฟล็กพกพาแบบกลับหัว
ค่าส่วนกลาง $0217
แอลดีเอ 0214 ดอลลาร์
SBC $0216
ค่าส่วนกลาง $0218

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

ก่อนรันโปรแกรม จะต้องอยู่ในหน่วยความจำก่อน เมื่อดูโค้ดโปรแกรมจะเห็นว่าคำสั่งที่ไม่มีความคิดเห็นประกอบขึ้นเป็น 19 10 = 13 16 ไบต์ เนื่องจากโปรแกรมทั้งหมดในบทนี้เริ่มต้นจากตำแหน่งหน่วยความจำ $0200 โปรแกรมจึงนำจากตำแหน่งไบต์ $0200 ในหน่วยความจำไปยังตำแหน่งไบต์ $0200 + $13 – $1 = $0212 (เริ่มต้นจาก $0200 และไม่ใช่ $0201) ช่วงนี้ไม่รวมขอบเขตสำหรับไบต์อินพุตและเอาต์พุต หมายเลขอินพุตสองตัวใช้เวลา 4 ไบต์ และหมายเลขเอาต์พุตหนึ่งตัวใช้เวลา 2 ไบต์ การเพิ่ม 6 ไบต์สำหรับหมายเลขอินพุตและเอาต์พุตทำให้ช่วงของโปรแกรมสิ้นสุดที่ $0212 + $6 = $0218 ความยาวรวมของโปรแกรมคือ 19 16 = 25 10 .

ไบต์ล่างของ minuend ควรอยู่ในที่อยู่ $0213 และไบต์ที่สูงกว่าของ minuend เดียวกันควรอยู่ในที่อยู่ $0214 – endianness เล็กน้อย ในทำนองเดียวกัน ไบต์ล่างของ subtrahend เดียวกันควรอยู่ในที่อยู่ $0215 และไบต์ที่สูงกว่าของ subtrahend เดียวกันควรอยู่ในที่อยู่ $0216 – endianness เล็กน้อย ไบต์ล่างของผลลัพธ์ (ความแตกต่าง) ควรอยู่ในที่อยู่ $0217 และไบต์ที่สูงกว่าของผลลัพธ์เดียวกันควรอยู่ในที่อยู่ $0218 – endianness เล็กน้อย

รหัส opcode ของ 38 16 สำหรับ SEC (ที่อยู่โดยนัย) อยู่ในที่อยู่ $0200 โปรแกรมทั้งหมดในบทนี้จะถือว่าเริ่มต้นที่ตำแหน่งหน่วยความจำที่ 0200 เหรียญสหรัฐฯ ซึ่งจะทำให้โปรแกรมใดๆ ที่อยู่ที่นั่นเป็นโมฆะ เว้นแต่จะระบุไว้เป็นอย่างอื่น opcode สำหรับ “LDA $0213” เช่น AD 16 สำหรับ LDA (การกำหนดแอดเดรสแบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ $0201 ไบต์ล่างของ minuend ซึ่งก็คือ 10111111 อยู่ในตำแหน่งไบต์หน่วยความจำที่ $0213 โปรดจำไว้ว่าแต่ละ opcode ใช้พื้นที่หนึ่งไบต์ ที่อยู่ “$0213” ของ “LDA $0213” อยู่ในตำแหน่งไบต์ที่ $0202 และ $0203 คำสั่ง “LDA $0213” จะโหลดไบต์ล่างของ minuend ไปยังตัวสะสม

opcode สำหรับ “SBC $0215” เช่น ED 16 สำหรับ SBC (การกำหนดแอดเดรสแบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ $0204 ไบต์ล่างของ subtrahend ซึ่งก็คือ 01101010 อยู่ในตำแหน่งไบต์ $0215 ที่อยู่ “$0215” ของ “ADC $0215” อยู่ในตำแหน่งไบต์ที่ $0205 และ $0206 คำสั่ง “SBC $0215” จะลบไบต์ล่างของตัวลบออกจากไบต์ล่างของตัว minuend ที่มีอยู่ในตัวสะสมอยู่แล้ว นี่คือการลบส่วนเติมเต็มของสอง ผลลัพธ์จะถูกวางกลับเข้าไปในตัวสะสม ส่วนเสริม (การผกผัน) ของการพกพาใด ๆ หลังจากบิตที่แปดถูกส่งไปยังแฟล็กพกพาของรีจิสเตอร์สถานะ ต้องไม่เคลียร์แฟล็กพกพานี้ก่อนการลบครั้งที่สองด้วยไบต์ที่สูงกว่า การพกพานี้จะถูกเพิ่มในการลบไบต์ที่สูงกว่าโดยอัตโนมัติ

ความเห็นพาไป 57 ต่อไป 10 = 3916 16 ไบต์ อย่างไรก็ตาม สิ่งนี้จะยังคงอยู่ในไฟล์ข้อความ “.asm” เท่านั้น มันไปไม่ถึงความทรงจำ มันถูกลบออกโดยการแปลซึ่งทำโดยแอสเซมเบลอร์ (โปรแกรม)

สำหรับคำสั่งถัดไปซึ่งก็คือ “STA $0217” opcode ของ STA คือ 8D 16 (การกำหนดที่อยู่แบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ $0207 ที่อยู่ “$0217” ของ “STA $0217” อยู่ในตำแหน่งหน่วยความจำที่ $0208 และ $0209 คำสั่ง “STA $0217” จะคัดลอกเนื้อหาแปดบิตของตัวสะสมไปยังตำแหน่งหน่วยความจำที่ $0217

ไบต์ที่สูงกว่าของ minuend ซึ่งก็คือ 00101010 อยู่ในตำแหน่งหน่วยความจำที่ $0214 และไบต์ที่สูงกว่าของ subtrahend ซึ่งก็คือ 00010101 อยู่ในตำแหน่งไบต์ที่ $0216 opcode สำหรับ “LDA $0214” เช่น AD 16 สำหรับ LDA (การกำหนดแอดเดรสแบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ $020A ที่อยู่ “$0214” ของ “LDA $0214” อยู่ในตำแหน่งของ $020B และ $020C คำสั่ง “LDA $0214” จะโหลดไบต์ที่สูงกว่าของ minuend ไปยังตัวสะสม โดยจะลบสิ่งใดก็ตามที่อยู่ในตัวสะสม

opcode สำหรับ “SBC $0216” เช่น ED 16 สำหรับ SBC (การกำหนดแอดเดรสแบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ $020D ที่อยู่ “$0216” ของ “SBC $0216” อยู่ในตำแหน่งไบต์ที่ $020E และ $020F คำสั่ง “SBC $0216” จะลบไบต์ที่สูงกว่าของ subtrahend ออกจากไบต์ที่สูงกว่าของ minuend (ส่วนเสริมของสองตัว) ซึ่งอยู่ในตัวสะสมอยู่แล้ว ผลลัพธ์จะถูกวางกลับเข้าไปในตัวสะสม หากมีการยก 1 สำหรับการลบครั้งที่สอง ส่วนเติมเต็มจะถูกวางไว้ในเซลล์พกพาของการลงทะเบียนสถานะโดยอัตโนมัติ แม้ว่าการพกพาเกินบิตที่สิบหก (ซ้าย) จะไม่จำเป็นสำหรับปัญหานี้ แต่ก็เป็นการดีที่จะตรวจสอบว่าการพกพาส่วนเสริมเกิดขึ้นหรือไม่โดยการตรวจสอบแฟล็กการพกพา

สำหรับคำสั่งถัดไปและสุดท้ายซึ่งก็คือ “STA $0218” ซึ่งเป็น opcode ของ STA เช่น 8D 16 (การกำหนดที่อยู่แบบสัมบูรณ์) อยู่ในตำแหน่งไบต์ $0210 ที่อยู่ “$0218” ของ “STA $0218” อยู่ในตำแหน่งหน่วยความจำที่ $0211 และ $0212 คำสั่ง “STA $0218” จะคัดลอกเนื้อหาแปดบิตของตัวสะสมไปยังตำแหน่งหน่วยความจำที่ $0218 ผลลัพธ์ของการลบด้วยตัวเลข 16 บิตสองตัวคือ 0001010101010101 โดยมีไบต์ล่าง 01010101 ในตำแหน่งหน่วยความจำที่ 0217 ดอลลาร์ และไบต์ที่สูงกว่า 00010101 ในตำแหน่งหน่วยความจำ 0218 ดอลลาร์ ซึ่งถือว่ามีจุดสิ้นสุดเพียงเล็กน้อย

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

4.4 การดำเนินการเชิงตรรกะ

ใน 6502 µP ตัวช่วยจำสำหรับ OR คือ ORA และตัวช่วยจำสำหรับ OR พิเศษคือ EOR โปรดสังเกตว่าการดำเนินการเชิงตรรกะไม่มีการกำหนดที่อยู่โดยนัย ที่อยู่โดยนัยไม่มีตัวถูกดำเนินการ ตัวดำเนินการเชิงตรรกะแต่ละตัวต้องใช้ตัวถูกดำเนินการสองตัว อันแรกอยู่ในตัวสะสมและอันที่สองอยู่ในหน่วยความจำหรือในคำสั่ง ผลลัพธ์ (8 บิต) กลับเข้าสู่ตัวสะสม ตัวแรกในตัวสะสมจะถูกใส่ไว้ที่นั่นโดยคำสั่งทันทีหรือคัดลอกมาจากหน่วยความจำด้วยการกำหนดที่อยู่แบบสัมบูรณ์ ในส่วนนี้ จะใช้เฉพาะการกำหนดที่อยู่เป็นศูนย์หน้าเป็นภาพประกอบเท่านั้น ตัวดำเนินการเชิงตรรกะเหล่านี้คือตัวดำเนินการ Bitwise ทั้งหมด

และ
ตารางต่อไปนี้แสดง Bitwise AND ในรูปแบบไบนารี เลขฐานสิบหก และทศนิยม:

โปรแกรมทั้งหมดในบทนี้ควรเริ่มต้นที่ตำแหน่งไบต์หน่วยความจำที่ 0200 ดอลลาร์ อย่างไรก็ตาม โปรแกรมในส่วนนี้อยู่ในเพจศูนย์ โดยมีจุดประสงค์เพื่อแสดงตัวอย่างการใช้เพจศูนย์โดยไม่มีไบต์ที่สูงกว่า 00000000 2 . ANDing ก่อนหน้านี้อาจมีการเข้ารหัสดังนี้:

LDA #$9A ; ไม่ใช่จากหน่วยความจำ - ระบุที่อยู่ทันที
และ #$ซีดี ; ไม่ใช่จากหน่วยความจำ - ระบุที่อยู่ทันที
ค่าส่วนกลาง $30 ; เก็บ $88 ไว้ที่ $0030 แบบอิงศูนย์

หรือ
ตารางต่อไปนี้แสดง Bitwise OR ในรูปแบบไบนารี เลขฐานสิบหก และทศนิยม:

LDA #$9A ; ไม่ใช่จากหน่วยความจำ - ระบุที่อยู่ทันที
ORA #$ซีดี ; ไม่ใช่จากหน่วยความจำ - ระบุที่อยู่ทันที
ค่าส่วนกลาง $30 ; เก็บ $CF ไว้ที่ $0030 ที่เป็นศูนย์

ฟรี
ตารางต่อไปนี้แสดง Bitwise XOR ในรูปแบบไบนารี เลขฐานสิบหก และทศนิยม:

LDA #$9A ; ไม่ใช่จากหน่วยความจำ - ระบุที่อยู่ทันที
EOR #$ซีดี ; ไม่ใช่จากหน่วยความจำ - ระบุที่อยู่ทันที
ค่าส่วนกลาง $30 ; เก็บ $57 ไว้ที่ $0030 แบบอิงศูนย์

4.5 การดำเนินการกะและหมุนเวียน

ตัวช่วยจำและ opcodes สำหรับตัวดำเนินการ shift และ Rotate คือ:

ASL: เลื่อนตำแหน่งของตัวสะสมหรือหน่วยความจำไปทางซ้ายหนึ่งบิต โดยใส่ 0 ในเซลล์ขวาสุดที่ว่าง

LSR: เลื่อนตำแหน่งของตัวสะสมหรือหน่วยความจำไปทางขวาหนึ่งบิต โดยใส่ 0 ในเซลล์ซ้ายสุดที่ว่าง
ROL: หมุนไปทางซ้ายเล็กน้อยของตำแหน่งสะสมหรือหน่วยความจำ โดยแทรกบิตที่หลุดออกมาทางด้านซ้ายลงในเซลล์ขวาสุดที่ว่างอยู่
ROR: หมุนตำแหน่งสะสมหรือหน่วยความจำไปทางขวาหนึ่งบิต โดยแทรกบิตที่หลุดออกมาทางด้านขวาลงในเซลล์ซ้ายสุดที่ว่าง

หากต้องการเปลี่ยนหรือหมุนด้วยแอคคิวมูเลเตอร์ คำสั่งจะเป็นดังนี้:

แอลเอสอาร์ เอ

ซึ่งใช้โหมดการกำหนดแอดเดรสอื่นที่เรียกว่าโหมดการกำหนดแอดเดรสแบบสะสม

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

ROR $2BCD

โดยที่ 2BCD คือตำแหน่งหน่วยความจำ

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

4.6 โหมดการกำหนดที่อยู่แบบสัมพันธ์

ไมโครโปรเซสเซอร์จะเพิ่ม Program Counter (PC) เสมอ (1, 2 หรือ 3 หน่วย) เพื่อชี้ไปยังคำสั่งถัดไปที่จะดำเนินการ 6502 µP มีคำสั่งที่มีตัวช่วยในการจำ BVS ซึ่งหมายถึง Branch on Overflow Set พีซีประกอบด้วยสองไบต์ คำสั่งนี้ทำให้พีซีมีที่อยู่หน่วยความจำที่แตกต่างกันสำหรับคำสั่งถัดไปที่จะดำเนินการโดยไม่เป็นผลจากการเพิ่มขึ้นตามปกติ ซึ่งทำได้โดยการเพิ่มหรือลบค่าที่เรียกว่าออฟเซ็ตในเนื้อหาของพีซี จากนั้นพีซีจะชี้ไปยังตำแหน่งหน่วยความจำอื่น (แยกสาขา) เพื่อให้คอมพิวเตอร์ดำเนินการจากที่นั่นต่อไป ออฟเซ็ตเป็นจำนวนเต็มตั้งแต่ -128 10 ถึง +127 10 (ส่วนเสริมของสอง) ดังนั้นการชดเชยสามารถทำให้การข้ามไปข้างหน้าในหน่วยความจำได้ ถ้ามันเป็นบวกหรือล้าหลังในความทรงจำหรือถ้ามันเป็นลบ

คำสั่ง BVS รับตัวถูกดำเนินการเพียงตัวเดียวเท่านั้นซึ่งเป็นออฟเซ็ต BVS ใช้การกำหนดที่อยู่แบบสัมพันธ์ พิจารณาคำแนะนำต่อไปนี้:

บีวีเอส $7F

ในฐานสอง 7F ชม คือ 01111111 2 = 127 10 . สมมติว่าเนื้อหาในพีซีสำหรับคำสั่งถัดไปคือ 0300 ดอลลาร์ คำสั่ง BVS ทำให้ $7F (จำนวนบวกที่อยู่ในส่วนเสริมของสองอยู่แล้ว) เพิ่มเป็น $0300 เพื่อให้ $037F ดังนั้น แทนที่จะเป็นคำสั่งถัดไปที่จะดำเนินการที่ตำแหน่งหน่วยความจำที่ $0300 คำสั่งนั้นจะอยู่ที่ตำแหน่งหน่วยความจำที่ $037F (ต่างกันประมาณครึ่งหน้า)

มีคำสั่งสาขาอื่น ๆ แต่ BVS เป็นคำสั่งที่ดีมากที่จะใช้เพื่อแสดงที่อยู่แบบสัมพันธ์ ข้อตกลงที่อยู่แบบสัมพันธ์กับคำแนะนำของสาขา

4.7 ที่อยู่ที่จัดทำดัชนีและที่อยู่ทางอ้อมแยกกัน

โหมดการกำหนดแอดเดรสเหล่านี้ช่วยให้ 6502 µP สามารถจัดการกับข้อมูลจำนวนมหาศาลในช่วงเวลาสั้น ๆ โดยมีจำนวนคำสั่งลดลง มีตำแหน่ง 64KB สำหรับหน่วยความจำ Comodore-64 ทั้งหมด ดังนั้น ในการเข้าถึงตำแหน่งไบต์ใดๆ ขนาด 16 บิต จำเป็นต้องมีไบต์ 2 ไบต์ ข้อยกเว้นเพียงอย่างเดียวสำหรับความต้องการสองไบต์คือสำหรับเพจศูนย์ โดยละเว้นไบต์ที่สูงกว่า $00 เพื่อประหยัดพื้นที่ที่คำสั่งในหน่วยความจำใช้ ด้วยโหมดการกำหนดแอดเดรสที่ไม่เป็นศูนย์หน้า ส่วนใหญ่จะระบุทั้งไบต์สูงและไบต์ล่างของที่อยู่หน่วยความจำ 16 บิต

ที่อยู่ดัชนีพื้นฐาน

ที่อยู่ดัชนีสัมบูรณ์
โปรดจำไว้ว่าการลงทะเบียน X หรือ Y เรียกว่าการลงทะเบียนดัชนี พิจารณาคำแนะนำต่อไปนี้:

LDA $C453,X

สมมุติว่ามีค่าเท่ากับ 6 ชม อยู่ในทะเบียน X โปรดทราบว่าไม่ได้พิมพ์ 6 ที่ใดก็ได้ในคำสั่ง คำสั่งนี้จะเพิ่มค่า 6H เป็น C453 ชม ซึ่งเป็นส่วนหนึ่งของคำสั่งพิมพ์ในไฟล์ข้อความที่ยังต้องประกอบ – C453 ชม + 6 ชม = C459 ชม . LDA หมายถึงโหลดไบต์ไปยังตัวสะสม ไบต์ที่จะโหลดลงในตัวสะสมนั้นมาจากที่อยู่ $C459 $C459 ซึ่งเป็นผลรวมของ $C453 ที่พิมพ์ด้วยคำสั่งและ 6 ชม ที่พบในการลงทะเบียน X จะกลายเป็นที่อยู่ที่มีประสิทธิภาพซึ่งเป็นที่มาของไบต์ที่จะโหลดเข้าสู่ตัวสะสม ถ้า 6 ชม อยู่ในการลงทะเบียน Y ส่วน Y ถูกพิมพ์แทน X ในคำสั่ง

ในคำสั่งคำสั่งที่พิมพ์ $C453 เรียกว่าที่อยู่ฐานและเลข 6 ชม ในการลงทะเบียน X หรือ Y เรียกว่าส่วนการนับหรือดัชนีสำหรับที่อยู่ที่มีประสิทธิภาพ ที่อยู่ฐานสามารถอ้างถึงที่อยู่ไบต์ใด ๆ ในหน่วยความจำและ 256 ถัดไป 10 สามารถเข้าถึงที่อยู่ได้ โดยสมมติว่าดัชนีเริ่มต้น (หรือจำนวน) ในการลงทะเบียน X หรือ Y คือ 0 โปรดจำไว้ว่าหนึ่งไบต์สามารถให้ช่วงต่อเนื่องได้ถึง 256 10 ตัวเลข (เช่น 00000000 2 ถึง 11111111 2 ).

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

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

โปรดจำไว้ว่าตัวช่วยจำเช่น LDA สามารถมี opcode ได้มากกว่าหนึ่งรหัส (ไบต์ต่างกัน) opcode สำหรับคำสั่งที่ใช้ X register นั้นแตกต่างจาก opcode ที่ใช้ Y register แอสเซมเบลอร์รู้ว่าควรใช้ opcode ใดตามคำสั่งที่พิมพ์ opcode หนึ่งไบต์สำหรับ “LDA $C453,X” แตกต่างจาก opcode หนึ่งไบต์สำหรับ “LDA $C453,Y” อันที่จริงแล้ว opcode สำหรับ LDA ใน “LDA $C453,X” คือ BD และ opcode สำหรับ LDA ใน “LDA $C453,9” คือ BD

หาก opcode สำหรับ LDA อยู่ในตำแหน่ง $0200 ไบต์ จากนั้น ที่อยู่ 16 บิตของ $C453 จะอยู่ถัดจากตำแหน่งไบต์ในหน่วยความจำซึ่งก็คือ $0201 และ $0202 ไบต์ opcode เฉพาะระบุว่าเป็นการลงทะเบียน X หรือการลงทะเบียน Y ที่เกี่ยวข้อง ดังนั้นคำสั่งภาษาที่ประกอบขึ้นซึ่งก็คือ “LDA $C453,X” หรือ “LDA $C453,Y” จะใช้พื้นที่สามไบต์ติดต่อกันในหน่วยความจำ ไม่ใช่สี่หรือห้าไบต์

ที่อยู่ที่จัดทำดัชนีหน้าเป็นศูนย์
การกำหนดที่อยู่ดัชนีหน้าศูนย์นั้นเหมือนกับการกำหนดที่อยู่ดัชนีแบบสัมบูรณ์ซึ่งอธิบายไว้ก่อนหน้านี้ แต่ไบต์เป้าหมายจะต้องอยู่ที่หน้าศูนย์เท่านั้น (ตั้งแต่ $0000 ถึง $00FF) ตอนนี้ เมื่อต้องจัดการกับหน้าศูนย์ ไบต์ที่สูงกว่าจะเป็น 00 เสมอ ชม สำหรับตำแหน่งหน่วยความจำมักจะหลีกเลี่ยง ดังนั้นจึงมักกล่าวถึงว่าหน้าศูนย์เริ่มต้นจาก $00 ถึง FF ดังนั้นคำสั่งก่อนหน้าของ “LDA $C453,X” คือ:

LDA $53.X

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

เมื่อค่าที่พิมพ์ในคำสั่งถูกเพิ่มเข้ากับค่าในการลงทะเบียนดัชนี ผลรวมไม่ควรให้ผลลัพธ์เหนือศูนย์หน้า (FF ชม ). ดังนั้นจึงไม่ใช่เรื่องแปลกที่จะมีคำสั่งเช่น “LDA $FF, X” และค่าเช่น FF ชม ในการลงทะเบียนดัชนีเพราะ FF ชม + เอฟเอฟ ชม = 200 ชม ซึ่งเป็นตำแหน่งไบต์แรกของ ($0200) ของหน้าที่ 2 (หน้าที่สาม) ในหน่วยความจำ ซึ่งอยู่ห่างจากหน้า 0 มาก ดังนั้น ด้วยการกำหนดแอดเดรสที่จัดทำดัชนีเป็นศูนย์หน้า ที่อยู่ที่มีผลจะต้องอยู่ในหน้าศูนย์

ที่อยู่ทางอ้อม

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

เจเอ็มพี 8765 ดอลลาร์

โปรแกรมที่รันในหน่วยความจำกระโดดจากที่อยู่ใดก็ตามที่เข้าถึงได้เป็น 8,765 ดอลลาร์ ตัวช่วยในการจำของ JMP มี opcode สามตัว ได้แก่ 4C, 6C และ 7C opcode สำหรับการกำหนดที่อยู่แบบสัมบูรณ์นี้คือ 4C opcode สำหรับการกำหนดที่อยู่ทางอ้อมสัมบูรณ์ของ JMP คือ 6C (โปรดดูภาพประกอบต่อไปนี้)

ที่อยู่ทางอ้อมแบบสัมบูรณ์
ใช้กับคำสั่ง Jump (JMP) เท่านั้น สมมติว่าที่อยู่ที่มีไบต์ที่สนใจ (ไบต์เป้าหมาย) คือ 8765 ดอลลาร์ นี่คือ 16 บิตที่ประกอบด้วยสองไบต์ โดยไบต์ที่สูงกว่าคือ 87 ชม และไบต์ล่างคือ 65 ชม . ด้วยการกำหนดที่อยู่ทางอ้อมแบบสัมบูรณ์ ไบต์ทั้งสองนี้จริงๆ แล้วอยู่ในตำแหน่งไบต์สองตำแหน่งติดต่อกันที่อื่นในหน่วยความจำ

สมมติว่าตำแหน่งเหล่านั้นอยู่ในตำแหน่งหน่วยความจำที่ $0210 และ $0211 จากนั้นไบต์ล่างของที่อยู่ที่สนใจคือ 65 ชม อยู่ในที่อยู่ $0210 และไบต์ที่สูงกว่าคือ 87 ชม อยู่ในที่อยู่ $0211 นั่นหมายความว่าไบต์หน่วยความจำที่สนใจต่ำกว่าจะไปที่ที่อยู่ต่อเนื่องกันที่ต่ำกว่า และไบต์หน่วยความจำที่สนใจสูงกว่าจะไปที่ที่อยู่ติดต่อกันที่สูงกว่า - ความเอนเดียนเล็กน้อย

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

เจเอ็มพี ($0210)

ตัวช่วยในการจำของ JMP มี opcode สามตัว ได้แก่ 4C, 6C และ 7C opcode สำหรับการกำหนดที่อยู่ทางอ้อมแบบสัมบูรณ์คือ 6C สิ่งที่พิมพ์ในไฟล์ข้อความคือ “JMP ($0210)” เนื่องจากวงเล็บ แอสเซมเบลอร์ (ตัวแปล) จึงใช้ opcode 6C สำหรับ JMP ไม่ใช่ 4C หรือ 7C

ด้วยการระบุที่อยู่ทางอ้อมแบบสัมบูรณ์ จริงๆ แล้วมีขอบเขตหน่วยความจำสามส่วน ขอบเขตแรกอาจประกอบด้วยตำแหน่งไบต์ที่ $0200, $0201 และ $0202 นี่เป็นไบต์สามไบต์สำหรับคำสั่ง “JMP ($0210)” ขอบเขตที่สอง ซึ่งไม่จำเป็นต้องอยู่ติดกับขอบเขตแรก ประกอบด้วยตำแหน่งไบต์สองตำแหน่งติดต่อกันที่ $0210 และ $0211 นี่คือไบต์ล่าง ($0210) ที่พิมพ์ลงในคำสั่งโปรแกรมภาษาแอสเซมบลี หากที่อยู่ที่สนใจคือ $8765 ไบต์ล่างจะเป็น 65 ชม อยู่ในตำแหน่งไบต์ $0210 และไบต์ที่สูงกว่าคือ 87 ชม อยู่ในตำแหน่งไบต์ $0211 ภูมิภาคที่สามประกอบด้วยตำแหน่งไบต์เดียว เป็นที่อยู่ $8765 สำหรับไบต์เป้าหมาย (ไบต์สุดท้ายที่น่าสนใจ) ที่อยู่ติดกันคู่หนึ่งคือ $0210 และ $0211 มีตัวชี้ $8765 ซึ่งเป็นที่อยู่ที่สนใจ หลังจากการตีความด้วยคอมพิวเตอร์ จะมีราคา 8,765 ดอลลาร์สหรัฐฯ ที่จะเข้าสู่พีซี (ตัวนับโปรแกรม) เพื่อเข้าถึงไบต์เป้าหมาย

ที่อยู่ทางอ้อมหน้าศูนย์
การกำหนดแอดเดรสนี้เหมือนกับการกำหนดแอดเดรสทางอ้อมแบบสัมบูรณ์ แต่ตัวชี้ต้องอยู่ในหน้าศูนย์ ที่อยู่ไบต์ล่างของขอบเขตตัวชี้คือสิ่งที่อยู่ในคำสั่งที่พิมพ์ดังนี้:

เจเอ็มพี ($50)

ไบต์ที่สูงกว่าของตัวชี้อยู่ในตำแหน่ง $51 ไบต์ ที่อยู่ที่มีประสิทธิภาพ (ชี้) ไม่จำเป็นต้องอยู่ในหน้าศูนย์

ดังนั้น ด้วยการกำหนดแอดเดรสดัชนี ค่าในรีจิสเตอร์ดัชนีจะถูกเพิ่มไปยังที่อยู่ฐานที่กำหนดในคำสั่งเพื่อให้มีแอดเดรสที่มีประสิทธิภาพ การกำหนดที่อยู่ทางอ้อมใช้ตัวชี้

4.8 การกำหนดที่อยู่ทางอ้อมที่จัดทำดัชนี

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

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

เจเอ็มพี ($020A,X)

โดยที่ X register มีค่าเป็น 6 ชม . 020A ชม + 6 ชม = 0210 ชม . การลงทะเบียน Y จะไม่ใช้กับโหมดการกำหนดแอดเดรสนี้

ที่อยู่ทางอ้อมที่มีการจัดทำดัชนีหน้าเป็นศูนย์
โหมดการกำหนดแอดเดรสนี้ใช้รีจิสเตอร์ X ไม่ใช่รีจิสเตอร์ Y ด้วยโหมดการกำหนดแอดเดรสนี้ ยังคงมีค่าชี้และตัวชี้อยู่ในภูมิภาคตัวชี้ที่อยู่แบบสองไบต์ ต้องมีไบต์สองไบต์ติดต่อกันในหน้าศูนย์สำหรับตัวชี้ ที่อยู่ที่พิมพ์ในคำสั่งคือที่อยู่หนึ่งไบต์ ค่านี้จะถูกบวกเข้ากับค่าในรีจิสเตอร์ X และการพกพาใดๆ จะถูกยกเลิก ผลลัพธ์ชี้ไปที่ขอบเขตของตัวชี้ในหน้า 0 ตัวอย่างเช่น หากที่อยู่ที่สนใจ (ชี้) คือ $8765 และอยู่ในตำแหน่งไบต์ที่ $50 และ $51 ของหน้า 0 และค่าในการลงทะเบียน X คือ $30 ค่า คำสั่งที่พิมพ์จะเป็นดังนี้:

LDA ($20.X)

เพราะ $20 + $30 = $50

ที่อยู่ที่จัดทำดัชนีทางอ้อม
โหมดการกำหนดแอดเดรสนี้ใช้รีจิสเตอร์ Y ไม่ใช่รีจิสเตอร์ X ในโหมดการกำหนดแอดเดรสนี้ ยังคงมีค่าชี้และขอบเขตของตัวชี้ แต่เนื้อหาของขอบเขตของตัวชี้จะทำงานแตกต่างออกไป ต้องมีไบต์สองไบต์ติดต่อกันในหน้าศูนย์สำหรับขอบเขตตัวชี้ ที่อยู่ด้านล่างของขอบเขตตัวชี้จะถูกพิมพ์ลงในคำสั่ง หมายเลขนี้ (คู่ของไบต์) ที่มีอยู่ในขอบเขตของตัวชี้จะถูกเพิ่มเข้ากับค่าในการลงทะเบียน Y เพื่อให้มีตัวชี้ที่แท้จริง ตัวอย่างเช่น ให้ที่อยู่ที่สนใจ (ชี้) อยู่ที่ 8765 ดอลลาร์ ค่า 6H อยู่ในรีจิสเตอร์ Y และตัวเลข (สองไบต์) อยู่ที่ที่อยู่ 50 ชม และ 51 ชม . สองไบต์รวมกันคือ $875F เนื่องจาก $875F + $6 = $8765 คำสั่งที่พิมพ์มีลักษณะดังนี้:

LDA ($50) Y

4.9 คำแนะนำการเพิ่มขึ้น การลดลง และการทดสอบ BIT

ตารางต่อไปนี้แสดงการดำเนินการของคำแนะนำการเพิ่มขึ้นและการลดลง:

INA และ DEA จะเพิ่มขึ้นและลดตัวสะสมตามลำดับ นั่นเรียกว่าที่อยู่แบบสะสม INX, DEX, INY และ DEY ใช้สำหรับการลงทะเบียน X และ Y ตามลำดับ พวกเขาไม่ใช้ตัวถูกดำเนินการใด ๆ ดังนั้นพวกเขาจึงใช้โหมดการกำหนดที่อยู่โดยนัย การเพิ่มขึ้นหมายถึงการเพิ่ม 1 ลงในรีจิสเตอร์หรือไบต์หน่วยความจำ การลดลงหมายถึงการลบ 1 ออกจากรีจิสเตอร์หรือไบต์หน่วยความจำ

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

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

  • N ซึ่งเป็นบิต 7 และบิตสุดท้าย (ซ้าย) ของรีจิสเตอร์สถานะ จะได้รับบิต 7 ของตำแหน่งหน่วยความจำก่อน ANDing
  • V ซึ่งเป็นบิต 6 ของการลงทะเบียนสถานะจะได้รับบิต 6 ของตำแหน่งหน่วยความจำก่อน ANDing
  • ธง Z ของการลงทะเบียนสถานะถูกตั้งค่า (สร้าง 1) หากผลลัพธ์ของ AND เป็นศูนย์ (00000000 2 ). มิฉะนั้นจะถูกล้าง (ทำ 0)

4.10 คำแนะนำในการเปรียบเทียบ

ตัวช่วยจำคำสั่งเปรียบเทียบสำหรับ 6502 µP คือ CMP, CPX และ CPY หลังจากการเปรียบเทียบแต่ละครั้ง แฟล็ก N, Z และ C ของการลงทะเบียนสถานะโปรเซสเซอร์ “P” จะได้รับผลกระทบ ตั้งค่าสถานะ N (สร้าง 1) เมื่อผลลัพธ์เป็นจำนวนลบ ตั้งค่าสถานะ Z (สร้าง 1) เมื่อผลลัพธ์เป็นศูนย์ (000000002) แฟล็ก C ถูกตั้งค่า (สร้าง 1) เมื่อมีการยกจากบิตแปดถึงบิตที่เก้า ตารางต่อไปนี้จะแสดงภาพประกอบโดยละเอียด

มีความหมายว่า “มากกว่า” ด้วยเหตุนี้ ตารางเปรียบเทียบจึงควรอธิบายได้ในตัว

4.11 คำแนะนำการกระโดดและสาขา

ตารางต่อไปนี้สรุปคำสั่งการข้ามและสาขา:

คำสั่ง JMP ใช้การกำหนดที่อยู่แบบสัมบูรณ์และทางอ้อม คำแนะนำที่เหลือในตารางคือคำสั่งสาขา พวกเขาใช้เฉพาะการกำหนดที่อยู่แบบสัมพันธ์กับ 6502 µP ด้วยเหตุนี้ ตารางจึงอธิบายได้ในตัวหากอ่านจากซ้ายไปขวาและบนลงล่าง

โปรดทราบว่าสาขาสามารถใช้ได้เฉพาะกับที่อยู่ภายใน -128 ถึง +127 ไบต์จากที่อยู่ที่กำหนด นี่คือที่อยู่แบบสัมพันธ์ สำหรับทั้งคำสั่ง JMP และคำสั่งสาขา Program Counter (PC) จะได้รับผลกระทบโดยตรง 6502 µP ไม่อนุญาตให้สาขาไปยังที่อยู่ที่แน่นอน แม้ว่าการกระโดดจะสามารถระบุที่อยู่ที่แน่นอนได้ก็ตาม คำสั่ง JMP ไม่ใช่คำสั่งสาขา

บันทึก: การระบุที่อยู่แบบสัมพันธ์จะใช้กับคำสั่งสาขาเท่านั้น

4.12 พื้นที่สแต็ก

รูทีนย่อยเปรียบเสมือนหนึ่งในโปรแกรมสั้นก่อนหน้าที่จะเพิ่มตัวเลขสองตัวหรือลบตัวเลขสองตัว พื้นที่สแต็กในหน่วยความจำเริ่มต้นที่ $0100 ถึง $01FF รวม พื้นที่นี้เรียกง่ายๆ ว่าสแต็ก เมื่อไมโครโปรเซสเซอร์ดำเนินการข้ามไปยังคำสั่งรูทีนย่อย (JSR - อ้างอิงถึงการสนทนาต่อไปนี้) ไมโครโปรเซสเซอร์จำเป็นต้องรู้ว่าจะส่งคืนที่ไหนเมื่อเสร็จสิ้น 6502 µP เก็บข้อมูลนี้ (ที่อยู่ผู้ส่ง) ไว้ในหน่วยความจำต่ำตั้งแต่ $0100 ถึง $01FF (พื้นที่สแต็ก) และใช้เนื้อหาการลงทะเบียนตัวชี้สแต็กซึ่งเป็น 'S' ในไมโครโปรเซสเซอร์เป็นตัวชี้ (9 บิต) ไปยังที่อยู่ที่ส่งคืนล่าสุด ที่ถูกจัดเก็บไว้ในหน้า 1 ($0100 ถึง $01FF) ของหน่วยความจำ สแต็กจะขยายลงจาก $01FF และทำให้สามารถซ้อนรูทีนย่อยได้ลึกถึง 128 ระดับ

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

บันทึก : ตัวชี้สแต็กมี 8 บิตสำหรับที่อยู่ไบต์ล่างในการกำหนดตำแหน่งตั้งแต่ $0100 ถึง $01FF ไบต์ที่สูงกว่าคือ 00000001 2 ถือว่า

ตารางต่อไปนี้ให้คำแนะนำที่เกี่ยวข้องกับสแต็กพอยน์เตอร์ “S” กับรีจิสเตอร์ A, X, Y และ P เข้ากับพื้นที่สแต็กในหน่วยความจำ:

4.13 การโทรและส่งคืนรูทีนย่อย

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

JSR : ข้ามไปที่ SubRoutine

คำสั่งในการส่งคืนจากรูทีนย่อยคือ:

RTS : กลับจากรูทีนย่อย

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

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

ดูภาพประกอบต่อไปนี้สำหรับการใช้ JSR และ RTS:

4.14 ตัวอย่างการนับถอยหลัง

รูทีนย่อยต่อไปนี้นับถอยหลังจาก $FF ถึง $00 (รวมเป็น 256 10 นับ):

เริ่ม LDX #$FF ; โหลด X ด้วย $FF = 255
วนซ้ำ DEX ; เอ็กซ์ = เอ็กซ์ – 1
บีเอ็นอี ลูป ; ถ้า X ไม่ใช่ศูนย์ก็ให้ข้ามไป
เรียลไทม์ ; กลับ

แต่ละบรรทัดมีความคิดเห็น ความคิดเห็นไม่เคยเข้าไปในหน่วยความจำสำหรับการดำเนินการ แอสเซมเบลอร์ (นักแปล) ที่แปลงโปรแกรมเป็นสิ่งที่อยู่ในหน่วยความจำเพื่อดำเนินการ (ทำงาน) มักจะตัดความคิดเห็นออก ความคิดเห็นขึ้นต้นด้วย “;” . “start” และ “loop” ในโปรแกรมนี้เรียกว่า label ป้ายระบุ (ชื่อ) ที่อยู่ของคำสั่ง หากคำสั่งนั้นเป็นคำสั่งแบบไบต์เดียว (การกำหนดที่อยู่โดยนัย) ป้ายกำกับจะเป็นที่อยู่ของคำสั่งนั้น ถ้าคำสั่งเป็นคำสั่งแบบหลายไบต์ ป้ายจะระบุไบต์แรกสำหรับคำสั่งแบบหลายไบต์ คำสั่งแรกสำหรับโปรแกรมนี้ประกอบด้วยสองไบต์ สมมติว่าเริ่มต้นที่ที่อยู่ $0300 ที่อยู่ $0300 สามารถแทนที่ด้วย 'start' ในโปรแกรมได้ คำสั่งที่สอง (DEX) เป็นคำสั่งไบต์เดียว และควรอยู่ที่ที่อยู่ $0302 ซึ่งหมายความว่าที่อยู่ $0302 สามารถแทนที่ด้วย 'loop' ลงในโปรแกรม ซึ่งจริงๆ แล้วอยู่ใน 'BNE loop'

“BNE loop” หมายถึงสาขาไปยังที่อยู่ที่กำหนดเมื่อแฟล็ก Z ของการลงทะเบียนสถานะเป็น 0 เมื่อค่าในการลงทะเบียน A หรือ X หรือ Y คือ 00000000 2 เนื่องจากการดำเนินการครั้งล่าสุด แฟล็ก Z จึงเป็น 1 (ตั้งค่า) ดังนั้น แม้ว่าจะเป็น 0 (ไม่ใช่ 1) แต่คำสั่งที่สองและสามในโปรแกรมจะถูกทำซ้ำตามลำดับนั้น ในแต่ละลำดับที่ทำซ้ำ ค่า (จำนวนเต็ม) ในรีจิสเตอร์ X จะลดลง 1 DEX หมายถึง X = X – 1 เมื่อค่าในรีจิสเตอร์ X คือ $00 = 00000000 2 , Z กลายเป็น 1 ณ จุดนั้น จะไม่มีการซ้ำซ้อนของคำสั่งทั้งสองอีกต่อไป คำสั่ง RTS สุดท้ายในโปรแกรมซึ่งเป็นคำสั่งแบบไบต์เดียว (การกำหนดแอดเดรสโดยนัย) จะส่งคืนจากรูทีนย่อย ผลกระทบของคำสั่งนี้คือการสร้างที่อยู่ตัวนับโปรแกรมในสแต็กสำหรับโค้ดที่จะดำเนินการก่อนการเรียกรูทีนย่อยและกลับไปที่ตัวนับโปรแกรม (PC) ที่อยู่นี้เป็นที่อยู่ของคำสั่งที่จะดำเนินการก่อนที่จะเรียกใช้รูทีนย่อย

บันทึก: เมื่อเขียนโปรแกรมภาษาแอสเซมบลีสำหรับ 6502 µP เฉพาะป้ายกำกับเท่านั้นที่ต้องเริ่มต้นที่จุดเริ่มต้นของบรรทัด รหัสบรรทัดอื่นๆ จะต้องเลื่อนไปทางขวาอย่างน้อยหนึ่งช่อง

การเรียกรูทีนย่อย
โดยไม่สนใจพื้นที่หน่วยความจำที่เลเบลก่อนหน้านี้ใช้ โปรแกรมจะใช้ตำแหน่งต่อเนื่องกัน 6 ไบต์ในหน่วยความจำ (RAM) ตั้งแต่ $0300 ถึง $0305 ในกรณีนี้ โปรแกรมคือ:

LDX #$FF ; โหลด X ด้วย $FF = 255
เด็กซ์ ; เอ็กซ์ = เอ็กซ์ – 1
บีเอ็นอี $0302 ; ถ้า X ไม่ใช่ศูนย์ก็ให้ข้ามไป
เรียลไทม์ ; กลับ

เริ่มต้นจากที่อยู่ $0200 ในหน่วยความจำสามารถเรียกรูทีนย่อยได้ คำแนะนำการโทรคือ:

JSR เริ่มต้น ; start คือที่อยู่ $0300 เช่น JSR $0300

รูทีนย่อยและการเรียกที่เขียนอย่างถูกต้องในไฟล์เท็กซ์เอดิเตอร์คือ:

เริ่ม LDX #$FF; โหลด X ด้วย $FF = 255
วนซ้ำ DEX ; เอ็กซ์ = เอ็กซ์ – 1

บีเอ็นอี ลูป ; ถ้า X ไม่ใช่ศูนย์ก็ให้ข้ามไป
เรียลไทม์ ; กลับ

เริ่มต้น JSR : ข้ามไปยังรูทีนเริ่มต้นที่ $0300

ในตอนนี้ สามารถมีรูทีนย่อยได้มากมายในโปรแกรมขนาดยาวโปรแกรมเดียว พวกเขาทั้งหมดไม่สามารถมีชื่อ 'เริ่มต้น' พวกเขาควรมีชื่อที่แตกต่างกัน จริงๆ แล้วไม่มีสักคนที่มีชื่อว่า 'เริ่มต้น' “Start” ถูกใช้ในที่นี้เพื่อการสอน

4.15 การแปลโปรแกรม

การแปลโปรแกรมหรือการประกอบมันมีความหมายเดียวกัน พิจารณาโปรแกรมต่อไปนี้:

เริ่ม LDX #$FF : โหลด X ด้วย $FF = 255
ลูป DEX : X = X – 1
BNE loop : ถ้า X ไม่เป็นศูนย์ ให้ข้ามไป
RTS : กลับมา
เริ่มต้น JSR : ข้ามไปยังรูทีนเริ่มต้นที่ $0300

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

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

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

โปรแกรมประกอบสามารถจัดทำเป็นเอกสารได้ดังนี้:

การทำเอกสารลักษณะนี้ว่ากันว่าเป็นการประกอบด้วยมือ โปรดทราบว่าความคิดเห็นในเอกสารนี้ไม่ปรากฏในหน่วยความจำ (สำหรับการดำเนินการ) คอลัมน์ที่อยู่ในตารางระบุที่อยู่เริ่มต้นของคำแนะนำในหน่วยความจำ โปรดทราบว่า 'JSR start' ซึ่งก็คือ 'JSR $0300' ซึ่งคาดว่าจะมีรหัสเป็น '20 03 00' จริงๆ แล้วมีรหัสเป็น '20 00 03' โดยที่อยู่ไบต์หน่วยความจำด้านล่างจะใช้ไบต์ล่างในหน่วยความจำและ ที่อยู่ไบต์หน่วยความจำที่สูงกว่าใช้ไบต์ที่สูงกว่าในหน่วยความจำ - ความเอนเอียงเล็กน้อย opcode สำหรับ JSR คือ 20 16 .

โปรดทราบว่าการชดเชยคำสั่งสาขาเช่น BNE นั้นเป็นหมายเลขเสริมของทั้งสองในช่วง 128 10 ถึง +127 10 . ดังนั้น “BNE loop” จึงหมายถึง “BNE -1 10 ” ซึ่งจริงๆ แล้วคือ “D0 FF” ในรูปแบบโค้ดของ FF 16 คือ -1 ในส่วนเสริมของสองซึ่งเขียนเป็น = 11111111 ในฐานสอง โปรแกรมแอสเซมเบลอร์จะแทนที่เลเบลและฟิลด์เป็นเลขฐานสิบหกจริง (เลขฐานสิบหกคือเลขฐานสองที่จัดกลุ่มเป็นสี่บิต) ที่อยู่จริงที่แต่ละคำสั่งเริ่มต้นจะรวมอยู่ด้วยจริงๆ

บันทึก: คำสั่ง 'JSR start' จะถูกแทนที่ด้วยคำสั่งที่สั้นกว่าซึ่งส่งเนื้อหาปัจจุบัน (ไบต์สูงและต่ำ) ของตัวนับโปรแกรมไปยังสแต็กด้วยตัวชี้สแต็กที่ลดลงสองครั้ง (หนึ่งครั้งสำหรับไบต์สูงและอีกครั้งสำหรับไบต์ต่ำ) และ จากนั้นรีโหลดพีซีด้วยที่อยู่ $0300 ตัวชี้สแต็กตอนนี้ชี้ไปที่ $00FD โดยสมมติว่ามันถูกเตรียมใช้งานเป็น $01FF

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

บันทึก: ข้อความป้ายกำกับไม่ควรมีอักขระเกิน 8 ตัว

“BNE loop” ใช้การกำหนดที่อยู่แบบสัมพันธ์ แปลว่า เพิ่ม -3 10 ไปยังเนื้อหาตัวนับโปรแกรมถัดไปของ $0305 ไบต์สำหรับ 'BNE loop' คือ 'D0 FD' โดยที่ FD คือส่วนเสริมของทั้งสองคือ -3 10 .

หมายเหตุ: บทนี้ไม่ได้นำเสนอคำแนะนำทั้งหมดสำหรับ 6502 µP คำแนะนำทั้งหมดและรายละเอียดมีอยู่ในเอกสารชื่อ “ตระกูลไมโครโปรเซสเซอร์ 8 บิต SY6500” มีไฟล์ PDF ชื่อ “6502.pdf” สำหรับเอกสารนี้ซึ่งหาได้ฟรีทางอินเทอร์เน็ต 6502 µP ที่อธิบายไว้ในเอกสารนี้คือ 65C02

4.16 การขัดจังหวะ

สัญญาณของอุปกรณ์ใดๆ ที่เชื่อมต่อกับพอร์ตภายนอก (พื้นผิวแนวตั้ง) ของ Commodore 64 จะต้องผ่านวงจร CIA 1 หรือ CIA 2 (IC) ก่อนที่จะถึงไมโครโปรเซสเซอร์ 6502 สัญญาณจากบัสข้อมูลของ 6502 µP จะต้องผ่านชิป CIA 1 หรือ CIA 2 ก่อนที่จะเข้าถึงอุปกรณ์ภายนอกใดๆ CIA ย่อมาจาก Complex Interface Adapter ในรูปที่ 4.1 “บล็อกไดอะแกรมของมาเธอร์บอร์ด Commodore_64” อุปกรณ์อินพุต/เอาท์พุตแบบบล็อกเป็นตัวแทนของ CIA 1 และ CIA 2 เมื่อโปรแกรมกำลังทำงานอยู่ การรันโค้ดชิ้นอื่นบางส่วนอาจถูกขัดจังหวะก่อนดำเนินการต่อ มีการหยุดชะงักของฮาร์ดแวร์และการหยุดชะงักของซอฟต์แวร์ สำหรับการหยุดชะงักของฮาร์ดแวร์ จะมีพินสัญญาณอินพุตสองตัวที่ 6502 µP ชื่อของหมุดเหล่านี้คือ IRQ และ เอ็นเอ็มไอ . สิ่งเหล่านี้ไม่ใช่เส้นข้อมูล µP เส้นข้อมูลสำหรับ µP คือ D7, D6, D5, D4, D3, D2, D1 และ D0; โดย D0 สำหรับบิตที่มีนัยสำคัญน้อยที่สุด และ D7 สำหรับบิตที่สำคัญที่สุด

IRQ ย่อมาจาก Interrupt ReQuest “active” ต่ำ โดยปกติแล้วสายอินพุตไปยัง µP จะสูงประมาณ 5 โวลต์ เมื่อลดลงเหลือประมาณ 0 โวลต์ นั่นคือคำขอขัดจังหวะที่ส่งสัญญาณ µP ทันทีที่คำขอได้รับอนุมัติ เส้นก็จะกลับขึ้นสูงอีกครั้ง การให้คำขอขัดจังหวะหมายความว่า µP แยกสาขาไปยังโค้ด (รูทีนย่อย) ที่จัดการการขัดจังหวะ

เอ็นเอ็มไอ ย่อมาจาก Non-Maskable Interrupt “ใช้งานอยู่” ต่ำ ในขณะที่รหัสสำหรับ IRQ กำลังถูกดำเนินการ เอ็นเอ็มไอ สามารถไปต่ำได้ ในกรณีนี้, เอ็นเอ็มไอ ได้รับการจัดการ (ดำเนินการโค้ดของตัวเอง) หลังจากนั้นก็โค้ดสำหรับ IRQ ดำเนินต่อไป หลังจากโค้ดสำหรับ IRQ สิ้นสุด โค้ดโปรแกรมหลักจะดำเนินต่อไป นั่นคือ, เอ็นเอ็มไอ ขัดจังหวะ IRQ ตัวจัดการ สัญญาณสำหรับ เอ็นเอ็มไอ ยังสามารถมอบให้กับ µP ได้แม้ว่า µP จะไม่ได้ใช้งานและไม่ได้จัดการอะไรหรือไม่ได้รันโปรแกรมหลักก็ตาม

บันทึก: จริงๆ แล้วมันคือการเปลี่ยนจากสูงไปต่ำ เอ็นเอ็มไอ , นั่นคือ เอ็นเอ็มไอ สัญญาณ – จะมีรายละเอียดเพิ่มเติมในภายหลัง IRQ ปกติจะมาจาก CIA 1 และ เอ็นเอ็มไอ ปกติจะมาจาก CIA 2 เอ็นเอ็มไอ ซึ่งย่อมาจาก Non-Maskable Interrupt ถือเป็นการขัดจังหวะที่หยุดไม่ได้

การจัดการกับการขัดจังหวะ
ไม่ว่าจะเป็นคำขอมาจาก IRQ หรือ เอ็นเอ็มไอ คำสั่งปัจจุบันจะต้องเสร็จสิ้น 6502 มีเพียงรีจิสเตอร์ A, X และ Y เท่านั้น ขณะที่รูทีนย่อยกำลังทำงานอยู่ อาจใช้รีจิสเตอร์ทั้งสามนี้ร่วมกัน ตัวจัดการการขัดจังหวะยังคงเป็นรูทีนย่อย แม้ว่าจะไม่เห็นเป็นเช่นนั้นก็ตาม หลังจากคำสั่งปัจจุบันเสร็จสิ้น เนื้อหาของรีจิสเตอร์ A, X และ Y สำหรับ 65C02 µP จะถูกบันทึกไว้ในสแต็ก ที่อยู่ของคำสั่งถัดไปของ Program Counter ก็ถูกส่งไปยังสแต็กด้วย จากนั้น µP จะแยกไปยังโค้ดสำหรับการขัดจังหวะ หลังจากนั้น เนื้อหาของรีจิสเตอร์ A, X และ Y จะถูกกู้คืนจากสแต็กในลำดับย้อนกลับที่ถูกส่งไป

ตัวอย่างการเข้ารหัสสำหรับการขัดจังหวะ
เพื่อความง่าย สมมติว่ารูทีนสำหรับ µP IRQ การขัดจังหวะเป็นเพียงการเพิ่มตัวเลข $01 และ $02 และบันทึกผลลัพธ์ของ $03 ที่ที่อยู่หน่วยความจำ $0400 รหัสคือ:

ไอเอสอาร์ ฟา
PHX
พี.วาย
;
แอลดีเอ #$01
ADC #$02
ราคา $0400
;
ชั้น
PLX
ปลา
สทท

ISR เป็นป้ายกำกับและระบุที่อยู่หน่วยความจำซึ่งมีคำสั่ง PHA ISR หมายถึง กิจวัตรการบริการขัดจังหวะ PHA, PHX และ PHY ส่งเนื้อหาของรีจิสเตอร์ A, X และ Y ไปยังสแต็กด้วยความหวังว่าจะจำเป็นต้องใช้โค้ด (โปรแกรม) ใดก็ตามที่ทำงานก่อนการหยุดชะงัก คำสั่งสามคำสั่งถัดไปเป็นแกนหลักของตัวจัดการการขัดจังหวะ คำสั่ง PLY, PLX และ PLA จะต้องอยู่ในลำดับนั้น และคำสั่งเหล่านั้นจะนำเนื้อหาของรีจิสเตอร์ Y, X และ A กลับมา คำสั่งสุดท้ายซึ่งก็คือ RTI (ไม่มีตัวถูกดำเนินการ) จะส่งคืนความต่อเนื่องของการดำเนินการไปยังโค้ด (โปรแกรม) ใดก็ตามที่กำลังดำเนินการก่อนที่จะหยุดชะงัก RTI ดึงที่อยู่ของคำสั่งถัดไปของโค้ดที่กำลังดำเนินการจากสแต็กกลับไปที่ตัวนับโปรแกรม RTI หมายถึงการกลับมาจากการขัดจังหวะ ด้วยเหตุนี้ การจัดการการขัดจังหวะ (รูทีนย่อย) จึงสิ้นสุดลง

ซอฟต์แวร์ขัดจังหวะ
วิธีหลักในการให้ซอฟต์แวร์ขัดจังหวะสำหรับ 6502 µP คือการใช้คำสั่งที่อยู่โดยนัยของ BRK สมมติว่าโปรแกรมหลักกำลังทำงานอยู่และพบคำสั่ง BRK จากจุดนั้น ที่อยู่ของคำสั่งถัดไปในพีซีควรถูกส่งไปยังสแต็กเมื่อคำสั่งปัจจุบันเสร็จสมบูรณ์ รูทีนย่อยสำหรับจัดการคำสั่งซอฟต์แวร์ควรเรียกว่า 'ถัดไป' รูทีนย่อยขัดจังหวะนี้ควรส่งเนื้อหารีจิสเตอร์ A, X และ Y ลงในสแต็ก หลังจากที่แกนหลักของรูทีนย่อยถูกดำเนินการแล้ว เนื้อหาของรีจิสเตอร์ A, X และ Y ควรถูกดึงกลับจากสแต็กไปยังรีจิสเตอร์โดยรูทีนย่อยที่สมบูรณ์ ข้อความสุดท้ายในกิจวัตรคือ RTI เนื้อหาพีซีจะถูกดึงกลับจากสแต็กไปยังพีซีโดยอัตโนมัติเนื่องจาก RTI

การเปรียบเทียบและความแตกต่างระหว่างรูทีนย่อยและรูทีนบริการขัดจังหวะ
ตารางต่อไปนี้เปรียบเทียบและเปรียบเทียบรูทีนย่อยและรูทีนบริการขัดจังหวะ:

4.17 สรุปโหมดการกำหนดแอดเดรสหลัก 6502

แต่ละคำสั่งสำหรับ 6502 คือหนึ่งไบต์ ตามด้วยศูนย์ตัวถูกดำเนินการหรือมากกว่า

โหมดที่อยู่ทันที
เมื่อใช้โหมดการกำหนดแอดเดรสทันที หลังจากตัวถูกดำเนินการ จะเป็นค่า ไม่ใช่แอดเดรสหน่วยความจำ ค่าจะต้องนำหน้าด้วย # หากค่าเป็นเลขฐานสิบหก เครื่องหมาย “#” จะต้องตามด้วย “$” คำแนะนำในการดำเนินการทันทีสำหรับ 65C02 คือ: ADC, AND, BIT, CMP, CPX, CPY, EOR, LDA, LDX, LDY, ORA, SBC ผู้อ่านควรอ่านเอกสารประกอบสำหรับ 65C02 µP เพื่อทราบวิธีใช้คำแนะนำที่แสดงไว้ที่นี่ซึ่งไม่ได้อธิบายไว้ในบทนี้ ตัวอย่างคำสั่งคือ:

แอลดีเอ #$77

โหมดการกำหนดที่อยู่แบบสัมบูรณ์
ในโหมดการกำหนดแอดเดรสแบบสัมบูรณ์ จะมีตัวถูกดำเนินการหนึ่งตัว ตัวถูกดำเนินการนี้คือที่อยู่ของค่าในหน่วยความจำ (โดยปกติจะเป็นเลขฐานสิบหกหรือป้ายกำกับ) มี 64K 10 = 65,536 10 ที่อยู่หน่วยความจำสำหรับ 6502 µP โดยทั่วไป ค่าหนึ่งไบต์จะอยู่ที่หนึ่งในที่อยู่เหล่านี้ คำแนะนำการกำหนดที่อยู่ที่แน่นอนสำหรับ 65C02 คือ: ADC, AND, ASL, BIT, CMP, CPX, CPY, DEC, EOR, INC, JMP, JSR, LDA, LDX, LDY, LSR, ORA, ROL, ROR, SBC, STA , STX, STY, STZ, TRB, TSB ผู้อ่านควรอ่านเอกสารประกอบสำหรับ 65C02 µP เพื่อทราบวิธีใช้คำแนะนำที่แสดงไว้ที่นี่ รวมถึงโหมดการกำหนดที่อยู่ที่เหลือที่ไม่ได้อธิบายไว้ในบทนี้ ตัวอย่างคำสั่งคือ:

พวกเขาคือ $1234

โหมดที่อยู่โดยนัย
ในโหมดการกำหนดแอดเดรสโดยนัย จะไม่มีตัวถูกดำเนินการ การลงทะเบียน µP ใดๆ ที่เกี่ยวข้องจะเป็นไปตามคำสั่ง คำแนะนำการระบุที่อยู่โดยนัยสำหรับ 65C02 ได้แก่: BRK, CLC, CLD, CLI, CLV, DEX, DEY, INX, INY, NOP, PHA, PHP, PHX, PHY, PLA, PLP, PLX, PLY, RTI, RTS, SEC , SED, SEI, ภาษี, TAY, TSX, TXA, TXS, TYA ตัวอย่างคำสั่งคือ:

DEX : ลดการลงทะเบียน X ลงหนึ่งหน่วย

โหมดการกำหนดที่อยู่แบบสัมพัทธ์
โหมดการกำหนดที่อยู่แบบสัมพันธ์เกี่ยวข้องกับคำสั่งสาขาเท่านั้น ในโหมดการกำหนดแอดเดรสแบบสัมพันธ์ จะมีตัวถูกดำเนินการเพียงตัวเดียวเท่านั้น เป็นค่าตั้งแต่ -128 10 ถึง +127 10 . ค่านี้เรียกว่าออฟเซ็ต ตามเครื่องหมาย ค่านี้จะถูกบวกหรือลบออกจากคำสั่งถัดไปของตัวนับโปรแกรมเพื่อให้ได้ที่อยู่ของคำสั่งถัดไปที่ต้องการ คำแนะนำโหมดที่อยู่แบบสัมพันธ์คือ: BCC, BCS, BEQ, BMI, BNE, BPL, BRA, BVC, BVS ตัวอย่างคำสั่งคือ:

BNE $7F : (สาขาถ้า Z = 0 ในทะเบียนสถานะ, P)

ซึ่งเพิ่ม 127 ให้กับตัวนับโปรแกรมปัจจุบัน (ที่อยู่ที่จะดำเนินการ) และเริ่มดำเนินการคำสั่งตามที่อยู่นั้น ในทำนองเดียวกัน:

BEQ $F9 : (สาขาถ้า Z = : ในสถานะ register, P)

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

ที่อยู่ที่จัดทำดัชนีสัมบูรณ์
ในการกำหนดที่อยู่ดัชนีแบบสัมบูรณ์ เนื้อหาของการลงทะเบียน X หรือ Y จะถูกเพิ่มไปยังที่อยู่ที่แน่นอนที่กำหนด (ตั้งแต่ $0000 ถึง $FFFF เช่น จาก 0 10 ถึง 65536 10 ) เพื่อให้มีที่อยู่จริง ที่อยู่ที่แน่นอนนี้เรียกว่าที่อยู่ฐาน ถ้าใช้ X register คำสั่งแอสเซมบลีจะเป็นดังนี้:

LDA $C453,X

หากใช้การลงทะเบียน Y มันจะมีลักษณะดังนี้:

LDA $C453,Y

ค่าสำหรับรีจิสเตอร์ X หรือ Y เรียกว่าค่าการนับหรือดัชนี และอาจมีค่าตั้งแต่ $00 (0 10 ) ถึง $FF (250 10 ). มันไม่ได้เรียกว่าออฟเซ็ต

คำแนะนำการกำหนดที่อยู่ดัชนีแบบสัมบูรณ์คือ: ADC, AND, ASL (X เท่านั้น), BIT (พร้อมตัวสะสมและหน่วยความจำ, พร้อม X เท่านั้น), CMP, DEC (หน่วยความจำและ X เท่านั้น), EOR, INC (หน่วยความจำและ X เท่านั้น), LDA , LDX, LDY, LSR (X เท่านั้น), ORA, ROL (X เท่านั้น), ROR (X เท่านั้น), SBC, STA, STZ (X เท่านั้น)

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

เจเอ็มพี ($3456)

ด้วยวงเล็บ และ $13 อยู่ในตำแหน่งที่อยู่ $3456 ในขณะที่ $EB อยู่ในตำแหน่งที่อยู่ $3457 (= $3456 + 1) จากนั้นที่อยู่ปลายทางคือ $13EB และ $13EB เป็นตัวชี้ ค่าสัมบูรณ์ $3456 อยู่ในวงเล็บในคำสั่ง โดยที่ 34 คือไบต์ล่าง และ 56 คือไบต์ที่สูงกว่า

4.18 การสร้างสตริงด้วยภาษาแอสเซมบลี 6502 µP

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

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

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

ตารางต่อไปนี้แสดงการตั้งค่าหน่วยความจำสตริงเมื่อไบต์แรกเป็น 11 10 = 0B 16 : :

ตารางต่อไปนี้แสดงการตั้งค่าหน่วยความจำสตริงเมื่อไบต์แรกคือ “I” และไบต์สุดท้ายเป็น Null ($00):

คำแนะนำต่อไปนี้สามารถใช้เพื่อเริ่มสร้างสตริง:

ราคา $0300

สมมติว่าไบต์แรกอยู่ในตัวสะสมที่จะถูกส่งไปยังตำแหน่งที่อยู่ 0300 ดอลลาร์ คำสั่งนี้เป็นจริงสำหรับทั้งสองกรณี (สตริงทั้งสองประเภท)

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

4.19 การสร้างอาร์เรย์ด้วยภาษาแอสเซมบลี 6502 µP

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

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

4.20 ปัญหา

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

  1. เขียนโปรแกรมภาษาแอสเซมบลีซึ่งเริ่มต้นที่ 0200 ดอลลาร์สำหรับ 6502 µP และเพิ่มตัวเลข 2A94 ที่ไม่ได้ลงนาม ชม (เติม) ลงใน 2ABF ชม (สิงหาคม). ให้อินพุตและเอาท์พุตอยู่ในหน่วยความจำ อีกทั้งจัดทำเอกสารโปรแกรมที่ประกอบขึ้นด้วยมือ
  2. เขียนโปรแกรมภาษาแอสเซมบลีซึ่งเริ่มต้นที่ 0200 ดอลลาร์สำหรับ 6502 µP และลบตัวเลขที่ไม่ได้ลงนามคือ 1569 ชม (ซับทราเฮนด์) จาก 2ABF ชม (นาที). ปล่อยให้อินพุตและเอาต์พุตอยู่ในหน่วยความจำ อีกทั้งจัดทำเอกสารโปรแกรมที่ประกอบขึ้นด้วยมือ
  3. เขียนโปรแกรมภาษาแอสเซมบลีสำหรับ 6502 µP ที่นับตั้งแต่ $00 ถึง $09 โดยใช้ลูป โปรแกรมควรเริ่มต้นที่ $0200 อีกทั้งจัดทำเอกสารโปรแกรมที่ประกอบขึ้นด้วยมือ
  4. เขียนโปรแกรมภาษาแอสเซมบลีซึ่งเริ่มต้นที่ 0200 ดอลลาร์สำหรับ 6502 µP โปรแกรมมีสองรูทีนย่อย รูทีนย่อยแรกจะเพิ่มหมายเลขที่ไม่ได้ลงชื่อ 0203 ชม (เพิ่ม) และ 0102H (เพิ่ม) รูทีนย่อยที่สองจะเพิ่มผลรวมจากรูทีนย่อยแรกซึ่งก็คือ 0305H ถึง 0006 ชม (สิงหาคม). ผลลัพธ์สุดท้ายจะถูกเก็บไว้ในหน่วยความจำ เรียกรูทีนย่อยแรกซึ่งก็คือ FSTSUB และรูทีนย่อยที่สองซึ่งก็คือ SECSUB ปล่อยให้อินพุตและเอาต์พุตอยู่ในหน่วยความจำ พร้อมทั้งจัดทำเอกสารโปรแกรมที่ประกอบขึ้นสำหรับทั้งโปรแกรมด้วยมือ
  5. โดยพิจารณาว่า IRQ ตัวจัดการจะเพิ่ม $02 ถึง $01 ที่ตัวสะสมเป็นการจัดการหลักในขณะที่ เอ็นเอ็มไอ ได้รับการออกและการจัดการหลักสำหรับ เอ็นเอ็มไอ เพิ่ม $05 ถึง $04 ที่ตัวสะสม เขียนภาษาแอสเซมบลีสำหรับตัวจัดการทั้งสองรวมถึงการเรียกของพวกเขาด้วย โทรไปที่ IRQ ตัวจัดการควรอยู่ที่ที่อยู่ $0200 ที่ IRQ ตัวจัดการควรเริ่มต้นที่ที่อยู่ $0300 ที่ เอ็นเอ็มไอ ตัวจัดการควรเริ่มต้นที่ที่อยู่ $0400 ผลลัพธ์ของการ IRQ ตัวจัดการควรถูกใส่ไว้ที่ที่อยู่ $0500 และผลลัพธ์ของ เอ็นเอ็มไอ ตัวจัดการควรอยู่ที่ที่อยู่ $0501
  6. อธิบายโดยย่อถึงวิธีการใช้คำสั่ง BRK เพื่อสร้างซอฟต์แวร์ขัดจังหวะในคอมพิวเตอร์ 65C02
  7. สร้างตารางที่เปรียบเทียบและเปรียบเทียบรูทีนย่อยปกติกับรูทีนบริการขัดจังหวะ
  8. อธิบายโหมดการกำหนดแอดเดรสหลักของ 65C02 µP โดยย่อตามตัวอย่างคำสั่งภาษาแอสเซมบลี
  9. ก) เขียนโปรแกรมภาษาเครื่อง 6502 เพื่อใส่คำว่า “ฉันรักคุณ!” สตริงของรหัส ASCII ในหน่วยความจำ เริ่มต้นจากที่อยู่ $0300 พร้อมความยาวของสตริง โปรแกรมควรเริ่มต้นที่ที่อยู่ $0200 รับอักขระแต่ละตัวจากตัวสะสมทีละตัว โดยสมมติว่าอักขระเหล่านั้นถูกส่งไปที่นั่นโดยรูทีนย่อยบางตัว อีกทั้งประกอบโปรแกรมด้วยมือ (หากคุณต้องการทราบรหัส ASCII สำหรับ “ฉันรักคุณ!” นี่คือ: 'ฉัน':49 16 , ช่องว่าง : 20 16 , 'ล': 6C 16 , 'o':6F 16 , 'ใน':76 16 , 'e':65, 'y':79 16 , 'ใน':75 16 และ '!':21 16 (หมายเหตุ: แต่ละรหัสใช้พื้นที่ 1 ไบต์)
    b) เขียนโปรแกรมภาษาเครื่อง 6502 เพื่อใส่คำว่า 'ฉันรักคุณ!' สตริงของรหัส ASCII ในหน่วยความจำ เริ่มต้นจากที่อยู่ $0300 โดยไม่มีความยาวของสตริง แต่ลงท้ายด้วย 00 16 . โปรแกรมควรเริ่มต้นที่ที่อยู่ $0200 รับอักขระแต่ละตัวจากตัวสะสม โดยสมมติว่าอักขระเหล่านั้นถูกส่งไปที่นั่น ทีละตัว โดยรูทีนย่อยบางตัว อีกทั้งประกอบโปรแกรมด้วยมือ