2016-04-26 12 views
0

Also habe ich diese Aufgabe, ein Programm zu schreiben, das einen Stuhl wie ein Dreieck mit Zeilen von Zeichen erstellt.Stapelproblem in x86-Baugruppe: Dreieck PROC-Fehler auf POP

Wenn der Benutzer eine Nummer wählt, in diesem Beispiel '4', sollte es so aussehen:

1 
12 
123 
1234 
2 3 
3 2 
4 1 

Nun, für das Dreieck Teil kam ich mit auf den Punkt:

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 

... aber aus irgendeinem Grund die POP gibt mir 00,00 auf einmal, obwohl ich die PUSH vorher verwendet .. Haben Sie einen Tipp?

+2

Es ist nicht ganz klar, was Sie tun, aber da Sie 'POP AX' in der Schleife, wenn Sie gehen zurück über' JBE CHECK_PRINT "bedeutet, dass du wieder ohne Druck drückst. PS: Lerne einen Debugger zu benutzen. – Jester

+0

Verstanden, danke. Schätzen Sie den Rat –

Antwort

2

Sie haben Ihre Frage mit dem Tag stack markiert. Wenn Sie mit der Maus darüber fahren, erhalten Sie die Information, dass ein Stapel eine LIFO (last-in-first-out) Datenstruktur ist.

Das Problem mit Ihrem Code ist, dass Sie PUSH einen Wert in und (möglicherweise) POP mehrere Werte heraus, die den Stapel vermasselt. Sehen Sie, in TRIANGLE: Sie schieben einen Wert auf den Stack:

PUSH AX 
CALL NEW_LINE 

Aber in CHECK_PRINT: Sie versuchen, POP diesen einen Wert (möglicherweise) mehr als einmal, POP ing andere Werte aus dem Stapel:

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

Dies kann zu Ihrem Problem führen. Zumindest ist es sehr unsichere Programmierung.

Eine Lösung für dieses könnte AX vor jedem INT 21h Aufruf speichern. Ich hatte vor einigen Tagen eine Antwort/Kommentar zu diesem Thema here. Wenn Sie jedoch den Stack nicht in Unordnung bringen und das Register AX beibehalten, sollten Sie sich Ihrer gewünschten Lösung nähern.

Also hier sind meine Vorschläge:

  • die PUSH AX entfernen, bevor die CALL NEW_LINE
  • Entfernen Sie die PUSH AX nach dem INC AL in NEXT_ROUND
  • entfernen die POP AX in CHECK_PRINT
  • Surround Ihr INT 21h Anruf CHECK_PRINT mit PUSH AX a nd POP AX

    PUSH AX ; added 
    MOV DL,BL 
    MOV AH,2 
    INT 21H 
    POP AX  ; added 
    
  • Ändern Sie bitte Ihre NEW_LINE PROC

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

Vielen Dank für die Informationen, werden versuchen, dies auszuarbeiten ..kann ich fragen, was würden Sie stattdessen tun? –