2016-04-26 9 views
0

私は、文字の行で三角形のように構築された椅子を印刷するプログラムを作成するこのタスクがあります。x86アセンブリのスタックの問題:POP上の三角形PROCフォルト

ユーザーは、この例では、番号を選択し、「4」、それは次のようになります。

1 
12 
123 
1234 
2 3 
3 2 
4 1 

まあ、三角形の部分のために、私はこの思い付いた:

DATA SEGMENT 

    WELCOME DB 'PLEASE ENTER INTEGER BETWEEN 2 AND 9:$' 
    NEWLINE DB 13, 10, '$' 
    WRONG DB 10,13,'WRONG INPUT!',10,13,'$' 

DATA ENDS 

SSEG SEGMENT STACK 
    DW 100 DUP (?) 
SSEG ENDS 

CODE SEGMENT 

    ASSUME CS:CODE,DS:DATA,SS:SSEG 

    START: 
    MOV AX,DATA 
    MOV DS,AX 
    MOV DX,OFFSET WELCOME 
    MOV AH,9 
    INT 21H 

    MOV AH,1 
    INT 21H 

    CMP AL,32H 
    JL WRONG_INPUT 
    CMP AL,39H 
    JA WRONG_INPUT 
    JMP TRIANGLE 

    WRONG_INPUT: 
    MOV DX,OFFSET WRONG 
    MOV AH,9 
    INT 21H 
    JMP START 

    MOV CL,AL 
    SUB CL,30H 

    TRIANGLE: 
    CALL NEW_LINE 
    ;BL PRINTED NUM 
    ;AL COUNTER NUM 
    ;CL LOOP NUMBER 

    XOR BH,BH 
    XOR AH,AH 
    XOR CH,CH 
    MOV AL,32H 
    MOV BL,32H 
    PUSH AX 
    CALL NEW_LINE 

    COUNTERLOOP: 

    CHECK_PRINT: 
    MOV DL,BL 
    MOV AH,2 
    INT 21H 
    INC BL 
    POP AX 
    CMP BL,AL    
    JBE CHECK_PRINT 
    JMP NEXT_ROUND 

    NEXT_ROUND: 

    INC AL 
    PUSH AX 
    DEC CL 
    MOV BL,32H 
    CALL NEW_LINE 
    LOOP COUNTERLOOP 

    LEGS: 
    ; TODO --- create 'legs' 
    EXIT:  
    MOV AH,4CH 
    INT 21H 

    PROC NEW_LINE 
    MOV BP,SP 
    MOV DL, 0AH 
    MOV AH, 2H 
    INT 21H 
    MOV DL, 0DH 
    MOV AH, 2H 
    INT 21H 
    MOV DL,31H 
    MOV AH,2H 
    INT 21H 
    RET 
    NEW_LINE ENDP 

CODE ENDS 
END START 

...何らかの理由でPOPは私が前にPUSHを使っていたのに私に00,00を与えます。 アドバイスはありますか?

+2

にごNEW_LINE PROCを変更JBE CHECK_PRINT'を押すと、プッシュせずに再びポップすることになります。 PS:デバッガの使い方を学んでください。 – Jester

+0

それは、thxを得ました。アドバイスをよろしくお願いします。 –

答えて

2

stackタグで質問にタグを付けました。この上にマウスを置くと、スタックはLIFO(先入れ先出し)データ構造であるという情報を受け取ります。

コードに問題があります。PUSHと、おそらくPOPの値が1つの値になり、スタックが壊れてしまいます。スタックから他の値をINGの

PUSH AX 
CALL NEW_LINE 

しかしCHECK_PRINT:に、あなたは、複数の時間(おそらく)この1つの値POPにしようと、POPTRIANGLE:にあなたがスタックに一つの値をプッシュし、参照してください

CHECK_PRINT: 
    ... 
    POP AX 
    CMP BL,AL    
    JBE CHECK_PRINT  ; !!! possibly POPping more than one time if BL >= AL 
    JMP NEXT_ROUND 

これは、問題を引き起こす可能性があります。少なくとも、それは非常に安全でないプログラミングです。

INT 21hコールの前に、これに対する解決策を保存すると、AXとなる場合があります。私は数日前にその話題に関する答え/コメントを持っていたhere。しかし、スタックを台無しにしてAXレジスタを保持しないと、あなたの希望するソリューションに近づくはずです。だからここ

は私の提案です:

  • NEXT_ROUND
  • INC ALがであなたのINT 21hコールサラウンドPOP AXCHECK_PRINT
  • を削除した後PUSH AXを削除CALL NEW_LINE

  • PUSH AXを削除しますCHECK_PRINTPUSH AXa ND POP AX

    PUSH AX ; added 
    MOV DL,BL 
    MOV AH,2 
    INT 21H 
    POP AX  ; added 
    
  • あなたは `を経由して戻って行く場合、それは、あなたがやっていることは非常に明確ではないですが、ループ内であなた以来` POPのAX`

    PROC NEW_LINE 
        PUSH AX  ; added 
        MOV BP,SP 
        ... 
        POP AX   ; added 
        RET 
    NEW_LINE ENDP 
    
+0

情報ありがとうございました。これを解決しようとします..代わりにあなたは何をするのですか? –

関連する問題