[ บทความ : เรียนรู้ z80 ] ตอนที่ 10 เรื่อง คำสั่งค้นหาข้อมูลในหน่วยความจำ |
เรียนรู้ Z80 ตอนที่ 10
คำสั่งค้นหาข้อมูลในหน่วยความจำ
จากสัปดาห์ที่แล้ว เราได้ศึกษาเรื่อง คำสั่งค้นหาข้อมูล ในหน่วยความจำ (แบบเป็นกลุ่ม) ไปแล้ว คราวนี้เราก็ มาดูถึง คำสั่งอีกชุดหนึ่งที่ทำหน้าที่คล้ายๆ กับเรื่องที่แล้ว นั่นก็คือ การค้นหาข้อมูล หรือจะเรียกว่าเป็นการเปรียบเทียบข้อมูล ในรีจิสเตอร์ กับข้อมูลในหน่วยความจำที่เราต้องการ ... คำสั่ง ดังกล่าวคือ CPI, CPIR, CPD, และ CPDR ... (คุ้นไหม) ... ซึ่งรูปแบบของคำสั่งจะเป็นดังนี้ครับ
ตาราง 10-1 ชุดคำสั่งสำหรับ ค้นหาข้อมูลแบบกลุ่ม
Instruction Source/Target Flag Operation CPD ไม่มี C
Z (=1 if A=[HL])
H, P/V (=0 if BC=0, =1 if BC <>0)
S (=1 if A < [HL])
N(=1)HL <- HL-1
BC <- BC-1
CPDR ไม่มี C
Z (=1 if A=[HL])
H, P/V (=0 if BC=0, =1 if BC <>0)
S (=1 if A < [HL])
N(=1)เหมือน CPD แต่ว่า คำสั่งนี้ จะทำการเปรียบเทียบข้อมูล ไปเรื่อยๆ จนกว่า BC จะเป็น 0 หรือ A=[HL] CPI ไม่มี C
Z (=1 if A=[HL])
H, P/V (=0 if BC=0, =1 if BC <>0)
S (=1 if A < [HL])
N(=1)HL <- HL+1
BC <- BC-1CPIR ไม่มี C
Z (=1 if A=[HL])
H, P/V (=0 if BC=0, =1 if BC <>0)
S (=1 if A < [HL])
N(=1)เหมือน CPI แต่ว่า คำสั่งนี้ จะทำการเปรียบเทียบข้อมูล ไปเรื่อยๆ จนกว่า BC จะเป็น 0 หรือ A=[HL] หมายเหตุ เราต้องเก็บค่าที่เราต้องการค้นหาใน A, เก็บจำนวนครั้งที่ต้องการค้นหาใน BC และ ตำแหน่งเริ่มต้นค้นหาใน HL
ส่วนความแตกต่างระหว่าง CPD กับ CPDR และ CPI กับ CPIR ก็คือ CPD / CPI จะทำเพียงครั้งเดียว แต่ CPDR/ CPIR จะทำเรื่อยๆ จนกว่า BC เป็น 0 หรือ เจอข้อมูลที่จ้องการ ... มาดูตัวอย่างโปรแกรมสำหรับ คำสั่งที่เกี่ยวกับ การแลกเปลี่ยนข้อมูล กันครับ ...
; ; Filename : TCPEx.asz ; Author : Supachai Budsaratij (raek@se-ed.net) ; Date : Feb 19, 2001 ; Hardware : ET-Board V6 (Z80 Mode) ; CP-jr180 (Z180) ; ET-Board V5 (Z180) ; ET-Board V3.5 New Power (Z80) ; ; INCL "etv6.inz" ; Inlude header for ET-V6 ; INCL "etv35.inz" ; Inlude header for ET-V3.5 ; INCL "jr180.inz" ; Inlude header for CP-jr180 ORG UMEM_ORG ; Start at UMEM_ORG main: LD HL,UMEM_ORG+1000h ; Start search at UMEM_ORG+1000h LD A,7 ; Find 7 LD BC,10 ; Do 10 times. CPIR LD HL,UMEM_ORG+1000h ; Start search at UMEM_ORG+1000h LD A,20 ; Find 20 LD BC,10 ; Do 10 times. CPDR HALT ORG UMEM_ORG+1000h data db 1,2,3,4,5,6,7,8,9,10 ENDเมื่อเราทำการแปลคำสั่งเรียบร้อยแล้ว เราก็จะได้ไฟล์ .LST ดังนี้
; ; Filename : TCPEx.asz ; Author : Supachai Budsaratij (raek@se-ed.net) ; Date : Feb 19, 2001 ; Hardware : ET-Board V6 (Z80 Mode) ; CP-jr180 (Z180) ; ET-Board V5 (Z180) ; ET-Board V3.5 New Power (Z80) ; ; INCL "etv6.inz" ; Inlude header for ET-V6 ; ; filename : etv6.inz ; assembler : az80 ; author : Supachai Budsaratij (raek@se-ed.net) ; hardware : et-board 6 (Z-80 mode) ; date : October 12,2000 ; ; --- MEMORY ; 8000 UMEM_ORG EQU 08000h ; User RAM start bdff UMEM_END EQU 0BDFFh ; User RAM end c000 XMEM_ORG EQU 0C000h ; Expand RAM end dfff XMEM_END EQU 0DFFFh ; Expand RAM end ; --- I/O ; 0000 S8255_PA EQU 00h ; System 8255 port A 0001 S8255_PB EQU 01h ; System 8255 port B 0002 S8255_PC EQU 02h ; System 8255 port C 0003 S8255_CT EQU 03h ; System 8255 control port ; 0020 U8255_PA EQU 20h ; User 8255 port A 0021 U8255_PB EQU 21h ; User 8255 port B 0022 U8255_PC EQU 22h ; User 8255 port C 0023 U8255_CT EQU 23h ; User 8255 control port ; 004d SCN_INP EQU 4Dh ; SCN2681 - Input port (Switch) 004e SCN_SEO EQU 4Eh ; SCN2681 - Set output port (LED) 004f SCN_REO EQU 4Fh ; SCN2681 - Reset output port (LED) ; 0060 CLCD_WC EQU 60h ; Character LCD write command 0061 CLCD_RC EQU 61h ; Character LCD read command 0062 CLCD_WD EQU 62h ; Character LCD write data 0063 CLCD_RD EQU 63h ; Character LCD read data ; 0064 GLCD_WC1 EQU 64h ; Graphics LCD write command (Page 1) 0065 GLCD_RC1 EQU 65h ; Graphics LCD read command (Page 1) 0066 GLCD_WD1 EQU 66h ; Graphics LCD write data (Page 1) 0067 GLCD_RD1 EQU 67h ; Graphics LCD read data (Page 1) ; 0068 GLCD_WC2 EQU 68h ; Graphics LCD write command (Page 2) 0069 GLCD_RC2 EQU 69h ; Graphics LCD read command (Page 2) 006a GLCD_WD2 EQU 6Ah ; Graphics LCD write data (Page 2) 006b GLCD_RD2 EQU 6Bh ; Graphics LCD read data (Page 2) ; ; INCL "etv35.inz" ; Inlude header for ET-V3.5 ; INCL "jr180.inz" ; Inlude header for CP-jr180 8000 ORG UMEM_ORG ; Start at UMEM_ORG 8000 main: 8000 21 00 90 LD HL,UMEM_ORG+1000h ; Start search at UMEM_ORG+1000h 8003 3e 07 LD A,7 ; Find 7 8005 01 0a 00 LD BC,10 ; Do 10 times. 8008 ed b1 CPIR 800a 21 00 90 LD HL,UMEM_ORG+1000h ; Start search at UMEM_ORG+1000h 800d 3e 14 LD A,20 ; Find 20 800f 01 0a 00 LD BC,10 ; Do 10 times. 8012 ed b9 CPDR 8014 76 HALT 9000 ORG UMEM_ORG+1000h 9000 01 02 03 04 data db 1,2,3,4,5,6,7,8,9,10 9004 05 06 07 08 9008 09 0a 900a END 0061 CLCD_RC 0063 CLCD_RD 0060 CLCD_WC 0062 CLCD_WD 0065 GLCD_RC1 0069 GLCD_RC2 0067 GLCD_RD1 006b GLCD_RD2 0064 GLCD_WC1 0068 GLCD_WC2 0066 GLCD_WD1 006a GLCD_WD2 0003 S8255_CT 0000 S8255_PA 0001 S8255_PB 0002 S8255_PC 004d SCN_INP 004f SCN_REO 004e SCN_SEO 0023 U8255_CT 0020 U8255_PA 0021 U8255_PB 0022 U8255_PC bdff UMEM_END 8000 UMEM_ORG dfff XMEM_END c000 XMEM_ORG 9000 data 8000 mainส่วนรายละเอียดของไฟล์ฐานสิบหก ก็จะเป็นดังนี้ครับ
:158000002100903E07010A00EDB12100903E14010A00EDB976A2 :0A9000000102030405060708090A2F :00900A0165มา debug กันดีกว่าครับ เริ่มตั้งแต่โหลดโปรแกรมเลยนะครับ
แล้วก็เริ่ม trace ด้วยคำสั่ง t 8000 ... คำสั่งแรกเป็นการนำค่า 9000h ไปเก็บใน HL
ต่อมาเราก็นำค่า 7 ไปเก็บใน A ซึ่งมีความหมายว่า เราต้องการค้นหาข้อมูล ที่มีค่า 7
กำหนดให้ BC เป็น 10 เพื่อกำหนดว่า เราจะทำการค้นหากัน 10 ครั้ง
เริ่มการค้นหาด้วย CPIR ซึ่งผลลัพธ์ ออกมาเป็นดังนี้ HL = 9007 เพราะทำไป 7 ครั้ง ... ซึ่งแสดงว่า เราน่าจะเจอข้อมูล หลังจากที่ ทำการเปรียบเทียบไปแล้ว 7 ครั้ง (เพราะเราสั่งให้ทำ 10 ครั้งไง ... แต่ HL ไม่เป็น 900Ah ก็หมายความว่า เจอข้อมูลก่อนไง) ... และ BC เป็น 3 เพราะ ทำไปแค่ 7 ครั้ง .. ส่วน Flag มันก็บอกว่า Z=1 และ S=0 ซึ่ง กรณีที่ Z=1 และ S=0 ก็คือ กรณี ที่ ข้อมูลใน A เท่ากับ ข้อมูลที่ HL ชี้อยู่ ...
คราวนี้ลองให้ HL เป็น 900Ah ดูบ้าง
คราวนี้เราจะหา 14h กันล่ะ
ทำ 10 ครั้งเหมือนเดิม
เอาล่ะ ลองหาแบบ CPDR กันบ้าง ... คราวนี้ผลลัพธ์ คือ HL = 9000h ซึ่ง น่าจะ หมายความว่า ทำไป 10 ครั้ง ... อ้าว BC ก็เป็น 0 เหมือนกัน เอ ... คราวนี้ตกลงว่าหาเจอไหมเนี่ย ... มาดู ที่ Flag กันครับ ... เราพบว่า Z=0 และ S=0 ซึ่ง ไม่ใช่กรณีของ ข้อมูล ใน A เหมือนกับ ข้อมูล ที่ชี้โดย HL ซึ่งหมายความว่า ... ไม่เจอ 14h ในหน่วยความจำตั้งแต่ 9000h-900Ah ...
อ๊ะ ... จบโปรแกรมแล้ว ล่ะ
เรียบร้อยครับ ... เราเรียนรู้เกี่ยวกับการแลกเปลี่ยนข้อมูล , การถ่ายโอนข้อมูล และการค้นหาข้อมูลไปเรียบร้อยแล้วล่ะ ... คราวหน้าเราก็จะศึกษาเกี่ยวกับ การบวก และการลบกันครับ ... แล้วตามด้วย การกระโดด แบบมีเงื่อนไข และไม่มีเงื่อนไขกันต่อ ... หลังจาก 2 เรื่องนี้ผ่านไป เราก็จะสามารถเขียนโปรแกรม ที่มีความซับซ้อนมากๆ ได้แล้วครับ ... เมื่อเริ่มเขียนแบบซับซ้อนได้ เราก็จะต่อ เกี่ยวกับคำสั่งกระทำทาง คำสั่ง I/O, ลอจิก, การกระทำกับบิต, การเลื่อน (shift) / การหมุน (Rotate) บิต, และคำสั่งพิเศษๆ พร้อมทั้ง เทคนิค การเขียนโปรแกรมแบบต่างๆ กับ Z80 กันต่อไป ... ส่วนหลังสุด อาจจะเป็น ข้อมูลเพิ่มเติมเกี่ยวกับ Z180 กัน เพื่อเปิดหูเปิดตาให้กว้าง และใช้ Z80 ในการเขียนโปรแกรมที่ซับซ้อนมากขึ้นเรื่อยๆ ...
นับวัน ผมยิ่งชอบ Z80/Z180 มากขึ้นแล้วสิครับ ... สนุกดีตรงที่มันให้เราเขียนเอง (...ฮา...) แต่ก็ต้องยอมรับครับ ... ส่วนมากผมใช้ MCS-51 แถมสอน หรือ อบรมสมาชิกชุมนุม ucRoboTics ด้วย MCS-51 กับ Micro-C51 อีกด้วย ... แถมหุ่น tracker line ของผม ก็เป็น MCS-51 กับ 68HC11 อีกต่างหากครับ ... อืม ... แล้ว Z80/Z180 ล่ะ ... ผมก็จะพยายาม ใช้มันให้มากขึ้นไงครับ ... และผมก็คงไม่มีบทความเกี่ยวกับ MCS-51 ที่ละเอียด แบบนี้แน่นอนครับ ... เพราะ มีอาจารย์หลายๆ ท่านได้ เขียนตำราเอาไว้มากมาย ... แถมเขียนได้ดีมากๆ ด้วยครับ ลองสืบเสาะหาเอาล่ะกันครับ ... สัปดหานี้เท่านี้ก่อนครับ สวัสดีครับ