我对程序集相对较新,我正在尝试创建一个程序,它接受2个命令行参数作为输入(第二个命令行参数是一个字符串)并检查它的长度为1到30之间。它还检查查看字符串是否仅由字符0,1和2组成。任何其他角色,它终止。当我运行程序时,它只输出“分段故障”。从我收集的内容来看,这种情况发生在我处理一部分我不应该搞砸的内存时。我知道我的问题在循环中的某个地方,但我不知道在哪里或为什么。任何有关我的代码错误的建议都将不胜感激。
以下是代码:
%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,我是如何从程序中终止的?
答案 0 :(得分:3)
导致分段错误的问题是在函数开头附近popa
之后的jne ERR_ARG
指令。如果未采用分支,寄存器将从堆栈中弹出,然后再次在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
将从堆栈中删除返回地址(除了用不相关的值填充大部分寄存器),使函数返回到最有可能不属于您的程序的任意位置。如果给出错误的参数数量,程序应该正常运行。
顺便说一句:在您的代码中,推送寄存器(除了由enter
推送ebp之外)不应该是必要的。