Punkt zeichnen (int 10, al 0Ch)



  • Hallo Leute!

    Bin noch ganz neu in Assembler und habe mir nur das Hallo Welt Programm angeguckt und die kleine DOS API Referenz in meinem Buch. Jetzt hab ich in den Grafikmodus 640 * 480 gewechselt -> klappt
    Und nun wollte ich einen Punkt zeichnen, aber ich seh ihn nicht. Hier mal der Code:

    CODE SEGMENT WORD 'CODE'
    ASSUME CS:CODE
    
    Start:
    
    ;----------------------------------------------------------
    ; In Videomodus 640 * 480 mit 16 Farben wechseln
    ;----------------------------------------------------------
    
    mov ah, 0
    mov al, 12
    int 10h
    
    ;----------------------------------------------------------
    ; Punkt zeichnen
    ;----------------------------------------------------------
    
    mov ah, 0Ch
    mov cx, 10 ; Splate
    mov dx, 10 ; Zeile
    mov al, 4 ; Farbattribut -> Ist 4 überhaupt gültig?
    int 10h
    
    ;----------------------------------------------------------
    ; Auf Eingabe eines Zeichens warten
    ;----------------------------------------------------------
    
    mov ah, 7
    int 21h
    
    ;----------------------------------------------------------
    ; Programm beenden
    ;----------------------------------------------------------
    
    mov ah, 04Ch
    int 21h
    
    CODE ENDS
    
    END Start
    

    Wer kann mir helfen? Ist das Farbattribut einfach nicht richtig? In meinem Buch stand nicht was man da einsetzen muss. Oder ist der Punkt zu klein das man ihn garnicht sehen kann? Wer kann mir dabei helfen?

    Ich benutze TASM 5 und Windows XP, falls das was zur Sache tut :p



  • kann es vielleicht sein, dass der Interrput 0x10 nicht geht, da XP ein PM OS ist und keine BISO Interrupts zulässt.



  • Das glaube ich nicht...denn bei dem Wechsel in den Videomodus benutze ich ja auch den Interrupt 10h und es tut sich was. Ich bekomme so in einen "Vollbildmodus". Habe auch gerade ein farbiges Zeichen mit Interrupt 10h (Funktion 09) ausgegeben. Hat auch funktioniert.
    Windows emuliert ja DOS wenn das Programm mit einem 16-bit Compiler/Assembler geschrieben wurde.



  • achso, na wenn Windos DOS emuliert, sollte das kein Problem sein.

    Versuch doch mal eine Linie (mehrere Punkte auf einer Schleife) zu malen, vielleicht siehst du das dann besser.



  • Ok, könnte ich mal versuchen...doch leider bin ich wie gesagt noch totaler Anfänger und weiss noch nicht wie z.B. ne Schleife in Assembler aussieht 😃 😃
    Könntest du mir vielleicht helfen, wie ich den Code in eine Schleife verpacken kann?



  • ich weiss nicht, ob es funzt, da ich nicht mehr so gut in Assembler bin (und vorallem nicht mehr in Intel Assembler)

    ;...
     ;----------------------------------------------------------
     ; Punkt zeichnen 
     ;----------------------------------------------------------
    
     push bx
     xor bx,bx
     linie01:
     mov ah, 0Ch
     mov cx, bx ; Splate
     mov dx, 10 ; Zeile
     mov al, 4 ; Farbattribut -> Ist 4 überhaupt gültig?
     int 10h
     inc bx
     cmp bx,20h ;zeichne eine Linie, die 0x20 Spalten lang ist
     jl linie01
    


  • Danke für deine Mühen Kingruedi. Assemblieren konnte ich den Code, doch leider sehe ich immer noch nichts. Was könnte noch falsch sein? :p



  • Der Monitor gehört an :p



  • @TriPhoenix: Hast du den Code getestet? Sieht du etwa was? :p :p



  • Bisher net, ich kanns ja mal versuchen 🙂 Wenn mir noch jemand sagt, wo ich TASM bekomme... (in der FAQ hab ich nichts gesehen...Google versuch ich gleich nochmal :))

    Edit: den 2.01er hab ich shcon..gibt aber sicher noch aktuellere Versionen, oder? ^^

    Zusatz 2 🙂 Unter WinXP ist dessen funktionieren fragwürdig..ich krieg nur ein wneig roten Matsch am oberen Rand, der hatte ein paar probs, den vollbildmodus zu greifen 🙂 Vielelicht morgen

    [ Dieser Beitrag wurde am 30.05.2002 um 02:02 Uhr von TriPhoenix editiert. ]



  • Moin, Moin...

    Der Fehler des Programms liegt in der Zeile mov al, 12. Der
    betreffende Videomodus hat den Wert 012(hex). Das entspricht 18(dez)!

    Also entweder schreiben mov al,18 oder mov al,012h.

    Außerdem sollte wieder in den Textmodus geschaltet werden, bevor das Programm beendet wird.

    mov ah,0
    mov al,03h
    int 010h
    
    ; Programm beenden
    

    Ciao...

    [ Dieser Beitrag wurde am 30.05.2002 um 08:38 Uhr von KalEl editiert. ]

    [ Dieser Beitrag wurde am 30.05.2002 um 08:39 Uhr von KalEl editiert. ]



  • Wow, vielen Dank an alle! KaiEl hatte recht, mit 12h in al funktioniert es 🙂 🙂
    Aber dazu muss ich sagen, dass es dann in meinem Buch falsch stand, dort standen nämlich nur 12 :p

    Grafikprogrammierung ist ja dann ziemlich einfach, echt super 🙂
    Jetzt bastel ich mir mal ein paar Funktionen zum Beispiel zum Zeichnen eines Kreises. Ist es überhaupt möglich irgendwie Funktionen wie in C/C++ zu schreiben? Dachte man nimm Labels.

    ZeichneKreis:
    ; Code

    Aber dann kann ich ja nie Werte übergeben. Kann man sowas machen?



  • funktionen gibt es auch in Assembler!

    Beispiel

    ;...
    call kreis
    ;...
    
    kreis PROC NEAR
       ;...
       ret
    kreis ENDP
    


  • Moinsen...

    Ähm, mein Name lautet nicht KaiEl sonder KalEl. 😉

    Danke...



  • Danke, habe es jetzt versucht das Zeichnen der Linie in eine Funktion einzubetten, dazu habe ich auch in meinem Buch nachgelesen, aber jetzt stürtzt das Programm ab:

    ;----------------------------------------------------------
    ; Linie zeichnen
    ;----------------------------------------------------------

    Linie PROC NEAR
    push bx
    xor bx,bx
    linie01:
    mov ah, 0Ch
    mov cx, bx ; Splate
    mov dx, 10 ; Zeile
    mov al, 4 ; Farbattribut
    int 10h
    inc bx
    cmp bx, 20h ;zeichne eine Linie, die 0x20 Spalten lang ist
    jl linie01
    ret
    Linie ENDP

    call Linie ; Die Linie-Funktion aufrufen

    Windows meldet: "Die NTVDM-CPU hat einen ungültigen Befehl entdenkt."

    Was könnte der Fehler sein?

    @KalEl: Sorry, werde es mir merken 😃 :p 😃



  • ich sehe in der proc "push bx" aber kein "pop bx" 😉



  • Und nochmal Moinsen...

    Hier ein kleines Programm, das die Parameterübergabe an eine
    Assemblerfunktion zeigen soll:

    .model small
    
    .stack 0200h
    
    .data
    
    .code
    
    start:  push 10       ; 1. Parameter auf den Stack
            push 20       ; 2. Parameter auf den Stack
            call addiere  
            add  sp, 4    ; Stack bereinigen
    
            mov ah, 7
            int 21h
    
            mov ah, 04Ch
            int 21h
    
    ; Hier folgen die Funktionen
    
    addiere proc near
    
            push bp     ; Register bp sichern
            mov  bp, sp ; Stackframe aufbauen
    
            push bx     ; Registerinhalt retten
    
            mov  ax, word ptr [bp + 4] ; 1. Parameter nach ax
            mov  bx, word ptr [bp + 6] ; 2. Parameter nach bx
    
            add  ax, bx
    
            pop  bx
    
            mov  sp, bp ; alten Wert von sp wiederherstellen
            pop  bp     ; alten Wert von bp zurückholen
    
            ret
    
    addiere endp
    
    end Start
    

    Die Funktion addiert die beiden Parameter. Das Ergebnis steht in Register ax und kann so an das Hauptprogramm übergeben werden.

    Wichtig ist, dass der Stack bereinigt wird, d.h. die Parameter werden quasi wieder vom Stack entfernt.

    Diese Art der Parameterübergabe ist wie in C. Pascal macht das etwas anders.

    Ciao...



  • Danke dir 🙂 🙂

    Es lag an 2 Sachen, erstmal das pop bx und dann ging's immer noch nicht, da ich so dämlich war und die Funktion in den Code des start-Labels gepackt hatte *lol* :p

    Also hier nochmal der vollständige Code, falls es jemand ausprobieren möchte oder ähnliches 😉

    CODE SEGMENT WORD 'CODE'
    ASSUME CS:CODE
    
    ;----------------------------------------------------------
    ; DrawLine Prozedur
    ;----------------------------------------------------------
    
    DrawLine PROC NEAR
        push bx
        xor bx,bx
        LineLoop:
        mov ah, 0Ch
        mov cx, bx ; Splate
        mov dx, 80 ; Zeile
        mov al, 4 ; rot
        int 10h
        inc bx
        cmp bx, 80h ; zeichne eine Linie, die 0x80 Spalten lang ist
        jl LineLoop
        pop bx
        ret
    DrawLine ENDP
    
    start:
    
    ;----------------------------------------------------------
    ; In Videomodus 640 * 480 mit 16 Farben wechseln
    ;----------------------------------------------------------
    
    mov ah, 0
    mov al, 12h
    int 10h
    
    ;----------------------------------------------------------
    ; Grünes 'a' ausgeben
    ;----------------------------------------------------------
    
    mov ah, 9
    mov bh, 0 ; Bildschirmseite 0
    mov cx, 1 ; Ein Zeichen
    mov al, 97 ; 'a'
    mov bl, 2 ; grün
    int 10h
    
    ;----------------------------------------------------------
    ; Linie zeichnen
    ;----------------------------------------------------------
    
    call DrawLine
    
    ;----------------------------------------------------------
    ; Auf Eingabe eines Zeichens warten
    ;----------------------------------------------------------
    
    mov ah, 7
    int 21h
    
    ;----------------------------------------------------------
    ; Videomodus zurückschalten
    ;----------------------------------------------------------
    
    mov ah, 0
    mov al, 3h
    int 10h
    
    ;----------------------------------------------------------
    ; Programm beenden
    ;----------------------------------------------------------
    
    mov ah, 04Ch
    int 21h
    
    CODE ENDS
    
    END start
    


  • Habe auch mal ne Frage zu deinem Code KalEl:

    mov ax, word ptr [bp + 4] ; 1. Parameter nach ax
    mov bx, word ptr [bp + 6] ; 2. Parameter nach bx

    Was macht man denn, wenn man ganz viele Parameter hat? Soviele Register stehen ja garnicht zur Verfügung 😞



  • Dann verarbeitet man die Parameter halt hintereinander. Die bleiben schliesslich auf dem Stack erhalten. 😉
    Die Parameteruebergabe via Stack erscheint mir ehrlichgesagt sowieso nur sinnvoll, wenn entweder mehr Parameter verarbeitet werden muessen, als Register zur Verfuegung stehen (kommt fast nie vor)
    Der code so unglaublich kompliziert und lang ist, dass man zwischendurch die Parameter so und so pushen muesste (eigentlich auch selten - ich wuerde dann eher auf globale Variablen zurueckgreifen)
    Oder wenn man eine Assembler routine in eine Hochsprache wie zB. C einbinden will.


Anmelden zum Antworten