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