พื้นหลัง
ฉันชอบชิป 8 บิต 6502 แบบเก่าของฉัน มันสนุกมากที่จะไขความท้าทายบางอย่างที่นี่บน PPCG ในรหัสเครื่อง 6502 แต่บางสิ่งที่ควรจะง่าย (เช่นอ่านข้อมูลหรือส่งออกไปยัง stdout) นั้นยุ่งยากโดยไม่จำเป็นในรหัสเครื่อง ดังนั้นจึงมีความคิดคร่าวๆในใจของฉัน: คิดค้นเครื่องเสมือน 8 บิตของตัวเองที่ได้รับแรงบันดาลใจจาก 6502 แต่ด้วยการออกแบบที่ปรับเปลี่ยนให้ใช้งานได้มากกว่าสำหรับความท้าทาย เริ่มใช้บางสิ่งฉันรู้ว่านี่อาจเป็นความท้าทายที่ดีถ้าการออกแบบ VM ลดลงจนเหลือน้อยที่สุด :)
งาน
ใช้เครื่องเสมือน 8 บิตที่สอดคล้องกับข้อกำหนดต่อไปนี้ นี่คือโค้ดกอล์ฟดังนั้นการติดตั้งที่มีไบต์น้อยที่สุดจะชนะ
อินพุต
การใช้งานของคุณควรใช้อินพุตต่อไปนี้:
ไบต์ที่ไม่ได้ลงนามเดียว
pc
นี่คือตัวนับโปรแกรมเริ่มต้น (ที่อยู่ในหน่วยความจำที่ VM เริ่มดำเนินการ0
- ตาม)รายการไบต์ที่มีความยาวสูงสุดของ
256
รายการนี่คือ RAM สำหรับเครื่องเสมือน (ที่มีเนื้อหาเริ่มต้น)
คุณสามารถรับอินพุตนี้ในรูปแบบที่สมเหตุสมผล
เอาท์พุต
รายการไบต์ซึ่งเป็นเนื้อหาสุดท้ายของ RAM หลังจาก VM ยกเลิก (ดูด้านล่าง) คุณสามารถสมมติว่าคุณได้รับการป้อนข้อมูลที่นำไปสู่การยกเลิกในที่สุด อนุญาตรูปแบบที่เหมาะสม
CPU เสมือน
ซีพียูเสมือนมี
- ตัวนับโปรแกรม 8 บิต
- ตัวสะสมแบบ 8 บิตที่เรียกว่า
A
และ - ลงทะเบียนดัชนี 8
X
บิตที่เรียกว่า
มีสถานะสามสถานะ:
Z
- ตั้งค่าสถานะเป็นศูนย์หลังจากการดำเนินการบางอย่างส่งผล0
N
- ตั้งค่าสถานะเชิงลบหลังจากที่ผลการดำเนินงานบางอย่างในจำนวนลบ (iow บิต 7 ของผลการตั้งค่า)C
- ค่าสถานะพกถูกตั้งค่าโดยการเพิ่มเติมและกะสำหรับบิต "หายไป" ของผลลัพธ์
เมื่อเริ่มต้นแฟล็กจะถูกล้างทั้งหมดตัวนับโปรแกรมจะถูกตั้งค่าเป็นค่าที่กำหนดและเนื้อหาของA
และX
ไม่แน่นอน
ค่า 8 บิตแสดงถึงอย่างใดอย่างหนึ่ง
- ที่ไม่ได้ลงนามจำนวนเต็มในช่วง
[0..255]
- ลงนามจำนวนเต็ม 2 สมบูรณ์ในช่วง
[-128..127]
ขึ้นอยู่กับบริบท หากการดำเนินการมากเกินไปหรือน้อยเกินไปค่าจะถูกล้อมรอบ (และในกรณีที่มีการเพิ่มค่าสถานะการพกพาจะได้รับผลกระทบ)
การสิ้นสุด
เครื่องเสมือนจะหยุดทำงานเมื่อ
-
HLT
คำแนะนำถึง - เข้าถึงที่อยู่หน่วยความจำที่ไม่มีอยู่
- ตัวนับโปรแกรมทำงานนอกหน่วยความจำ (โปรดทราบว่ามันจะไม่พันรอบแม้ว่า VM จะได้รับหน่วยความจำเต็ม 256 ไบต์)
โหมดที่อยู่
- โดยนัย - คำสั่งไม่มีข้อโต้แย้งตัวถูกดำเนินการโดยนัย
- ทันที - ตัวถูกดำเนินการเป็นไบต์โดยตรงหลังจากการเรียนการสอน
- สัมพัทธ์ - (สำหรับการแตกแขนงเท่านั้น) ไบต์หลังจากคำสั่งถูกลงชื่อ (ส่วนเติมเต็ม 2) และกำหนดออฟเซ็ตเพื่อเพิ่มลงในตัวนับโปรแกรมหากมีการแยกสาขา
0
เป็นที่ตั้งของคำแนะนำต่อไปนี้ - แน่นอน - ไบต์หลังจากคำสั่งคือที่อยู่ของตัวถูกดำเนินการ
- จัดทำดัชนี - ไบต์หลังจากคำสั่งบวก
X
(การลงทะเบียน) คือที่อยู่ของตัวถูกดำเนินการ
คำแนะนำ
การเรียนการสอนในแต่ละประกอบด้วย opcode (หนึ่งไบต์) และในโหมดที่อยู่ได้ทันที , ญาติ , แน่นอนและการจัดทำดัชนีไบต์อาร์กิวเมนต์ที่สอง เมื่อ CPU เสมือนดำเนินการคำสั่งจะเพิ่มตัวนับโปรแกรมตาม (โดย1
หรือ2
)
opcodes ทั้งหมดที่แสดงในที่นี้เป็นเลขฐานสิบหก
LDA
- ตัวถูกดำเนินการโหลดเข้าA
- Opcodes: ทันที:
00
, สัมบูรณ์:02
, จัดทำดัชนี:04
- ธง:
Z
,N
- Opcodes: ทันที:
STA
- เก็บตัวA
ถูกดำเนินการ- Opcodes: ทันที:
08
, สัมบูรณ์:0a
, จัดทำดัชนี:0c
- Opcodes: ทันที:
LDX
- ตัวถูกดำเนินการโหลดเข้าX
- Opcodes: ทันที:
10
, แน่นอน:12
, จัดทำดัชนี:14
- ธง:
Z
,N
- Opcodes: ทันที:
STX
- เก็บตัวX
ถูกดำเนินการ- Opcodes: ทันที:
18
, สัมบูรณ์:1a
, จัดทำดัชนี:1c
- Opcodes: ทันที:
AND
- bitwise และ ofA
และ operand เป็นA
- Opcodes: ทันที:
30
, แน่นอน:32
, จัดทำดัชนี:34
- ธง:
Z
,N
- Opcodes: ทันที:
ORA
- bitwise หรือของA
และ operand เป็นA
- Opcodes: ทันที:
38
, แน่นอน:3a
, จัดทำดัชนี:3c
- ธง:
Z
,N
- Opcodes: ทันที:
EOR
- bitor xor (พิเศษหรือ) ของA
และถูกดำเนินการไปA
- Opcodes: ทันที:
40
, แน่นอน:42
, จัดทำดัชนี:44
- ธง:
Z
,N
- Opcodes: ทันที:
LSR
- ตรรกะเลื่อนไปทางขวาเลื่อนบิตของตัวถูกดำเนินการทั้งหมดที่เดียวไปทางขวาบิต 0 จะถูกนำไปใช้- Opcodes: ทันที:
48
, สัมบูรณ์:4a
, จัดทำดัชนี:4c
- ธง:
Z
,N
,C
- Opcodes: ทันที:
ASL
- การเลื่อนเลขคณิตไปทางซ้ายเลื่อนบิตของตัวถูกดำเนินการทั้งหมดที่เดียวไปทางซ้ายบิต 7 จะถูกดำเนินการ- Opcodes: ทันที:
50
, สัมบูรณ์:52
, จัดทำดัชนี:54
- ธง:
Z
,N
,C
- Opcodes: ทันที:
ROR
- หมุนไปทางขวาเลื่อนบิตของตัวถูกดำเนินการทั้งหมดที่เดียวไปทางขวาพกไปที่บิต 7, บิต 0 ไปเพื่อดำเนินการ- Opcodes: ทันที:
58
, สัมบูรณ์:5a
, จัดทำดัชนี:5c
- ธง:
Z
,N
,C
- Opcodes: ทันที:
ROL
- หมุนไปทางซ้ายเลื่อนบิตทั้งหมดของตัวถูกดำเนินการไปทางซ้ายหนึ่งจุดไปยังบิต 0, บิต 7 ไปสู่การถือ- Opcodes: ทันที:
60
, สัมบูรณ์:62
, จัดทำดัชนี:64
- ธง:
Z
,N
,C
- Opcodes: ทันที:
ADC
- เพิ่มด้วยการดำเนินการ, ตัวถูกดำเนินการบวกการดำเนินการเพิ่มไปยังA
การดำเนินการตั้งอยู่บนล้น- Opcodes: ทันที:
68
, สัมบูรณ์:6a
, จัดทำดัชนี:6c
- ธง:
Z
,N
,C
- Opcodes: ทันที:
INC
- ตัวถูกดำเนินการที่เพิ่มขึ้นหนึ่ง- Opcodes: ทันที:
78
, สัมบูรณ์:7a
, จัดทำดัชนี:7c
- ธง:
Z
,N
- Opcodes: ทันที:
DEC
- ตัวถูกดำเนินการลดลงหนึ่ง- Opcodes: ทันที:
80
, สัมบูรณ์:82
, จัดทำดัชนี:84
- ธง:
Z
,N
- Opcodes: ทันที:
CMP
- เปรียบเทียบA
กับตัวถูกดำเนินการโดยการลบตัวถูกดำเนินการจากA
ลืมผลลัพธ์ Carry ถูกลบล้างอันเดอร์โฟลว์หรือไม่- Opcodes: ทันที:
88
, สัมบูรณ์:8a
, จัดทำดัชนี:8c
- ธง:
Z
,N
,C
- Opcodes: ทันที:
CPX
- เทียบX
- เช่นเดียวCMP
สำหรับX
- Opcodes: ทันที:
90
, สัมบูรณ์:92
, จัดทำดัชนี:94
- ธง:
Z
,N
,C
- Opcodes: ทันที:
HLT
- ยุติ- Opcodes: โดยนัย:
c0
- Opcodes: โดยนัย:
INX
- เพิ่มขึ้นทีละX
หนึ่ง- Opcodes: โดยนัย:
c8
- ธง:
Z
,N
- Opcodes: โดยนัย:
DEX
- ลดลงX
หนึ่ง- Opcodes: โดยนัย:
c9
- ธง:
Z
,N
- Opcodes: โดยนัย:
SEC
- ตั้งธงพก- Opcodes: โดยนัย:
d0
- ธง:
C
- Opcodes: โดยนัย:
CLC
- ธงพกพาที่ชัดเจน- Opcodes: โดยนัย:
d1
- ธง:
C
- Opcodes: โดยนัย:
BRA
- สาขาเสมอ- Opcodes: ญาติ:
f2
- Opcodes: ญาติ:
BNE
- สาขาถ้าZ
ล้างธง- Opcodes: ญาติ:
f4
- Opcodes: ญาติ:
BEQ
- สาขาถ้าZ
ตั้งค่าสถานะ- Opcodes: ญาติ:
f6
- Opcodes: ญาติ:
BPL
- สาขาถ้าN
ล้างธง- Opcodes: ญาติ:
f8
- Opcodes: ญาติ:
BMI
- สาขาถ้าN
ตั้งค่าสถานะ- Opcodes: ญาติ:
fa
- Opcodes: ญาติ:
BCC
- สาขาถ้าC
ล้างธง- Opcodes: ญาติ:
fc
- Opcodes: ญาติ:
BCS
- สาขาถ้าC
ตั้งค่าสถานะ- Opcodes: ญาติ:
fe
- Opcodes: ญาติ:
opcodes
พฤติกรรมของ VM นั้นไม่ได้กำหนดไว้หากพบว่ามี opcode ที่ไม่ได้จับคู่กับคำสั่งที่ถูกต้องจากรายการด้านบน
ตามคำขอของ Jonathan Allanคุณสามารถเลือก opcodes ของคุณเองแทน opcodes ที่แสดงในหัวข้อคำแนะนำ หากคุณทำเช่นนั้นคุณจะต้องเพิ่มการจับคู่แบบเต็มใน opcode ที่ใช้ด้านบนในคำตอบของคุณ
การจับคู่ควรเป็นไฟล์เลขฐานสิบหกที่มีคู่<official opcode> <your opcode>
เช่นหากคุณแทนที่ opcodes สองรายการ:
f4 f5
10 11
บรรทัดใหม่ไม่สำคัญที่นี่
กรณีทดสอบ (opcodes อย่างเป็นทางการ)
// some increments and decrements
pc: 0
ram: 10 10 7a 01 c9 f4 fb
output: 10 20 7a 01 c9 f4 fb
// a 16bit addition
pc: 4
ram: e0 08 2a 02 02 00 6a 02 0a 00 02 01 6a 03 0a 01
output: 0a 0b 2a 02 02 00 6a 02 0a 00 02 01 6a 03 0a 01
// a 16bit multiplication
pc: 4
ram: 5e 01 28 00 10 10 4a 01 5a 00 fc 0d 02 02 d1 6a 21 0a 21 02 03 6a 22 0a 22 52
02 62 03 c9 f8 e6 c0 00 00
output: 00 00 00 00 10 10 4a 01 5a 00 fc 0d 02 02 d1 6a 21 0a 21 02 03 6a 22 0a 22 52
02 62 03 c9 f8 e6 c0 b0 36
ฉันอาจเพิ่มการทดสอบเพิ่มเติมในภายหลัง
การอ้างอิงและการทดสอบ
เพื่อช่วยในการทดลองของตัวเองนี่คือการดำเนินการอ้างอิงบางส่วน (โดยสิ้นเชิงที่ไม่ใช่กอล์ฟ) - มันสามารถส่งออกข้อมูลการติดตาม (รวมถึงคำแนะนำในการถอดประกอบ) ไปstderr
ที่
วิธีที่แนะนำในการรับแหล่งที่มา:
git clone https://github.com/zirias/gvm --branch challenge --single-branch --recurse-submodules
หรือสาขาชำระเงินchallenge
และทำgit submodule update --init --recursive
โคลนหลังจากเพื่อรับระบบสร้างที่กำหนดเองของฉัน
สร้างเครื่องมือด้วย GNU make (เพียงพิมพ์make
หรือgmake
ถ้าอยู่ในระบบของคุณการสร้างเริ่มต้นไม่ใช่ GNU)
การใช้งาน :gvm [-s startpc] [-h] [-t] [-c convfile] [-d] [-x] <initial_ram
-s startpc
- ตัวนับโปรแกรมเริ่มต้นเริ่มต้นที่0
-h
- อินพุตอยู่ในรูปแบบเลขฐานสิบหก (เป็นอย่างอื่นไบนารี)-t
- การดำเนินการติดตามไปที่stderr
-c convfile
- แปลง opcodes ตามแผนที่ที่กำหนดconvfile
-d
- ดัมพ์หน่วยความจำที่ได้นั้นเป็นข้อมูลไบนารี่-x
- ถ่ายโอนข้อมูลหน่วยความจำที่เกิดเป็น hexinitial_ram
- เนื้อหา RAM เริ่มต้นไม่ว่าจะเป็นฐานสิบหกหรือไบนารี
หมายเหตุคุณลักษณะการแปลงจะล้มเหลวในโปรแกรมที่ปรับเปลี่ยน opcodes ในขณะที่ทำงาน
คำเตือน:กฎและรายละเอียดด้านบนมีอำนาจสำหรับความท้าทายไม่ใช่เครื่องมือนี้ โดยเฉพาะอย่างยิ่งนี้ใช้กับคุณสมบัติการแปลง opcode หากคุณคิดว่าเครื่องมือที่นำเสนอที่นี่มีข้อผิดพลาด wrt รายละเอียดโปรดรายงานในความคิดเห็น :)
BRA
(สาขา "เสมอ") ไม่แนะนำสาขาในการควบคุมการไหลไม่ควรมันจะเรียกว่าJMP
?
BRA
มีอยู่ในการออกแบบชิปในภายหลัง (6502 ไม่มีคำสั่งดังกล่าว) เช่น 65C02 และ MC 68000 JMP
มีอยู่เช่นกัน ความแตกต่างคือการBRA
ใช้การกำหนดที่อยู่แบบสัมพันธ์และJMP
ใช้การกำหนดที่อยู่แบบสัมบูรณ์ ดังนั้นฉันเพิ่งทำตามการออกแบบเหล่านี้ - แน่นอนว่ามันฟังดูไม่สมเหตุสมผลเลย)