如何检查字符是否是汇编中的字母?

时间:2015-08-05 05:56:49

标签: assembly x86

所以,我有一个代码块,用于设置bounders来检查一个字符是否是一个字母(不是数字,而不是符号),但我认为它不适用于大小写之间的字符。你能帮我吗?谢谢!

mov al, byte ptr[esi + ecx]; move the first character to al
cmp al, 0                  ; compare al with null which is the end of string
je done                    ; if yes, jump to done
cmp al, 0x41               ; compare al with "A" (upper bounder)
jl next_char               ; jump to next character if less
cmp al, 0x7A               ; compare al with "z" (lower bounder)
jg next_char               ; jump to next character if greater
//do something if it's a letter
next_char:
//do something different

4 个答案:

答案 0 :(得分:4)

你可以或每个角色0x20;这将使大写字母为小写(并用其他非字母字符替换非字母字符):

...
je done       ; This is your existing code
or al, 0x20   ; <-- This line is new!
cmp al, 0x41  ; This is your existing code again
...

注意:如果你的代码应该使用0x7F以上的字母(如“Ä”,“Ó”,“Ñ”),它将变得非常复杂。在这种情况下的一个问题是这些字符的ASCII码在Windows控制台程序(例如:“Ä”= 0x8E)和Windows GUI程序(“Ä”= 0xC4)中是不同的,在其他操作系统中甚至可能不同。 ..

答案 1 :(得分:1)

您的评论与代码不符。与代码实际执行的内容不匹配的注释是asm中常见的一种错误。

0x41 == 'A'是,而不是a0x7A == 'z'NASM syntax even allows character constants like C,所以你可以写

cmp al, 'A'

然后你甚至不需要评论这条线。

另一种错误是评论没有描述所需任务的工作算法。您也遇到此问题:'Z''a'之间存在非字母字符。

您可以通过

提高代码效率
            dec ecx
ALIGN 16
next_char:  inc ecx
            mov al, byte ptr[esi + ecx]; move al to the first character
            test al, al  ; test for zero (string terminator)
            jz done      ; if yes, jump to done.  (jz and je are the same instruction)
            ... 

以这种方式编写(在循环顶部使用next_char标签)在底部保存jmp。循环中的指令越少=越好。这些天写作的唯一要点就是表现,所以从一开始就学习这样的好技术是有意义的,如果不是太混乱的话。没有asm回答可以通过指向http://agner.org/optimize/的链接完成。

ascii(1)的输出:

Dec Hex    Dec Hex    Dec Hex  Dec Hex  Dec Hex  Dec Hex   Dec Hex   Dec Hex  
  0 00 NUL  16 10 DLE  32 20    48 30 0  64 40 @  80 50 P   96 60 `  112 70 p
  1 01 SOH  17 11 DC1  33 21 !  49 31 1  65 41 A  81 51 Q   97 61 a  113 71 q
  2 02 STX  18 12 DC2  34 22 "  50 32 2  66 42 B  82 52 R   98 62 b  114 72 r
  3 03 ETX  19 13 DC3  35 23 #  51 33 3  67 43 C  83 53 S   99 63 c  115 73 s
  4 04 EOT  20 14 DC4  36 24 $  52 34 4  68 44 D  84 54 T  100 64 d  116 74 t
  5 05 ENQ  21 15 NAK  37 25 %  53 35 5  69 45 E  85 55 U  101 65 e  117 75 u
  6 06 ACK  22 16 SYN  38 26 &  54 36 6  70 46 F  86 56 V  102 66 f  118 76 v
  7 07 BEL  23 17 ETB  39 27 '  55 37 7  71 47 G  87 57 W  103 67 g  119 77 w
  8 08 BS   24 18 CAN  40 28 (  56 38 8  72 48 H  88 58 X  104 68 h  120 78 x
  9 09 HT   25 19 EM   41 29 )  57 39 9  73 49 I  89 59 Y  105 69 i  121 79 y
 10 0A LF   26 1A SUB  42 2A *  58 3A :  74 4A J  90 5A Z  106 6A j  122 7A z
 11 0B VT   27 1B ESC  43 2B +  59 3B ;  75 4B K  91 5B [  107 6B k  123 7B {
 12 0C FF   28 1C FS   44 2C ,  60 3C <  76 4C L  92 5C \  108 6C l  124 7C |
 13 0D CR   29 1D GS   45 2D -  61 3D =  77 4D M  93 5D ]  109 6D m  125 7D }
 14 0E SO   30 1E RS   46 2E .  62 3E >  78 4E N  94 5E ^  110 6E n  126 7E ~
 15 0F SI   31 1F US   47 2F /  63 3F ?  79 4F O  95 5F _  111 6F o  127 7F DEL

答案 2 :(得分:0)

你需要有一个逻辑,它结合了多个条件,类似于&#34; C&#34;声明:if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))

你可以这样做:

...
je done                    ; if yes, jump to done
cmp al, 0x41               ; compare al with "A"
jl next_char               ; jump to next character if less
cmp al, 0x5A               ; compare al with "Z"
jle found_letter           ; if al is >= "A" && <= "Z" -> found a letter
cmp al, 0x61               ; compare al with "a"
jl next_char               ; jump to next character if less (since it's between "Z" & "a")
cmp al, 0x7A               ; compare al with "z"
jg next_char               ; above "Z" -> not a character
found_letter:
// ...
next_char:
// ...

答案 3 :(得分:-1)

此函数采用字符串,并使用ascii表值确定它是大写字符还是小写字符。 CMP-> BLS和CMP-> BLI指令可以确定是大写还是小写字符。如果小写字符为char,此后的代码将大写。

__asm void my_capitalize(char *str)
{
cap_loop
        LDRB r1, [r0] ; Load byte into r1 from memory pointed to by r0 (str pointer)
        CMP r1, #'a'-1 ; compare it with the character before 'a'
        BLS cap_skip ; If byte is lower or same, then skip this byte
        CMP r1, #'z' ; Compare it with the 'z' character
        BHI cap_skip ; If it is higher, then skip this byte
        SUBS r1,#32 ; Else subtract out difference to capitalize it
        STRB r1, [r0] ; Store the capitalized byte back in memory
cap_skip
        ADDS r0, r0, #1 ; Increment str pointer
        CMP r1, #0 ; Was the byte 0?
        BNE cap_loop ; If not, repeat the loop
        BX lr ; Else return from subroutine
}