2011-10-07 22 views
0

그래서이 프로그램은 과제를위한 것입니다. 납기일이 지났고 내가 갖고있는 것을 돌려보고 좋은 성적을 받았지만이 버그는 나를 괴롭혔다. 이것은 기술적으로 더 이상 과제가 아니지만, 필자가 코드를 작성하지 않았다면 더 좋아질 것입니다. 이유는 무엇인지 이해하고 싶기 때문입니다. 반드시 수정해야하는 것은 아닙니다.프로그램 종료 후 무한 루프

그래서 프로그램이 정상적으로 작동하지만 (어셈블리에서는 본질적으로 toUpper()입니다.) 프로그램에 종료 문자 (마침표)를 전달하면 프로그램이 '끝'을 성공적으로 호출하지만 실제로는 종료되지 않습니다. 단계별 디버거에서 실행하면 'end main'이 호출 된 다음 프로그램이 jumsp를 사용하여 인식 할 수없는 미리 작성된 코드로 DOS를 호출하여 스택을 정리할 수 있습니다. 잘 모르겠습니다. 나는 여러 가지를 시도해 보았습니다. (성공하지 못했습니다.) 누군가가 이것을 일으킬 수있는 것에 대해 통찰력을 갖고 있다면 궁금합니다. 아래

코드 :

;--------------------------------------------------------------------- 
; program:  Key 
; function: Reads in specific characters from input and displays them. 
; owner:  ---------- 
; date:  9/29/11 
; 09/22/2011 Original Version 
;---------------------- 
    .model small 
    .8086 
;---------------------- 
    .data    ; Start the data segment 
;---------------------- 
    ; No variables 

;---------------------- 
    .code    ; Start the code segment 
;---------------------- 
main:     ; Reading in values 
    mov ah, 8h   ; Request input without echo 
    int 21h   ; Read character into al 

    cmp al, 20h  ; Is it a space? 
    je print   ; If so, print with no changes 
    cmp al, 2Eh  ; Is it a period? 
    je print   ; If so, go to exit. 
    cmp al, 41h  ; Is it below the floor of uppercase? 
    jl main   ; Then it's useless, throw it out and read in new. 
    cmp al, 7Ah  ; Is it above lower ceiling? 
    jg main   ; Then it's useless, throw it out and read in new. 
    cmp al, 5Ah  ; Is it smaller than upper ceiling? 
    jle print   ; If it's equal or smaller, then it's an upper. 
    cmp al, 61h  ; Is it above lower floor? 
    jl main   ; If it is lower, back to main. 
         ; If we're here it's a lowercase letter 
    sub al, 20h  ; Subtract 20h to make lowercase 

print:     ; Print characters 
    mov dl, al   ; Copy character to output register 
    mov ah, 2h   ; Load character output subroutine 
    int 21h   ; Print character 
    cmp dl, 2Eh  ; Check if it was a period. 
    jne main   ; If not a period, go to main. 

    mov ah, 4Ch  ; Place Exit Code for DOS service 
    int 21h   ; call DOS service 
    end main   ; If it was a period, exit program. 
;---------------------- 

이 끝나기 전에 2 줄

가 나보다 어셈블러와 더 많은 경험의 광산의의 frind에 의해 제안되었고,이 프로그램이 내 DOS 에뮬레이터에서 제대로 종료 할 수 있지만, 문제는 '끝'여전히 디버거 및 내 교수 테스트 스크립트에서 발생합니다.

누구든지이 문제를 일으킬 수있는 아이디어가 있습니까?

+2

종료를 위해 DOS를 호출하면 al에 종료 코드 (또는 오류 수준)가 포함됩니다. Mov ax, 4c00h 대신 mov ah, 4ch를 사용하십시오. 이 방법으로 오류 코드는 0이됩니다 (모든 것을 의미합니다). – BlackBear

+0

와우, 정말 고칠 수 있습니다. 알에 남은 숫자가있는 것 같아요. 어떻게 든 그걸 던져 버렸나 봅니다. 원한다면 답변으로 제출하십시오. 해결할 수 있습니다. – Charles

+0

'sub al, 20h' 행의 주석은 "lower * case가 아닌 * upper * case"를 만들기 위해 "20h를 빼기"여야합니다. –

답변

3

종료를 위해 DOS를 호출하면 al에 종료 코드 (또는 오류 수준)가 포함됩니다. mov ah, 4ch 대신 mov ax, 4c00h을 시도하십시오. 이렇게하면 오류 코드는 0이됩니다 (모든 것이 좋습니다). 이것은 리턴 코드가 어떤 식 으로든 DOS 문 IF ERRORLEVEL ...에 의해 모든 것을 망가 뜨리기 때문에 사용되기 때문에 작동합니다. ;)

+0

이것으로 해결되었습니다. 감사합니다. – Charles

+0

@Charles : 문제 없습니다. 조립은이 멋진 헤드 브레이킹 재료로 가득합니다.) – BlackBear

3

"호출이 끝났습니다"라고 말하면 성공적으로 end main으로 전달된다는 의미입니까?

end은 아무 것도하지 않습니다. 이것은 코드의 끝을 나타내는 어셈블러에 대한 지시 일뿐입니다. 코드 실행에는 영향을 미치지 않습니다. 친구가 제안한 마지막 int 21h이 없으면 코드가 계속 실행됩니다. 운이 좋으면 nop 명령을 계속 실행합니다.

+0

그래, 내가 잘못 생각한 것 같아. 필자는 그것이 본질적으로 컴파일러 명령어라는 것을 깨닫지 못했습니다. int 21h/mox ax, 4c00h가 실제 종료 명령이었습니다. 나는 근본적으로 자바의 System.exit()와 끝을 같게하고 int/mov 명령을 괄호 안의 숫자에 썼다. – Charles

+0

실제로 학생들은 여전히 ​​어셈블러 언어를 배우고 있다는 것을 알기는하지만 MS-DOS 컨텍스트에서 실행되는 x86 어셈블러를 가르쳐 주므로 저에게 즐겁습니다. OS/360에서 돌아가는 IBM BAL (기본 어셈블러 언어) 과정을 배워야한다는 것을 상기시켜줍니다. 강사가 최첨단 기계와 OS를 사용하여 최종 3 과제를 수행하도록 설득하는 데는 많은 노력이 필요했습니다. 정말 'int 21h'를 다시 보는 기이 한 모습입니다. –

+0

역사적으로 보잘 것없는 관점에서 가르쳐지는 이유를 완전히 이해합니다.하지만 더 많은 수업이 있었으면 좋겠지 만 다른 언어의 경우 : Ruby, PHP 등. 나는 그것들에서 훨씬 더 많은 것을 사용할 수 있습니다. – Charles