Mein erstes Assemblerprogramm



  • Hi Leute!

    Ich hab bzw. ich sollte heute mein erstes lauffähiges Assemblerprogram geschrieben haben; leider nicht ohne Fehler.

    Meine Aufgabe: Mein Programm soll Ausdruck berechnen: ERG = (A-B) + C

    Den Code assembliere, linke und debugge ich mit dem Borland TASM TLINKER und TDEBUGGER. Wenn ich als erstes Debugger drüber laufen lasse, sagt er mir es gibt einen Error. Ich weiß aber nicht wo es den haben soll. Könnt ihr mir helfen?

    Mein Code:

    %noctls										; keine Listing Steueranweisung
    %noincl										; keine "Include-Dateien" ausgeben
    INCLUDE macros.asm
    ASSUME DS:Daten, CS:CODE					; Segment "Daten" wird Datensegment, "Code" wird Codesegment
    ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    Daten SEGMENT								; hier beginnt das Segment mit dem Namen DATEN
    	A			DW	20h
    	B			DW	20h
    	C			DW	0h
    	Text		DB	"Ergebnis"
    	ERG			DW	0
    				DB	"Flag:"
    	O_Flag		DB	0
    				DB	"Zahl:"
    	Zahl		DW	3421h
    ENDS										; hier endet das Datensegment
    ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    CODE SEGMENT								; hier beginnt das Segment mit dem Name CODE
    	Anfang:
    		mov AX,Daten						; Die Segmentadresse "Daten" kommt in AX
    		mov DS,AX							; "Daten" kommt in DS
    
    		mov AX,A
    		mov BX,B
    		sub AX,BX
    		jo Overflow
    
    		mov BX,C
    		add AX,BX							; (A-B)+C
    		jo Overflow
    		mov ERG,AX							; Speichere Ergebnis
    
    		inc Zahl
    
    		mov AX,A							; A*2
    		mov BX,A
    		add AX,BX
    		mov A,AX
    
    		mov AX,B							; B*2
    		mov BX,B
    		add AX,BX
    		mov B,AX
    
    		mov AX,C							; C*2
    		mov BX,C
    		add AX,BX
    		mov C,AX
    
    		jmp Anfang
    
    	Overflow:
    		mov O_Flag
    
    		Terminate_Program					; Rückkehr zum Betriebssystem
    ENDS										; hier endet das Code-Segment
    ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    END Anfang									; hier endet das Assemblerprogramm
    											; das Programm wird an der Adresse Anfang gestartet
    


  • Die Fehlernachricht die mir Debuuger bringt lautet so:

    Error in Line56: Too few operands to instruct
    Warning in Line 56: Argument needs type override

    Ich kann leider mit diesen Meldungen wenig anfangen....



  • die Fehlermeldung sagt doch was falsch ist!



  • Danke!

    Hab ich jetzt auch gesehen. Laut meiner Aufgabe, soll ich nach dem das Programm einen Overflow erreicht hat in O_Flag eine 1 schreiben. Es fehlt also ",1".

    Eine Frage hab ich noch. Bei meiner Aufgabe wird gesagt, man soll das Ergebnis in die Variable ERG speichern. Wie geht das? Ich hab immer gedacht, man kann nur in den Registern (AX,BX,CX,DX) speichern...

    Wenn das Programm nun bis zu einem Overflow das Ergebnis berechnet, möchte ich das es mir die Ergebnisse auf dem Bildschirm ausgibt. Wie mache ich das? Bzw. das ist wahrscheinlich unsinn, da man nix sehen wird, da vorher das Programm terminieren wird, oder?

    Kannst du mir sagen was da gemeint ist?



  • Sorry, ich sehe gerade das ich ja das eigentlich programmiert habe. Ich speichere den Wert nach der kompletten Berechnung vom Register AX in die Variable ERG. 🙂



  • die beiden Anweisungen
    inc Zahl
    und
    mov O_Flag

    sind nicht ganz unproblematisch. Was passiert denn da genau?

    Außerdem fehlt noch ein Systemaufruf zum Beenden des Programms.

    Und obwohl der Turbo Debugger eine recht gute Hilfe ist, empfiehlt sich der Einstieg in Asm eher über Debug und Fasm. Wenn du deine ersten Gehversuche mit debug (in jedem Windows dabei) machst, merkst du gleich, was auf unterster ebene geht, und was nicht, und du weißt, wie modernere Assembler wie Masm32, Masm, Nasm, Yasm, Fasm, oder gas dir die Arbeit erleichtern, und worin sie sich unterscheiden. Wenn du ein guter Hochsprachenprogrammierer bist, dann lohnt sich auch ein Blick auf den pädagogisch gemachten Assembler HLA. In älteren Assemblerbüchern steht zwar immer noch Tasm-Code, aber ab einem bestimmten Schulungslevel ist es leicht, Tasm Programme z.B. nach seinem inoffizellen und gut optimierten Nachfolgerassembler Fasm zu übertragen.



  • Danke Nachtfeuer für deine Hilfe!

    Wie gesagt (und wie du wahrscheinlich schon erkannt haben wirst...), bin ich blutiger Anfänger in Bezug auf Assemblerprogrammierung. Genau genommen bin ich auch in Hochsprachen wie C oder C++ blutiger Anfänger. Ich befinde mich momentan im ersten Semester eines Technischen Informatik Studiums. Unser Professor zieht die Vorlesung zu Assemblerprogrammierung aber anhand von TASM auf. Deswegen verwende ich diesen Assemblierer.

    Nun zu deinen erwähnten Anweisungen.

    In meiner Aufgabe steht auch noch, dass ich nach jedem Durchlauf das Programms eine Zählvariable um eins hochzählen lassen soll, wenn kein Overflow entstanden ist. Laut Aufgabe sollen wir dafür eben den Befehl des inkrementierens (inc) benutzen und das Ergebnis des inc-Befehls in die Variable "Zahl" schreiben. Was an diesem Befehl nun problematisch sein soll weiß ich leider nicht und kann ich mir gerade auch selber nicht so vorstellen. In unseren Befehlssatzdatenblättern die wir zur Verfügung gestellt bekommen haben, steht zu einer etwaigen Problemtik diesen Befehls leider auch nichts.

    Dementsprechend verhält es sich mit dem Befehl "mov O_Flag". Hier sollen wir laut Aufgabe nachdem ein Overflow aufgetreten ist eine 1 schreiben. Da der Assemblierer aber erst nach dem ein Overflow aufgetreten ist (zumindestens an den prägnanten Stellen an denen ein Overflow auftreten kann; falls ein Overflow auftritt springt er ja dann mit dem Befehl JO an die Marke "Overflow"), an der Marke "Overflow" weiterliest, schreibt er auch erst dann eine 1 in die Variable O_Flag. Ich weiß ebenfalls nicht was daran problematisch sein soll.

    Du schreibst:

    Und obwohl der Turbo Debugger eine recht gute Hilfe ist, empfiehlt sich der Einstieg in Asm eher über Debug und Fasm. Wenn du deine ersten Gehversuche mit debug (in jedem Windows dabei) machst, merkst du gleich, was auf unterster ebene geht, und was nicht, und du weißt, wie modernere Assembler wie Masm32, Masm, Nasm, Yasm, Fasm, oder gas dir die Arbeit erleichtern, und worin sie sich unterscheiden.

    Kannst du vielleicht genauer drauf eingehen? Findest du ich sollte bzw. muss mit dem Windowseigenen Debugger arbeiten um einen wirklich guten Einstieg in Assembler zu bekommen? Was sind die anderen Debugger? Was können die besser als der TASM? So wie ich das verstehe ist der FASM die Weiterentwicklung des TASM, oder?



  • Sorry, jetzt hab ich eine Frage vergessen: Ich möchte nun mal einen Overflow herbeiführen, damit ich im Debugger sehe wie das Overflowflag gesetzt wird. Wie mache ich das geschicktesten bzw. wie muss ich die Zahlen wählen, damit z.B. nach der Addition das O-Flag gesetzt wird?



  • bandchef schrieb:

    Sorry, jetzt hab ich eine Frage vergessen: Ich möchte nun mal einen Overflow herbeiführen, damit ich im Debugger sehe wie das Overflowflag gesetzt wird. Wie mache ich das geschicktesten bzw. wie muss ich die Zahlen wählen, damit z.B. nach der Addition das O-Flag gesetzt wird?

    z.B: mit einem Byte lassen sich maximal 256 Zahlen darstellen (0 bis 255)

    mov al, 255
        add al, 7 ; Überlauf O-Flag wird gesetzt!
    

    😉



  • Mein Code sieht jetzt so aus:

    Daten SEGMENT								; hier beginnt das Segment mit dem Namen DATEN
    	A			DW	255h
    	B			DW	1h
    	C			DW	2h
    	Text		DB	"Ergebnis"
    	ERG			DW	0
    				DB	"Flag:"
    	O_Flag		DB	0
    				DB	"Zahl:"
    	Zahl		DW	0h
    ENDS										; hier endet das Datensegment
    ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    CODE SEGMENT								; hier beginnt das Segment mit dem Name CODE
    	Anfang:
    		mov AX,Daten						; Die Segmentadresse "Daten" kommt in AX
    		mov DS,AX							; "Daten" kommt in DS
    
    		mov AX,A
    		mov BX,B
    		sub AX,BX
    		jo Overflow
    
    		mov BX,C
    		add AX,BX							; (A-B)+C
    		jo Overflow
    		mov ERG,AX							; speichere Ergebnis
    

    Die gefährliche Stelle ist ja hier jetzt eigentlich die Addition. Er addiert aber trotzdem brav +2 und geht über die 255 drin...

    Was mach ich falsch?



  • @ Otto8 Nein, das stimmt nicht, hier wird das Carryflag gesetzt.

    @bandchef

    Es ist vielleicht nicht so schlecht, wenn du die Tasm Progamme aus dem Unterricht erstmal versuchst, nach debug umzusetzten. Was zu schwierig ist, wie z.B. inc Zahl, das läßt du es erstmal bleiben.

    Wie die Flags reagieren, kannst du dir super in debug.exe (oder debug.com) anschauen. Wenn man im Konsolenfenster von debug ist, und den blinkenden Unterstrich sieht, dann kann man z.B. ? eingeben und bestätigen um die Liste der Kurzbefehle zu sehen.

    mit r kannst du dir die Register anzeigen lassen
    mit rax oder rbx oder rip usw. kannst du werte in die Register laden
    mit e 100 schreibst du Hexcodes in den Speicher bei Adresse 100. (es erscheint eine Art Hexeditor)(Leertaste weiter, Return zum Hinausgehen)
    Beispiel: gib ein e100 und dann 29 (Leertaste) d8 (Enter)
    und dann gib ein: r
    Normalerweise sieht man u.a. den asm Befehl sub ax,bx
    dann lädst du den Wert 8000 nach Ax mit rax:
    dann lädst du den Wert 1 nach bx mit rbx

    mit t kannst du den Code schrittweise durchgehen, also mach einmal t
    (und dann schau dir die Register an, und die Flags)
    dann stellst du den Instructionpointer zurück auf 100 mit rip

    jetzt kannst du andere Werte in die Register laden, alles nochmal wie eben machen, nur mit anderen Zahlen, und die Flags beobachten

    mit dem buchstaben a kannst du assemblerbefehle direkt eingeben.

    Den Professor würde ich einfach mal fragen, ob es nicht möglich wäre, den Kurs mit Fasm fortzusetzten. Für Fasm sprechen mehrere Gründe, u.a. einfache Syntax, Einsteigerfreundlich, 64bit und SSE Unterstützung. Man kann ja den Fasmcode trotzdem mit dem Turbodebugger anschauen, aber in der Regel reicht debug.
    Gegen Tasm spricht: veraltete Syntax, kommerzielles Produkt, vergriffen.



  • Ich hab hier nochmal ein Programm das auf meinem Übungszettel steht.

    Hier der Code:

    ;***************************************************************************************
    %noctls ;		Listing-Steueranweisungen werden nicht im Listing ausgegeben
    %noincl ;		Include-Dateien werden nicht im Listing ausgegeben
    INCLUDE MACROS.ASM
    ASSUME CS:CODE, DS:DATA
    ;--------------------------------------------------------------------------------------------
    MKAND EQU	0FFh ; Multiplikand ist Konstante mit Wert 255
    MKATOR EQU 	0FFh ; Multiplikator ist Konstante mit Wert 255
    ;---------------------------------------------------------------------
    DATA SEGMENT
    
    PROD 		DD		00000000h
    MPROD		DD		0h
    
    DATA ENDS
    ;---------------------------------------------------------------------
    CODE SEGMENT
    
    START:		mov AX,DATA								; Die Segmentadresse "Daten" kommt in AX
    			mov DS,AX								; "Daten" kommt in DS
    
    			mov CX,0FFh								; 255 wird in CX geschrieben -> Abbruchkriterium für LOOP
    			Marke1:
    			mov AX,MKAND							; MKAND wird in AX geschrieben
    			mov BX,MKAND							; MKAND wird in AX geschrieben
    			add ax,bx								; AX und BX werden addiert
    			LOOP Marke1
    
    		Terminate_Program					; Rückkehr zum Betriebssystem
    ENDS
    
    END Start
    

    Wenn ich das Programm jetzt assembliere kommen keine Fehler. Wenn ich es linken lasse, dann sagt er mir "Bad Object Code". Ich hab das jetzt mal ignoriert und trotzdem mit dem debuggen weitergemacht und da meldet er mir, dass das Programm nicht geöffnet werden kann.

    Was ist daran jetzt falsch?

    Das Programm soll eine Multiplikation aufgrund wiederkehrender Addition durchführen. Es soll mir die Werte 255 mit 255 multplizieren. Der LOOP Befehl funktioniert ja so, indem man ihm in das Register CX die Anzahl der Schleifendurchläufe angibt. Das hab ich ja mit 0FFh getan. Ich weiß echt nicht was falsch ist; ich schau mir jetzt das Programm schon fast seit 1h an...

    Kannst du mir helfen? Danke!



  • Ich hab jetzt nochmal meinen Code überarbeitet. Jetzt tu er (denke ich) schon mal das was er soll, nämlich addieren. Er bringt mir aber jetzt in der Zeile 32 einen Fehler das der Typ eines Operanden nicht passen soll. Ich weiß aber nicht was damit gemeint ist, da ich nicht blicke wo der Fehler liegen soll. MPROD ist ja im Datensegment korrekt geschrieben...; an AX kann's auch nicht liegen, da steht ja mein Ergebnis drin...

    ;***************************************************************************************
    %noctls ;		Listing-Steueranweisungen werden nicht im Listing ausgegeben
    %noincl ;		Include-Dateien werden nicht im Listing ausgegeben
    INCLUDE MACROS.ASM
    ASSUME CS:CODE, DS:DATA
    ;--------------------------------------------------------------------------------------------
    MKAND EQU	0FFh ; Multiplikand ist Konstante mit Wert 255
    MKATOR EQU 	0FFh ; Multiplikator ist Konstante mit Wert 255
    ;---------------------------------------------------------------------
    DATA SEGMENT
    
    PROD 		DD		00000000h
    MPROD		DD		00000000h
    
    DATA ENDS
    ;---------------------------------------------------------------------
    CODE SEGMENT
    
    START:		mov AX,DATA								; Die Segmentadresse "Daten" kommt in AX
    			mov DS,AX								; "Daten" kommt in DS
    
    			mov CX,0C7h								; 255 wird in CX geschrieben -> Abbruchkriterium für LOOP
    
    			mov AX,MKAND							; MKAND wird in AX geschrieben
    			mov BX,MKAND							; MKAND wird in BX geschrieben
    			add AX,BX								; AX und BX werden addiert
    
    			Marke1:									; Marke1 der LOOP-Schleife
    			add AX,BX								; wiederholte Addition
    			LOOP Marke1								; LOOP-Schleife
    			mov MPROD,AX							; Speichern des Ergebnisses in MPROD
    
    		Terminate_Program					; Rückkehr zum Betriebssystem
    ENDS
    
    END Start
    


  • So, ich glaub ich hab das Problem jetzt selbst gelöst. MPROD ist als DD angegeben DD hat aber 4Byte; AX hat aber nur 2Byte deswegen gibts nen typ konflikt



  • otto8 schrieb:

    mov al, 255
    add al, 7 ; Überlauf O-Flag wird gesetzt!
    
    mov al, 127
    add al, 1 ; Überlauf O-Flag wird gesetzt!
    

    ^^ So geht das. 🙂


Anmelden zum Antworten