如何检查字符是否介于0-9,A-Z和a-z之间?我了解您可以使用cmp字符,“ A”或cmp字符,“ 0”等。但是,如果我必须检查三个不同的范围,我该怎么做?
如果我需要检查'A'<= C <='Z',那么我必须先检查字符值是否低于A,然后再检查字符值是否小于或等于Z。但是由于0- A下方有9个,我如何在不弄乱逻辑的情况下解决这个问题? Z也一样,因为a-z高于Z。按照我的逻辑,到目前为止我已经发表过。我没有得到简单的东西感到很傻,但是我是一个初学者,并且我已经为此工作了几天,现在我不得不重新开始,所以任何帮助将不胜感激。
_asm
{
mov ecx, 127
mov esi, 0
mov ebx,LocalBuffer[esi] ;LocalBuffer is a c++ array
Loop1:
cmp ebx, 'a' ;ebx is the 0'th index value of LocalBuffer
jb notLowercase ;If character value is below 'a'
cmp ebx,'z'
jbe CharCount ;if it's less than or equal to 'z'
cmp ebx,'A'
jb notUpperCase ;If less than 'A', but then won't this discard 0-9?
cmp ebx,'Z'
jb CharCount ;If it's less than 'Z', but what about greater than Z?
cmp ebx,'0'
jb NotDigit ;If less than '0'
cmp ebx,'9'
jb CharCount ;What if it's greater than 9?
notLowerCase:
;DO I LOOP BACK TO LOOP1, MOVE ON TO THE NEXT CHARACTER OR SOMETHING ELSE?
notUpperCase:
;SAME ISSUE AS NotLowerCase
notDigit:
;SAME ISSUE AS LAST 2
CharCount:
;Do something
一种简单的方法是以升序(或降序)对范围进行排序。然后,您可以按[ON / OFF]样式使用cmp
:
mov ecx, 127 ; Check a 127 char string
mov esi, 0
Loop1:
movzx ebx, byte ptr LocalBuffer[esi] ; Load a byte from the address
cmp bl, '0' ; '0' = 48 - all lower values mask are NOT IN THE SET
jb notInSet ;
cmp bl,'9' ; '9' = 57 - all lower are IN THE SET
jbe CharCount ; It is a number
cmp bl,'A' ; 'A' = 65 - all lower are NOT IN THE SET
jb notInSet ; If less than 'A'
cmp bl,'Z' ; 'Z' = 90 - all lower are IN THE SET
jbe CharCount ; It is an uppercase char
cmp bl,'a' ; 'a' = 97 - all lower are NOT IN THE SET
jb NotInSet ;
cmp bl,'z' ; 'z' = 122 - all lower are IN THE SET
jbe CharCount ; It is a lowercase letter
; FALL THROUGH for greater values
notInSet:
inc esi
loop Loop1
jmp Final
CharCount:
; DO SOMETHING (that doesn't mess up ECX, ESI)
inc esi
loop Loop1
; FALL THROUGH to Final
Final:
; END of this snippet
如您所见,检查的值确实上升。例如,3
(= 51)的值将首先检查它是否低于48(=否),然后检查它是否低于57(= YES),因此进行第二次跳转。
一种替代方法是使用带有索引寻址的跳转表。在这种方法中,您将范围定义为布尔值表(0 = NotInSet,1 = CharCount):
针对您的方案,应该在.data
段中按如下方式设置表格(请注意0
和1
的交替值,上述的ON / OFF样式:]]
.data JumpTable db 48 dup(0), 10 dup(1), 7 dup(0), 26 dup(1), 7 dup(0), 26 dup(1), 133 dup(0)
然后代码看起来像这样:
mov ecx, 127 mov esi, 0 Loop1: movzx ebx, byte ptr LocalBuffer[esi] ; Load a byte from the address movzx eax, byte ptr JumpTable[ebx] ; Retrieve the ebx'th value of the table[ test eax, eax ; Check if it's zero jnz CharCount ; If it's not, it's a char, so jump to CharCount ; FALL THROUGH TO notInSet notInSet: inc esi loop Loop1 jmp Final CharCount: ; DO SOMETHING (that doesn't mess up ECX, ESI) inc esi loop Loop1 ; FALL THROUGH to Final Final: ; END of this snippet
该表具有256个值,整个ASCII范围为0或1。
在两种情况下,都可以在inc esi
读取值之后立即将movzx ebx, byte ptr LocalBuffer[esi]
移到开头。
首先,在修复How to load a single byte from address in assembly之前,您无法调试分支-您正在加载4个字节的字符,并将整个32位值与'a'
进行比较,依此类推。使用movzx
而不是movzx
,因为它是mov ebx, LocalBuffer[esi]
数组。