NASM 程序集:检查字符串长度+确认字符串是否只由'0'、'1'、'2'组成?
NASM Assembly: checking length of string + confirming string is only made up of '0', '1', and '2' 's?
我对汇编比较陌生,我正在尝试编写一个程序,将 2 个命令行参数作为输入(第二个命令行参数是一个字符串)并检查其长度在 1 到 30 之间。它还检查字符串是否仅由字符 0、1 和 2 组成。任何其他字符,它终止。当我 运行 程序时,它只是输出 "Segmentation fault"。从我收集到的信息来看,当我处理我不应该处理的一部分内存时,就会发生这种情况。我知道我的问题出在循环中的某个地方,但我不知道在哪里或为什么。任何关于我的代码错误的建议将不胜感激。
代码如下:
%include "asm_io.inc"
global asm_main
SECTION .data
lenError: db "Length of string must be between 1 and 30 (inclusive).",10,0
argError: db "Only 2 command line arguments accepted.",10,0
charError: db "Only characters '0', '1', and '2' are accepted.",10,0
SECTION .text
global asm_main
extern strlen
extern printf
asm_main:
enter 0,0
pusha
mov eax, dword [ebp+8] ; argc
cmp eax, dword 2 ; if argc == 2
jne ERR_ARG
popa
mov ebx, dword [ebp+12]
mov eax, [ebx+4] ;eax has the string in it now
mov ecx, 0 ;initialize a counter
LOOP1:
cmp byte[eax], 0 ;end of string
je DONE
cmp byte[eax], '0' ;check if char == 0
je GO
cmp byte[eax], '1'
je GO
cmp byte[eax], '2'
je GO
jmp ERR_CHAR
GO:
inc ecx ; increase counter
inc eax ;next position in string
cmp ecx, 30
jg ERR_LEN
jmp LOOP1
DONE:
call print_string ;there's more to come,
jmp asm_main_end ;but i want to find the error first
ERR_CHAR:
mov eax, charError
call print_string
jmp asm_main_end
ERR_LEN:
pop eax
mov eax, lenError
call print_string
jmp asm_main_end
ERR_ARG:
mov eax, argError
call print_string
jmp asm_main_end
asm_main_end:
popa
leave
ret
更新:我相信我已经将分段错误隔离到 asm_main_end,我终止程序的方式有什么问题吗?
导致分段错误的问题是 jne ERR_ARG
之后靠近函数开头的 popa
指令。如果不采用分支,则寄存器从那里的堆栈中弹出,然后在 asm_main_end
处再次弹出。
asm_main:
enter 0,0
pusha
mov eax, dword [ebp+8]
cmp eax, dword 2
jne ERR_ARG
popa ; Do not pop here
;
;
;
asm_main_end:
popa ; when popping here
leave
ret
第二个popa
然后将从堆栈中删除return地址(除了用不相关的值填充大部分寄存器),使函数return成为任意位置很可能不属于您的程序。如果给定了错误数量的参数,程序应该会正确运行。
顺便说一句:在您的代码中不需要推送寄存器(除了 enter
完成的推送 ebp 之外)。
我对汇编比较陌生,我正在尝试编写一个程序,将 2 个命令行参数作为输入(第二个命令行参数是一个字符串)并检查其长度在 1 到 30 之间。它还检查字符串是否仅由字符 0、1 和 2 组成。任何其他字符,它终止。当我 运行 程序时,它只是输出 "Segmentation fault"。从我收集到的信息来看,当我处理我不应该处理的一部分内存时,就会发生这种情况。我知道我的问题出在循环中的某个地方,但我不知道在哪里或为什么。任何关于我的代码错误的建议将不胜感激。
代码如下:
%include "asm_io.inc"
global asm_main
SECTION .data
lenError: db "Length of string must be between 1 and 30 (inclusive).",10,0
argError: db "Only 2 command line arguments accepted.",10,0
charError: db "Only characters '0', '1', and '2' are accepted.",10,0
SECTION .text
global asm_main
extern strlen
extern printf
asm_main:
enter 0,0
pusha
mov eax, dword [ebp+8] ; argc
cmp eax, dword 2 ; if argc == 2
jne ERR_ARG
popa
mov ebx, dword [ebp+12]
mov eax, [ebx+4] ;eax has the string in it now
mov ecx, 0 ;initialize a counter
LOOP1:
cmp byte[eax], 0 ;end of string
je DONE
cmp byte[eax], '0' ;check if char == 0
je GO
cmp byte[eax], '1'
je GO
cmp byte[eax], '2'
je GO
jmp ERR_CHAR
GO:
inc ecx ; increase counter
inc eax ;next position in string
cmp ecx, 30
jg ERR_LEN
jmp LOOP1
DONE:
call print_string ;there's more to come,
jmp asm_main_end ;but i want to find the error first
ERR_CHAR:
mov eax, charError
call print_string
jmp asm_main_end
ERR_LEN:
pop eax
mov eax, lenError
call print_string
jmp asm_main_end
ERR_ARG:
mov eax, argError
call print_string
jmp asm_main_end
asm_main_end:
popa
leave
ret
更新:我相信我已经将分段错误隔离到 asm_main_end,我终止程序的方式有什么问题吗?
导致分段错误的问题是 jne ERR_ARG
之后靠近函数开头的 popa
指令。如果不采用分支,则寄存器从那里的堆栈中弹出,然后在 asm_main_end
处再次弹出。
asm_main:
enter 0,0
pusha
mov eax, dword [ebp+8]
cmp eax, dword 2
jne ERR_ARG
popa ; Do not pop here
;
;
;
asm_main_end:
popa ; when popping here
leave
ret
第二个popa
然后将从堆栈中删除return地址(除了用不相关的值填充大部分寄存器),使函数return成为任意位置很可能不属于您的程序。如果给定了错误数量的参数,程序应该会正确运行。
顺便说一句:在您的代码中不需要推送寄存器(除了 enter
完成的推送 ebp 之外)。