Ein paar Fragen



  • Hi,
    also ich habe mir vorgenommen Assembler zu lernen. Ich kann auch schon in C/C++ programmieren, llerdings bin ich ein wenig verwirrt, denn wenn man nach Tutorials oder dergleichen sucht sieht der Code jedesmal anders aus, obwohl er scheinbar das gleiche tun soll. Außerdem finde ich es ein wenig dumm, wenn mein Programm dann nur auf einem einzigen Computer läuft. Könnt ihr mir da ein paar Tipps/Erklärungen und am besten noch ein Tutorial empfehlen womit ich mir die Grundlagen aneignen kann?

    Viele Grüße und danke im Voraus



  • Hi,
    ich hab gerade eine neue Frage bezüglich des Assemblers.
    Ich habe folgendenen Code:

    .model tiny
    .code
    org 100h
    
    START:
    
        mov ah, 09h
        mov dx, offset Hello
        INT 21h
    
    ENDE:
    
        mov ah, 4ch
        INT 21h
    
    Hello db 'Hello :)', 10d, 13d, '$'
    
    END START
    

    Allerdings kann ich das leider nicht mit MASM erstellen. Mir wäre der TASM auch lieber, da im Tutorial erwähnt wird das es dafür geschrieben wurde, aber den konnte ich trotz das er ja scheinbar Freeware zu sein scheint nicht finden 😞

    Microsoft (R) Macro Assembler Version 6.14.8444
    Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.
    
     Assembling: D:\masm32\Tut\HelloWorld.asm
    D:\masm32\Tut\HelloWorld.asm(18) : warning A4023: with /coff switch, leading und
    erscore required for start address : START
    Microsoft (R) Incremental Linker Version 5.12.8078
    Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
    
    HelloWorld.obj : fatal error LNK1190: invalid fixup found, type 0x0001
    _
    Link error
    

    Ideen?

    Vielen dank

    Gruß



  • Hi,
    habe mich nun die ganze Zeit damit rumgeärgert und eine Lösung gefunden 🙂

    Erstmal ist MASM32 dafür nicht geeignet, weil ich wohl 16 Bit Code habe.
    Also hab ich nun das alte MASM genommen und bei Microsoft im Support gefunden man muss beim Linker /TINY hinzufügen. Und nun klappts 🙂

    Weite Tutorialempfehlungen.... uswstehen aber noch offen 😃

    Gruß



  • Habe nun nen bisschen gebastelt und dieses bescheidene Programm erstellt.

    .MODEL tiny
    .CODE
    
    ORG 100h
    
    _START:
    	MOV DX, OFFSET MyMessageEqual 
    	PUSH DX
    
    	MOV DX, OFFSET MyEqual
    	PUSH BX
    
    	MOV DX, OFFSET MySecondMessage 
    	PUSH DX
    
    	MOV DX, OFFSET MyMessage
    	PUSH DX
    
    	; Klappt leider nicht. Sollte nach dem Tutorial aber mit TASM geht wie mache ich das mit MASM?
    
    	;PUSH 09h				; error A2001: immediate operand not allowed
    	;POP AH					; error A2149: byte register cannot be first operand
    
    	POP DX					; Warum geht das nicht IN der Funktion selber?
    	CALL WRITE_OUTPUT_FROM_STACK
    
    	MOV CX, 25h
    	SUB CX, 1h
    	POP DX
    	LINE_LOOP:				; Dito...
    		CALL WRITE_OUTPUT_FROM_STACK
    	LOOP LINE_LOOP
    
    READ_INPUT:
    	CALL READ_KEY
    
    	CMP AL, MyEqual
    	 je EQUAL
    
    	JMP _END
    
    EQUAL:
    	MOV AH, 09h
    	;LEA DX, MyMessageEqual 
    
    	POP BX
    	POP DX
    
    	INT 21h
    
    	JMP _END
    
    _END:
    	MOV AH, 09h
    	LEA DX, MyEnd
    	INT 21h
    
    	MOV AH, 4CH
    	INT 21h
    
    WRITE_OUTPUT_FROM_STACK:
    	MOV AH, 09h
    	INT 21h
    ret
    
    READ_KEY:
    	MOV AH, 01h
    	INT 21h
    ret
    
    MyMessage DB 10d, 13d, 'Dies ist ein sehr simples Programm.', 10d, 13d, '$'
    MySecondMessage DB '-', '$'
    MyEqual DB '1', 10d, 13d, '$'
    MyMessageEqual DB 10d, 13d, 10d, 13d, 'Der Wert ist gleich!', '$'
    MyEnd DB 10d, 13d, 10d, 13d, 'Bye. Bye.', 10d, 13d, '$'
    
    END _START
    

    Vielleicht könnte ja mal jemand drübergucken und mir das was ich als Kommentar geschrieben haben beantworten und mir vielleicht auch noch andere Sachen sagen die euch auffallen.

    Gruß



  • Ich benutze den MASM nicht, steige auch nicht so ganz durch, was dein Programm ueberhaupt machen soll und kann so bei einigen Fehlern nur raten, aber was soll's... 😃

    Blubbb schrieb:

    ; Klappt leider nicht. Sollte nach dem Tutorial aber mit TASM geht wie mache ich das mit MASM?

    ;PUSH 09h ; error A2001: immediate operand not allowed
    ;POP AH ; error A2149: byte register cannot be first operand

    Das Erste haette der TASM AFAIR in der Tat so gefressen und 9 als word ge"push"t. Warum der MASM meint, push wuerde keine konstanten Werte akzeptieren, weiss ich auch nicht. Vielleicht zu alte Version? Falschen Zielprozessor eingestellt? ...?
    Beim Zweiten hat der MASM allerdings recht: du kannst keine bytes vom Stack "pop"en oder auf den Stack "push"en. Denk' dir da also was anderes aus.

    Blubbb schrieb:

    POP DX ; Warum geht das nicht IN der Funktion selber?
    CALL WRITE_OUTPUT_FROM_STACK

    Ich nehme mal an, du wunderst dich, warum dieses pop in der Funktion so nicht das gewuenschte Ergebnis liefern wuerde.
    Dabei solltest du vielleicht bedenken, dass ein call im Grunde nichts anderes macht als:

    CALL WRITE_OUTPUT_FROM_STACK
    ==
    push ip + laenge_d._jmp-Befehls  ; den Befehl gibt es so nicht - nur als Beispiel
    jmp  WRITE_OUTPUT_FROM_STACK
    

    , also das offset des naechsten Befehls hinter dem call auf den Stack zu packen und dann in die Funktion zu springen.
    Mit dem pop holst du in der Funkion dann natuerlich erstmal die Ruecksprungadresse der Funkion vom Stack.
    ...
    Der Rest ist mir gerade irgendwie zu verworren... Sry. 🙄



  • Hi,
    habe das mal kommentiert 🙂

    Vielleicht kannst du mir ja für meine Vorhaben ein paar bessere Möglichkeiten nennen, denn POP z.B. außerhalb der Funktion aufrufen zu müssen ist doof, also muss es da ja eine Möglichkeit geben aber da komme ich selber leider mit den Kenntnissen, habe gestern angefangen, noch nicht drauf.

    .MODEL tiny ; Kleines Programm
    .CODE ; Code...
    
    ORG 100h ; Überlesen wird ja irgendwie bei dem Model nicht benötigt
    
    _START:
        MOV DX, OFFSET MyMessageEqual ; Nachricht (s. Unten) in DX schreibeb
        PUSH DX                       ; Und auf den Stack...
    
        MOV DX, OFFSET MyEqual
        PUSH BX
    
        MOV DX, OFFSET MySecondMessage
        PUSH DX
    
        MOV DX, OFFSET MyMessage
    
        POP DX                    ; DX vom Stack holen
        CALL WRITE_OUTPUT_FROM_STACK ; Ausgabefunktion ausführen
    
        MOV CX, 25h ; Counter mit 25 initalisieren
        SUB CX, 1h ; Counter um 1 erniedriegen --> 24h
        POP DX ; DX vom Stack holen
        LINE_LOOP:                ; Schleife
            CALL WRITE_OUTPUT_FROM_STACK ; '-' ausgeben
        LOOP LINE_LOOP
    
    READ_INPUT:
        CALL READ_KEY ; Taste einlesen
    
        CMP AL, MyEqual ; Mit MyEqual vergleichen
         je EQUAL ; Wenn gleich nach EQUAL gehen
    
        JMP _END ; Ansonsten ENDE
    
    EQUAL: ; Ist Gleich
        MOV AH, 09h ; Interrupt "vorbereiten" oder wie man so was nennt
    
        POP BX ; Ist überflüssig war der Wert den ich vergleichen habe (MyEqual)
        POP DX ; Wert in DX laden
    
        INT 21h ; Und jetzt ausführen
    
        JMP _END
    
    _END:
        MOV AH, 09h ;         Zeigt halt die "Auf wiedersehns" Meldung an
        LEA DX, MyEnd ;
        INT 21h ;
    
        MOV AH, 4CH ; Und beenden...
        INT 21h ; .... ausführen
    
    WRITE_OUTPUT_FROM_STACK:
        MOV AH, 09h
        INT 21h
    ret
    
    READ_KEY:
        MOV AH, 01h
        INT 21h
    ret
    
    ; Die ganzen Variablen oder wie sich das hier nennt
    
    MyMessage DB 10d, 13d, 'Dies ist ein sehr simples Programm.', 10d, 13d, '$'
    MySecondMessage DB '-', '$'
    MyEqual DB '1', 10d, 13d, '$'
    MyMessageEqual DB 10d, 13d, 10d, 13d, 'Der Wert ist gleich!', '$'
    MyEnd DB 10d, 13d, 10d, 13d, 'Bye. Bye.', 10d, 13d, '$'
    
    END _START
    

    Mach dir aber keine Sorgen das ich erst 25h schreibe uns dann um 1h vermindere. Sind halt alles kleine spielerein. Wobei so was hier nie geklappt hat wie ich wollte:

    MOV AH, 10h
    DEC AH
    

    Scheint zumindest nicht 9h zu sein wie ich wollte. Ich habs gestern dann sogar geschafft meinen Computer zum Piepen zu bringen, mitten in der Nacht versteht sich. Gibts eine Möglichkeit eine Testumgebung zu erstellen. Ich will meinen PC nicht schrotten 👍

    Danke!

    Gruß 😃

    PS: Assembler gefällt mir! Bin ich jetzt verrückt!? :p



  • Blubbb schrieb:

    Hi,
    [...]POP z.B. außerhalb der Funktion aufrufen zu müssen ist doof, also muss es da ja eine Möglichkeit geben aber da komme ich selber leider mit den Kenntnissen, habe gestern angefangen, noch nicht drauf.

    Normalerweise macht man das so, dass man sp nach bp schiebt (weil mit sp nicht adressiert werden kann), und dann so auf die Werte im Stack zugreift.
    zB.

    push    ax
    call    myProc
    add     sp, 2    ; ax vom Stack loeschen
    
    ...
    
    myProc:
    mov    bp, sp
    mov    dx, [word ptr bp + 2]    ; letzter vor call ge"push"ter Wert liegt jetzt
    ; bei sp + 2
    ...
    ret
    

    ... hab ein paar Kommentare hinzugefuegt...

    .MODEL tiny ; Kleines Programm
    .CODE ; Code...
    
    ORG 100h ; Überlesen wird ja irgendwie bei dem Model nicht benötigt
    
    _START:
        MOV DX, OFFSET MyMessageEqual ; Nachricht (s. Unten) in DX schreibeb
        PUSH DX                       ; Und auf den Stack...
    
        MOV DX, OFFSET MyEqual        ; Wozu das?
        PUSH BX                       ; wie du weiter unten bemerkst: macht keinen
                                      ; Sinn...
    ; Du setzt hier dx und "push"st dann bx - ein uninitialisierter Wert...
    
        MOV DX, OFFSET MySecondMessage
        PUSH DX
    
        MOV DX, OFFSET MyMessage      ; dx setzen und in der naechsten Zeile gleich
    ; wieder ueberschreiben... Sinn?
    
    ; also entweder hier ein
    ;push dx
    ; einfuegen, oder...
    
    ;    POP DX                    ; DX vom Stack holen
    ; dieses pop weglassen.
    ; IMHO lassen wir das erstmal besser...
    
    ; sonst waere nach dem pop DX = OFFSET MySecondMessage
    ; und weiter unten wuerdest du nicht die richtigen Werte vom Stack kriegen
    
    ;... naja, an sich kein schoenes Konstrukt...
    ;Hochsprachen packen die Funktionsparameter gern auf den Stack - in Assembler
    ;kann man dagegen unnoetige Speicheroperationen nach Moeglichkeit vermeiden...
        CALL WRITE_OUTPUT_FROM_STACK ; Ausgabefunktion ausführen
    
        MOV CX, 25h ; Counter mit 25 initalisieren
        SUB CX, 1h ; Counter um 1 erniedriegen --> 24h
    ; ein dec cx haette das gleiche bewirkt...
        POP DX ; DX vom Stack holen
    ; DX ist dann = OFFSET MySecondMessage
        LINE_LOOP:                ; Schleife
    ; naja, zum Testen...
    ; sonst wuerde ich hier zB. einmal ausserhalb der Schleife alle Register fuer
    ; den Interruptaufruf entsprechend setzen und in der Schleife nur noch den
    ; Interrupt aufrufen
    ; Generell solltest du davon Abstand nehmen, Funktionen mit so wenig Code
    ; zu basteln. Das ist ineffizient. Um die Uebersichtlichkeit zu erhoehen, kannst
    ; du stattdessen Macros verwenden.
            CALL WRITE_OUTPUT_FROM_STACK ; '-' ausgeben
        LOOP LINE_LOOP
    
    READ_INPUT:
        CALL READ_KEY ; Taste einlesen
    
        CMP AL, MyEqual ; Mit MyEqual vergleichen
         je EQUAL ; Wenn gleich nach EQUAL gehen
    
        JMP _END ; Ansonsten ENDE
    
    EQUAL: ; Ist Gleich
        MOV AH, 09h ; Interrupt "vorbereiten" oder wie man so was nennt
    
        POP BX ; Ist überflüssig war der Wert den ich vergleichen habe (MyEqual)
    ; 1. hast Recht - ist überflüsig =)
    ; 2. Nope, ist irgendein erstmal undefinierter Wert - siehe oben
        POP DX ; Wert in DX laden
    ; DX ist dann = OFFSET MyMessageEqual
    
        INT 21h ; Und jetzt ausführen
    
        JMP _END ; Sinn?
    
    _END:
        MOV AH, 09h ;         Zeigt halt die "Auf wiedersehns" Meldung an
        LEA DX, MyEnd ; lea fuer so einfache Konstanten macht nicht viel Sinn
    ; zumindest der TASM wandelt sowas dann AFAIR auch kommentarlos in ein mov um.
        INT 21h ;
    
        MOV AH, 4CH ; Und beenden...
        INT 21h ; .... ausführen
    
    WRITE_OUTPUT_FROM_STACK:
        MOV AH, 09h
        INT 21h
    ret
    
    READ_KEY:
        MOV AH, 01h
        INT 21h
    ret
    
    ; Die ganzen Variablen oder wie sich das hier nennt
    
    MyMessage DB 10d, 13d, 'Dies ist ein sehr simples Programm.', 10d, 13d, '$'
    MySecondMessage DB '-', '$'
    MyEqual DB '1', 10d, 13d, '$' ; tjoa - schon wieder: Sinn?
    ; Du benutzt nur einmal das erste Zeichen fuer einen Vergleich.
    ; Auf die drei uebrigen Zeichen in diesem String greifst du in deinem
    ; Programm nicht zu.
    MyMessageEqual DB 10d, 13d, 10d, 13d, 'Der Wert ist gleich!', '$'
    ; Du kannst das "$" auch einfach in den String schreiben...
    MyEnd DB 10d, 13d, 10d, 13d, 'Bye. Bye.', 10d, 13d, '$'
    
    END _START
    

    Blubbb schrieb:

    Mach dir aber keine Sorgen das ich erst 25h schreibe uns dann um 1h vermindere. Sind halt alles kleine spielerein. Wobei so was hier nie geklappt hat wie ich wollte:

    MOV AH, 10h
    DEC AH
    

    Scheint zumindest nicht 9h zu sein wie ich wollte.

    Vielleicht solltest du dir bei Wikipedia o.Ae. nochmal ansehen, was das Hexadezimalsystem ist... 10h - 1 ist naemlich 0Fh und nicht 09h.
    Haettest du im obigen Beispiel "DEC AH" durch "SUB AH, 1" ersetzt haettest du das gleiche Ergebnis erhalten.

    Blubbb schrieb:

    Ich habs gestern dann sogar geschafft meinen Computer zum Piepen zu bringen, mitten in der Nacht versteht sich. Gibts eine Möglichkeit eine Testumgebung zu erstellen. Ich will meinen PC nicht schrotten 👍

    Wenn du deine Programme unter einem WinNT (Win2k, WinXP o.Ae.) startest, werden sie sowieso schon im Windowseigenen Dosemulator ausgefuehrt...
    Fuer hardwarenaehere Experimente gibt es dann zB. den PC-Emulator bochs.

    Blubbb schrieb:

    PS: Assembler gefällt mir! Bin ich jetzt verrückt!? :p

    Kann ich dir auch net sagen. 😃



  • Hallo,

    @Blubbb:
    ich habe mir grade Codeausschnitte angeguckt und ich finde, es gibt zu viele und an einigen Stellen falsche Kommentare... ich möchte nicht zu kleinlich sein, aber diese Zeile z.B.

    .MODEL tiny ; Kleines Programm
    

    ist ganz schön irreführend.
    Oder das hier:

    MOV CX, 25h ; Counter mit 25 initalisieren
    

    ist irreführend und unnötig. Irreführend, weil 25h ungleich 25, unnötig, weil es steht ja schon da, was gemacht wird und das muss man nicht noch mal im Kommentar erwähnen (vielleicht bloss erwähnen, dass cx dein Counter ist und sonst nichts).
    Genauso hier:

    POP DX ; DX vom Stack holen
    

    Man muss nicht extra erwähnen, dass dx vom Stack geholt wird...
    Das hier ist auch ...

    MOV AH, 4CH ; Und beenden... 
    INT 21h ; .... ausführen
    

    ... ein Kommentar aber sonst nichts, ich meine, man weiss, dass es Kommentar ist, aber was es aussagt, kann man nicht verstehen.

    Gruß,
    abc.c


Anmelden zum Antworten