美文网首页
6502芯片:字符分类(Character Classifica

6502芯片:字符分类(Character Classifica

作者: 苹果王子刘泽庆 | 来源:发表于2021-05-25 08:19 被阅读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
    

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

    相关文章

      网友评论

          本文标题:6502芯片:字符分类(Character Classifica

          本文链接:https://www.haomeiwen.com/subject/cnvajltx.html