如何检查字符是否在特定的ASCII值范围内?

问题描述 投票:0回答:2

如何检查字符是否介于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


assembly x86 ascii masm range-checking
2个回答
1
投票

一种简单的方法是以升序(或降序)对范围进行排序。然后,您可以按[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段中按如下方式设置表格(请注意01的交替值,上述的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]移到开头。


0
投票

首先,在修复How to load a single byte from address in assembly之前,您无法调试分支-您正在加载4个字节的字符,并将整个32位值与'a'进行比较,依此类推。使用movzx而不是movzx,因为它是mov ebx, LocalBuffer[esi]数组。

© www.soinside.com 2019 - 2024. All rights reserved.