6502芯片:字符分类(Character Classifica

2021-05-25  本文已影响0人  苹果王子刘泽庆

标准的C库提供了一组用于分类(例如是字母,是数字,是ASCII,是大写,等等)和修改(例如变成大写和小写)定义在标题中称为<ctype.h>的字符的函数。本节描述如何在6502汇编程序中编码一组类似的功能。有两种技术可以用于解决这个问题,即比较或查找表。

注意:这些函数将仅限于普通ASCII字符范围00-7F。

实现字符分类所需的查找表需要每个字符一个字节。查找表中的位表示字符是如何分类的(例如,控制字符、可打印字符、空格、十进制数字、十六进制数字、标点、大写字母或小写字母)。为了测试一个字符的特定分类,你可以从表中加载它的描述字节,并测试是否存在某些位(例如用AND 指令)。

; Constants describing the role of each classification bit
_CTL    EQU $80
_PRN    EQU $40
_WSP    EQU $20
_PCT    EQU $10
_UPR    EQU $08
_LWR    EQU $04
_DGT    EQU $02
_HEX    EQU $01

; Test if the character in A is a control character
ISCNTRL TAX
    LDA #_CTL
    BNE TEST

; Test if the character in A is printable
ISPRINT TAX
    LDA #_PRN
    BNE TEST

; Test if the character in A is punctation
ISPUNCT TAX
    LDA #_PCT
    BNE TEST

; Test if the character in A is upper case
ISUPPER TAX
    LDA #_UPR
    BNE TEST

; Test if the character in A is lower case
ISLOWER TAX
    LDA #_LWR
    BNE TEST

; Test if the character in A is a letter
ISALPHA TAX
    LDA #_UPR|_LWR
    BNE TEST

; Test if the character in A is a decimal digit
ISDIGIT TAX
    LDA #_DGT
    BNE TEST

; Test if the character in A is a hexadecimal digit
ISXDIGIT TAX
    LDA #_HEX
    BNE TEST

; Test if the character in A is letter or a digit
ISALNUM TAX
    LDA #_DGT|_UPR|_LWR

; Tests for the required bits in the look up table value
TEST    AND CTYPE,X
    BEQ FAIL

; Set the carry flag if any target bits were found
PASS    TXA
    SEC
    RTS

; Test if the character in A is in the ASCII range $00-$7F
ISASCII TAX
    BPL PASS

; Clear the carry flag if no target bits were found
FAIL    TXA
    CLC
    RTS

; If A contains a lower case letter convert it to upper case
TOUPPER JSR ISLOWER
    BCC *+4
    AND #$DF
    RTS

; If A contains an upper case letter convert it to lower case
TOLOWER JSR ISUPPER
    BCC *+4
    ORA #$20
    RTS

; The lookup table of character descriptions
CTYPE   DB  _CTL        ; NUL
    DB  _CTL        ; SOH
    DB  _CTL        ; STX
    DB  _CTL        ; ETX
    DB  _CTL        ; EOT
    DB  _CTL        ; ENQ
    DB  _CTL        ; ACK
    DB  _CTL        ; BEL
    DB  _CTL        ; BS
    DB  _CTL|_WSP       ; TAB
    DB  _CTL|_WSP       ; LF
    DB  _CTL|_WSP       ; VT
    DB  _CTL|_WSP       ; FF
    DB  _CTL|_WSP       ; CR
    DB  _CTL        ; SO
    DB  _CTL        ; SI
    DB  _CTL        ; DLE
    DB  _CTL        ; DC1
    DB  _CTL        ; DC2
    DB  _CTL        ; DC3
    DB  _CTL        ; DC4
    DB  _CTL        ; NAK
    DB  _CTL        ; SYN
    DB  _CTL        ; ETB
    DB  _CTL        ; CAN
    DB  _CTL        ; EM
    DB  _CTL        ; SUB
    DB  _CTL        ; ESC
    DB  _CTL        ; FS
    DB  _CTL        ; GS
    DB  _CTL        ; RS
    DB  _CTL        ; US
    DB  _PRN|_WSP       ; SPACE
    DB  _PRN|_PCT       ; !
    DB  _PRN|_PCT       ; "
    DB  _PRN|_PCT       ; #
    DB  _PRN|_PCT       ; $
    DB  _PRN|_PCT       ; %
    DB  _PRN|_PCT       ; &
    DB  _PRN|_PCT       ; '
    DB  _PRN|_PCT       ; (
    DB  _PRN|_PCT       ; )
    DB  _PRN|_PCT       ; *
    DB  _PRN|_PCT       ; +
    DB  _PRN|_PCT       ; ,
    DB  _PRN|_PCT       ; -
    DB  _PRN|_PCT       ; .
    DB  _PRN|_PCT       ; /
    DB  _PRN|_DGT|_HEX  ; 0
    DB  _PRN|_DGT|_HEX  ; 1
    DB  _PRN|_DGT|_HEX  ; 2
    DB  _PRN|_DGT|_HEX  ; 3
    DB  _PRN|_DGT|_HEX  ; 4
    DB  _PRN|_DGT|_HEX  ; 5
    DB  _PRN|_DGT|_HEX  ; 6
    DB  _PRN|_DGT|_HEX  ; 7
    DB  _PRN|_DGT|_HEX  ; 8
    DB  _PRN|_DGT|_HEX  ; 9
    DB  _PRN|_PCT       ; :
    DB  _PRN|_PCT       ; ;
    DB  _PRN|_PCT       ; <
    DB  _PRN|_PCT       ; =
    DB  _PRN|_PCT       ; >
    DB  _PRN|_PCT       ; ?
    DB  _PRN|_PCT       ; @
    DB  _PRN|_UPR|_HEX  ; A
    DB  _PRN|_UPR|_HEX  ; B
    DB  _PRN|_UPR|_HEX  ; C
    DB  _PRN|_UPR|_HEX  ; D
    DB  _PRN|_UPR|_HEX  ; E
    DB  _PRN|_UPR|_HEX  ; F
    DB  _PRN|_UPR       ; G
    DB  _PRN|_UPR       ; H
    DB  _PRN|_UPR       ; I
    DB  _PRN|_UPR       ; J
    DB  _PRN|_UPR       ; K
    DB  _PRN|_UPR       ; L
    DB  _PRN|_UPR       ; M
    DB  _PRN|_UPR       ; N
    DB  _PRN|_UPR       ; O
    DB  _PRN|_UPR       ; P
    DB  _PRN|_UPR       ; Q
    DB  _PRN|_UPR       ; R
    DB  _PRN|_UPR       ; S
    DB  _PRN|_UPR       ; T
    DB  _PRN|_UPR       ; U
    DB  _PRN|_UPR       ; V
    DB  _PRN|_UPR       ; W
    DB  _PRN|_UPR       ; X
    DB  _PRN|_UPR       ; Y
    DB  _PRN|_UPR       ; Z
    DB  _PRN|_PCT       ; [
    DB  _PRN|_PCT       ; \
    DB  _PRN|_PCT       ; ]
    DB  _PRN|_PCT       ; ^
    DB  _PRN|_PCT       ; _
    DB  _PRN|_PCT       ; `
    DB  _PRN|_LWR|_HEX  ; a
    DB  _PRN|_LWR|_HEX  ; b
    DB  _PRN|_LWR|_HEX  ; c
    DB  _PRN|_LWR|_HEX  ; d
    DB  _PRN|_LWR|_HEX  ; e
    DB  _PRN|_LWR|_HEX  ; f
    DB  _PRN|_LWR       ; g
    DB  _PRN|_LWR       ; h
    DB  _PRN|_LWR       ; i
    DB  _PRN|_LWR       ; j
    DB  _PRN|_LWR       ; k
    DB  _PRN|_LWR       ; l
    DB  _PRN|_LWR       ; m
    DB  _PRN|_LWR       ; n
    DB  _PRN|_LWR       ; o
    DB  _PRN|_LWR       ; p
    DB  _PRN|_LWR       ; q
    DB  _PRN|_LWR       ; r
    DB  _PRN|_LWR       ; s
    DB  _PRN|_LWR       ; t
    DB  _PRN|_LWR       ; u
    DB  _PRN|_LWR       ; v
    DB  _PRN|_LWR       ; w
    DB  _PRN|_LWR       ; x
    DB  _PRN|_LWR       ; y
    DB  _PRN|_LWR       ; z
    DB  _PRN|_PCT       ; {
    DB  _PRN|_PCT       ; |
    DB  _PRN|_PCT       ; }
    DB  _PRN|_PCT       ; ~
    DB  _CTL        ; DE

如果我们使用比较,那么每个函数将由若干个比较阶段组成,以确定所提供的字符是否有适当的值。在大多数情况下,这些功能都很小,但其中的一两个可能涉及到很多阶段(例如标点符号)。执行时间将根据字符所受测试的次数而变化。

ISUPPER CMP #'A'
    BCC FAIL
    CMP #'Z'+1
    BCS FAIL
    ; Drop thru here on success

ISLOWER CMP #'a'
    BCC FAIL
    CMP #'z'+1
    BCS FAIL
    ; Drop thru here on success

ISALPHA CMP #'A'
    BCC FAIL
    CMP #'Z'+1
    BCC PASS
    CMP #'a'
    BCC FAIL
    CMP #'z'+1
    BCS FAIL
PASS    EQU *
    ; Drop thru here on success

究竟哪种解决方案最好?在很多情况下,它取决于我们所要编写的程序。如果您只需要一个或两个测试,并且内存大小是个问题,那么比较方法将生成更少的代码,但可能会稍微慢一些(对于复杂的测试),否则查找表是简单和快速的。

上一篇下一篇

猜你喜欢

热点阅读