2016-12-10 8 views
1

Я относительно новичок в сборке, и я пытаюсь создать программу, которая принимает два аргумента командной строки в качестве входных данных (второй аргумент командной строки является строкой) и проверяет, что она имеет длину от 1 до 30. Она также проверяет см., если строка состоит только из символов 0, 1 и 2. Любой другой персонаж и он заканчивается. Когда я запускаю программу, он просто выводит «Ошибка сегментации». Из того, что я собрал, это происходит, когда я имею дело с частью памяти, с которой мне не следует возиться. Я знаю, что моя проблема находится где-то внутри циклов, но я не знаю, где и почему. Любые предложения о том, где мой код ошибочен, будут очень признательны.NASM Assembly: проверка длины строки + подтверждающая строка состоит только из '0', '1' и '2' 's?

Вот код:

%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 

UPDATE: Я считаю, что я изолировал ошибку сегментации в asm_main_end, есть что-то не так с тем, как я прекращением из программы?

+1

Когда вы проходите через отладчик, что вы находите? –

+0

извините, но не могли бы вы проинструктировать меня о том, как использовать отладчик? im новый для всего этого. – user7275873

+1

Отладка - это не то, на что можно ответить очень легко. Если вы проходите курс, вы поговорили с ассистентом профессора или учителя. Вы можете попросить у них информацию об отладке. –

ответ

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 затем удалить адрес возврата из стека (в дополнении к заполнению большой части регистра с несвязанными значениями), что делает функцию возврат к произвольному месту, скорее всего, не принадлежащему к вашей программе. Затем программа должна корректно вести себя, если задано неверное количество аргументов.

BTW: нажатие регистров (помимо нажатия ebp, сделанное enter) не должно быть необходимым в вашем коде.

+0

спасибо человеку! это заставило его работать! – user7275873