循环检查汇编中的小写字母

Loop to check lowercase letter in assembly

我正在编写一个循环作为更大程序的一部分,该程序检查第二个参数是否包含任何大写字母(如果是,程序退出)。这是我到目前为止所拥有的。我已经标记了我遇到问题的代码部分。

%include "asm_io.inc"
SECTION .data
err1: db "Incorrect number of command line arguments",10,0
err2: db "2nd argument lenght more than 20",10,0
err3: db "Upper-case letter found!!!",10,0
strt: db "ho",10,0

SECTION .bss
N: resd 1

SECTION .text 
    global  asm_main

asm_main:
   enter 0,0
   pusha

   mov eax, dword [ebp+8]
   cmp eax, dword 2
   jne ERR1

   mov ebx, dword [ebp+12]   ; 24 to 37 calculates the length of 2nd argument
   mov eax, dword [ebx+4]
   mov edi, eax
   sub ecx, ecx
   sub al, al
   not ecx
   cld
   repne scasb
   not ecx 
   dec ecx
   mov eax, ecx
   cmp eax, dword 20
   ja ERR2

   mov [N], dword eax       ;line 39 to 54 makes sure that all letters are lowercase
   call print_int
   mov ebx, N
   call print_int
   mov ebx, dword [ebp+12]
   mov eax, dword [ebx+4]

;------------------------- Code that I am having problems with
LOOP: 
   mov bl, byte[eax]
   cmp bl, 0x61
   jb ERR3
   cmp bl, 0x7A
   jb ERR3
   add eax, 4
   add ecx,1
   cmp ecx, N
   jb LOOP
;---------------------------------------------------------------

   mov eax,  0
   mov eax, strt
   call print_nl
   call print_string
   jmp asm_main_end

 ERR1:
   mov eax, err1
   call print_string
   jmp asm_main_end

 ERR2:
   mov eax, err2
   call print_string
   jmp asm_main_end

 ERR3: 
   mov eax, err3
   call print_string
   jmp asm_main_end

 asm_main_end:
   call print_nl
   popa                  
   leave                     
   ret

但即使我的第二个参数是abcd,循环仍然跳转到ERR3。任何想法我可能做错了什么?我是 运行 redhat-linux,nas 2.10.07。 编辑:N 是第二个参数的长度,这是正确的。

我想你正在寻找类似的东西:

  xor ecx, ecx   ; Initialize the counter ECX to zero
LOOP:
  mov bl, byte[eax]
  cmp bl, 'A'
  jb .CONT       ; If we are below 'A' we are not a capital, continue to next char
  cmp bl, 'Z'    ; We are >= 'A' here, but we need to check if we are <= 'Z' 
  jbe ERR3       ; If we are <= 'Z' then we must be a capital so Goto ERR3
.CONT:           ; If there was no error we reach here
  inc eax        ; Goto next character
  inc ecx        ; We want to do another loop
  cmp ecx, [N]   ; Compare to what is variable [N], not its pointer
  jbe LOOP       ; Loop while ECX <= N (N = strlen not including nul terminator) 

我在代码中添加了注释来解释。此代码尚未精简,我正在尝试以与您当前正在编写的代码类似的方式生成代码。

大意是比较'A'和'Z'的范围。如果我们在那个范围内,那么我们就会出错。首先比较我们是否小于'A'。如果是我们就不能是大写字母,因为'A'下面没有大写字母(在ASCII table中)。如果我们低于 'A',我们就继续下一个字符。如果我们不低于 'A',我们将继续检查以查看我们实际上是否 <= 'Z'。如果我们是那么我们必须是一个大写字母然后我们产生一个错误。否则我们继续下一个字符。


一种更高级的方法(我在上面提到过)是从 BL 中减去 'A',然后将其与 25('Z'-'A') 使用无符号比较。如果 BL 小于或等于 25,则 BL 是大写字母。代码可能如下所示:

     xor ecx, ecx
   LOOP:
     mov bl, byte [eax]
     sub bl, 'A'              ; Normalize BL
     cmp bl, 'Z'-'A'          ; 'Z'-'A' = 25 (alphabet between 0 and 25 inclusive)
     jbe ERR3                 ; If BL <= 25 (unsigned comparison!) then BL 
                              ; was a capital letter

     inc eax
     inc ecx
     cmp ecx, [N]
     jbe LOOP