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 gefundenErstmal 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 klapptsWeite 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 operandDas 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_STACKIch 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 kommentiertVielleicht 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