ข้อ 4 · 25 คะแนน — ข้อที่คะแนนเยอะที่สุด

หา Opcode และ Address ของโค้ดแต่ละคำสั่ง

ข้อนี้เป็นข้อที่เก็บคะแนนง่ายที่สุด เพราะอาจารย์แจกชีท Instruction Set ให้ในห้องสอบ ไม่ต้องท่อง แค่ต้องอ่านตารางให้เป็น นับไบต์ให้ถูก และไม่พลาดเรื่อง little-endian

4.1 อ่านชีท Instruction Set ให้เป็น

คอลัมน์ในชีทเรียงแบบนี้

คอลัมน์อ่านยังไง
Mnemonicชื่อคำสั่ง เช่น LD r, r′ — ตัวพิมพ์เล็ก r, n, dd, cc คือ “ช่องว่าง” ที่เราต้องเติมเอง
Symbolic Operationความหมายทางคณิตศาสตร์ เช่น r ← r′
Flags• = ไม่กระทบ, 0 = เคลียร์, 1 = เซ็ต, ↕ = เปลี่ยนตามผลลัพธ์
Opcode 76 543 210คอลัมน์สำคัญที่สุด — เขียนบิตของ opcode โดยแบ่งเป็น 2-3-3 ตามฟิลด์ ตัวอักษรในนั้น (r, p, q, dd) ให้แทนด้วยรหัสจากตารางท้ายหน้า
Hexค่าฐานสิบหกสำหรับคำสั่งที่ไม่มีช่องว่างให้เติม ถ้ามี r/n จะเว้นว่างไว้
Bytesขนาดคำสั่ง — เอาไปบวก address ของบรรทัดถัดไป
M Cyclesจำนวน machine cycle — เอาไปใช้ในข้อ 5
T Statesจำนวน T-state — เอาไปคูณกับคาบ clock เป็นเวลา

ตัวอย่างการถอด: LD B, A

  1. หาแถวที่ตรงกับรูปแบบ LD r, r′ ⇒ opcode = 01 r r′
  2. เปิดตารางรหัส register (มุมขวาของชีท) B = 000, A = 111
  3. แทนค่าลงไป
      76   543  210
      01   000  111    ← r = B (ปลายทาง),  r′ = A (ต้นทาง)
    = 0100 0111
    = 47H
  4. อ่านคอลัมน์ที่เหลือ Bytes = 1, M cycles = 1, T states = 4
จำลำดับให้แม่น

ในรูปแบบ 01 d s ฟิลด์กลาง (บิต 5-4-3) คือ ปลายทาง ฟิลด์ล่าง (บิต 2-1-0) คือ ต้นทาง
LD B,A = 01 000 111 = 47H ส่วน LD A,B = 01 111 000 = 78H — คนละตัวกัน

4.2 ตารางรหัสที่ต้องใช้ตลอด

r, r′ — register 8 บิต

000B100H
001C101L
010D110(HL)
011E111A

110 คือ (HL) ไม่ใช่ register — จึงทำให้ LD (HL),(HL) ชนกับ HALT (76H) พอดี Zilog เลยยกให้เป็น HALT

dd / qq — register pair

รหัสddqq
00BCBC
01DEDE
10HLHL
11SPAF

dd ใช้กับ LD/INC/DEC/ADD HL — qq ใช้กับ PUSH/POP เท่านั้น ต่างกันที่ตัวสุดท้าย

cc — เงื่อนไข

000NZ100PO
001Z101PE
010NC110P
011C111M

ใช้กับ JP cc / CALL cc / RET cc
JR ใช้ได้แค่ 4 ตัวแรก (NZ, Z, NC, C)

รูปแบบ opcode ที่เจอบ่อย

รูปแบบบิตคำสั่งตัวอย่าง
01 d sLD r, r′LD B,A = 01 000 111 = 47H
00 r 110 + nLD r, nLD A,9FH = 00 111 110 = 3EH, 9F
00 dd0 001 + nnLD dd, nnLD HL,2100H = 00 100 001 = 21H, 00, 21
10 000 sADD A, rADD A,B = 10 000 000 = 80H
10 001 sADC A, rADC A,B = 88H
10 010 sSUB rSUB B = 90H
10 100 sAND rAND B = A0H
10 101 sXOR rXOR A = 10 101 111 = AFH
10 110 sOR rOR B = B0H
10 111 sCP rCP B = B8H
00 r 100INC rINC A = 00 111 100 = 3CH
00 r 101DEC rDEC A = 3DH
11 qq0 101PUSH qqPUSH BC = 11 000 101 = C5H
11 qq0 001POP qqPOP AF = 11 110 001 = F1H
11 cc 010 + nnJP cc, nnJP NZ,2000H = 11 000 010 = C2H, 00, 20

Prefix — เมื่อ 256 รหัสไม่พอ

Prefixใช้กับตัวอย่างผลต่อขนาด/เวลา
CBปรับบิต: BIT / SET / RES / RLC / RL / SRL …BIT 0,A = CB 47+1 ไบต์, มี M1 เพิ่มอีกรอบ
EDคำสั่งขยาย: LDIR, IN r,(C), OUT (C),r, NEG, IM …LDIR = ED B0+1 ไบต์, +4 T
DDเปลี่ยน HL เป็น IXLD A,(IX+5) = DD 7E 05+1 ไบต์ (+ displacement)
FDเปลี่ยน HL เป็น IYLD A,(IY+5) = FD 7E 05+1 ไบต์ (+ displacement)

Prefix แต่ละตัวทำให้เกิด M1 cycle เพิ่มอีกรอบ — ทำให้ IN r,(C) ใช้ 12 T ในขณะที่ IN A,(n) ใช้ 11 T ทั้งที่ดูเหมือนคล้ายกัน

4.3 นับ Address ให้ถูก

  1. เริ่มจากค่าใน ORG เช่น ORG 0000H ⇒ คำสั่งแรกอยู่ที่ 0000H
  2. address ของคำสั่งถัดไป = address ปัจจุบัน + จำนวนไบต์ของคำสั่งนี้ ห้ามลืมนับไบต์ operand
  3. ค่า 16 บิตเก็บแบบ little-endian ไบต์ต่ำอยู่ address น้อยกว่า
  4. Label ไม่กินที่ — LOOP: ไม่ใช่คำสั่ง แค่ตั้งชื่อให้ address ปัจจุบัน
  5. Directive ก็ไม่กินที่ cpu, hof, org, end เป็นคำสั่งสำหรับตัวแปลภาษา ไม่ใช่สำหรับ CPU ⇒ ไม่มี opcode และไม่มี address (ดูรายละเอียดว่ามันคืออะไร มาจากไหน)

คิด displacement ของ JR / DJNZ

d = address ปลายทาง − (address ของคำสั่ง JR + 2)

; เพราะ PC ถูกเพิ่มไปแล้ว 2 (ขนาดของคำสั่ง JR) ก่อนบวก d

ตัวอย่าง  200BH: LOOP: OUT (40H),A
          200EH:       JR LOOP

d = 200BH − (200EH + 2) = 200BH − 2010H = −5
−5 ในรูป two's complement 8 บิต = FBH
⇒ machine code = 18 FB

เครื่องคิด displacement

4.4 เครื่องมือถอดรหัส opcode

พิมพ์ opcode 1 ไบต์ (ฐานสิบหก) เพื่อดูว่ามันถูกแบ่งฟิลด์ยังไง และหมายความว่าอะไร

โจทย์หลัก — ตาราง Opcode + Address ของโค้ดในข้อ 3

โจทย์หลัก · 25 คะแนน

จงหา Opcode และ Address ของโค้ดแต่ละคำสั่งในข้อที่ 3

ดูเฉลย — พร้อมวิธีคิดทีละบรรทัด

โค้ดจากข้อ 3

        CPU  "z80.tbl"    ; directive — ไม่กิน address
        HOF  "INT8"        ; directive — ไม่กิน address
        ORG  0000H
START:  LD   SP, 1FFFH
        LD   HL, 1000H
MAIN:   IN   A, (84H)
        LD   (HL), A
        LD   A, (1000H)
        CPL
        OUT  (40H), A
        LD   B, 0FFH
DELAY:  DJNZ DELAY
        JR   MAIN
        HALT

ตารางคำตอบ

วิธีคิดของบรรทัดที่คนพลาดบ่อย

คำสั่งวิธีคิด
LD SP,1FFFH รูปแบบ 00 dd0 001 · dd ของ SP = 11 ⇒ 00 110 001 = 31H ตามด้วย FF 1F (ไบต์ต่ำก่อน)
LD HL,1000H dd ของ HL = 10 ⇒ 00 100 001 = 21H ตามด้วย 00 10
IN A,(84H) เป็นรหัสตายตัว DBH ตามด้วยเลขพอร์ต 84H · 2 ไบต์ 11 T
LD (HL),A รูปแบบ 01 110 r · r ของ A = 111 ⇒ 01 110 111 = 77H · 1 ไบต์ 7 T (2 machine cycle)
LD A,(1000H) รหัสตายตัว 3AH ตามด้วย 00 10 · 3 ไบต์ 13 T (4 machine cycle)
CPLรหัสตายตัว 2FH · 1 ไบต์ 4 T
OUT (40H),Aรหัสตายตัว D3H ตามด้วย 40H · 2 ไบต์ 11 T
LD B,0FFH รูปแบบ 00 r 110 · r ของ B = 000 ⇒ 00 000 110 = 06H ตามด้วย FFH
DJNZ DELAY รหัส 10H + displacement · คำสั่งอยู่ที่ 0011H ปลายทาง DELAY = 0011H
d = 0011H − (0011H + 2) = −2 = FEH ⇒ 10 FE (วนที่ตัวเอง)
JR MAIN รหัส 18H + displacement · คำสั่งอยู่ที่ 0013H ปลายทาง MAIN = 0006H
d = 0006H − (0013H + 2) = 0006H − 0015H = −15 = F1H ⇒ 18 F1
HALTรหัส 76H — ตรงกับช่อง LD (HL),(HL) ที่ไม่มีความหมาย
เช็กคำตอบด้วยการบวกกลับ

address สุดท้าย − address แรก ต้องเท่ากับผลรวมจำนวนไบต์ — ถ้าไม่ตรง แปลว่านับไบต์ผิดที่ใดที่หนึ่ง วิธีนี้จับ error ได้เร็วที่สุดในห้องสอบ

ลองแปลโค้ดของตัวเอง

ตัวอย่างเพิ่มอีก 5 ข้อ

ตัวอย่างที่ 1

จงหา opcode และ address ของโปรแกรมต่อไปนี้ (จากใบงาน Lab 1)

        CPU  "z80.tbl"
        HOF  "INT8"
        ORG  2000H
        LD   A, 1
        LD   B, 2
        LD   C, 8
        LD   D, 3
        ADD  A, B
        ADD  A, C
        ADD  A, D
        HALT
เฉลยตัวอย่างที่ 1

ตรงกับ Listing File ของ Lab 1 ทุกไบต์ · ผลลัพธ์ใน A = 1+2+8+3 = 14 = 0EH

ตัวอย่างที่ 2

จงหา opcode และ address ของโปรแกรมบวกเลขจากใบงาน Lab 2

        CPU  "z80.tbl"
        HOF  "INT8"
        ORG  200AH
        LD   HL, 2100H
        LD   DE, 2101H
        LD   A, (HL)
        LD   B, A
        LD   A, (DE)
        ADD  A, B
        INC  DE
        LD   (DE), A
        HALT
เฉลยตัวอย่างที่ 2
สังเกต

LD HL,2100H = 21 00 21 — ไบต์แรกคือ opcode 21H ไบต์ที่สองคือ 00H (ไบต์ต่ำของ 2100H) ไบต์ที่สามคือ 21H (ไบต์สูง) บังเอิญเลข 21 ซ้ำกันพอดี อย่าสับสน

ตัวอย่างที่ 3

จงหา opcode และ address ของโปรแกรม LED จากใบงาน Lab 2 และอธิบายว่าทำไม displacement ของ JR loop ถึงเป็น FBH

        CPU  "z80.tbl"
        HOF  "INT8"
        ORG  200AH
        XOR  A
loop:   OUT  (40H), A
        INC  A
        JR   loop
        HALT
เฉลยตัวอย่างที่ 3
คำสั่ง JR อยู่ที่ 200EH  ·  ปลายทาง loop = 200BH
d = 200BH − (200EH + 2) = 200BH − 2010H = −5
−5 → two's complement 8 บิต:  5 = 0000 0101
                       กลับบิต = 1111 1010
                          บวก 1 = 1111 1011 = FBH  ✓

ตรงกับ Listing File 200E 18FB ทุกประการ

ตัวอย่างที่ 4

จงหา opcode ของคำสั่งเหล่านี้จากรูปแบบบิต โดยไม่เปิดคอลัมน์ Hex: LD C,H · LD (HL),E · SUB (HL) · DEC L · PUSH AF · RET NC · JP PE,1234H

เฉลยตัวอย่างที่ 4
คำสั่งรูปแบบแทนค่าบิตHex
LD C,H01 d sC = 001, H = 10001 001 1004CH
LD (HL),E01 110 sE = 01101 110 01173H
SUB (HL)10 010 s(HL) = 11010 010 11096H
DEC L00 r 101L = 10100 101 1012DH
PUSH AF11 qq0 101AF = 1111 110 101F5H
RET NC11 cc 000NC = 01011 010 000D0H
JP PE,1234H11 cc 010 + nnPE = 10111 101 010EAH 34 12

สังเกต JP PE,1234H → operand เก็บเป็น 34 12 ไม่ใช่ 12 34

ตัวอย่างที่ 5 · ย้อนกลับ

โปรแกรมหนึ่งเริ่มที่ 1000H และมี machine code ต่อกันดังนี้ 3E 55 06 08 D3 40 3C 10 FC 76 จงถอดกลับเป็น assembly พร้อม address ของแต่ละคำสั่ง

เฉลยตัวอย่างที่ 5
AddressMachine codeInstructionวิธีถอด
1000H3E 55LD A,55H3E = 00 111 110 ⇒ LD r,n โดย r = 111 = A
1002H06 08LD B,08H06 = 00 000 110 ⇒ r = 000 = B
1004HD3 40OUT (40H),AD3 = รหัสตายตัวของ OUT (n),A
1006H3CINC A3C = 00 111 100 ⇒ INC r โดย r = 111 = A
1007H10 FCDJNZ 1005HFCH = −4 ⇒ ปลายทาง = 1007H + 2 + (−4) = 1005H
1009H76HALT76 = HALT
ข้อสังเกต

ปลายทางของ DJNZ คือ 1005H ซึ่งตกกลาง ๆ คำสั่ง D3 40 (คือไบต์ 40) — โปรแกรมนี้จะทำงานผิดพลาด เพราะ 40H = LD B,B ตัวอย่างนี้แสดงให้เห็นว่า displacement ผิดนิดเดียว โปรแกรมเปลี่ยนความหมายทั้งหมด

← ข้อ 3 · Assembly ข้อ 5 · Timing →