String einlesen und ausgeben
-
Hallo
Ich habe (wieder mal) ein kleines Problem in ASM.
Wie ich einen Text einlese weiss ich, nur wie kann ich ihn wieder ausgeben?? Mit:
mov ah,09H
mov dx,OFFSET Variable_des_Strings
int 21Hwird mir nur ASCII Zeichen Müll angezeigt. Wie kann ich einen eingelesenen String terminieren? Wird beim Einlesen die Anzahl der gelesenen Zeichen in irgendein Register geschrieben? Dann könnte man ja OFFSET+Anzahl+1 auf $ setzen. Kann ich einfach so auf eine Speicherstelle zugreifen und die verändern, sofern mein Prog das darf oder ich im RM bin?
thx im Voraus
Noob
-
Ich vermute mal, du verwendest zum Einlesen ah=0A int 21...
Dann schau dir mal dieses Beispiel an, falls du das noch nicht getan hast. Ich hoffe, das klaehrt die Frage, wie die Laenge des Strings uebergeben wird, etc. sonst nochmal fragen
Im RM kannst du einfach irgendwo in den Speicher schreiben, stimmt. Dabei kann es jedoch leicht passieren, dass du den PC zum Absturz bringst. Solange du aber im Segment deines Programms bleibst und den Code nicht ueberschreibst, passiert da nichts.sofern mein Prog das darf
Wieso sollte es nicht
Jedes vernuenftige PM-Interface weist deinem Programm mindestens ein beschreibares Datensegment zu.
-
Ich hatte jetzt leider meinen PC einige Zeit nicht, meine HDD hat sich den Kopf angehaut, habe gestern versucht weiter zu kommen.
Ich kann zwar einen String einlesen und ausgeben, aber auch nur mit einem schlechten Trick. Ich kriege nicht die ersten beiden Zeichen weg oder hinten ein $(ASCII 36) drann.
mit folgendem Code kann ich zwar einlesen und ausgeben, aber es ist nur ein schlechter Trick.DATEN SEGMENT
TempStr DB 0FH
Str2 DB 0FH
DATEN ENDSSTAPEL SEGMENT BYTE STACK
DW 128 DUP(0)
STAPEL ENDSCODE SEGMENT
ASSUME CS:CODE,DS:DATEN,ES:NOTHING,SS:STAPEL
START:
mov ax,DATEN
mov ds,axmov dx,OFFSET TempStr
mov ah,0AH
int 21Hmov [Str2],36
mov ah,09H
mov dx,OFFSET Str2
int 21HAus: mov ah,4CH
int 21HCODE ENDS
END STARTIch würd gern aus der Eingabe nur den Eingegeben Text mit einem $ hinten drann machen.
thx im Voraus
NoobP.S. Wie kann man eigentlich ohne INT 21H Text ausgeben? (Ich habe nicht vor inerhalb der nächsten 10 Jahre den Versuch zu starten ein OS zu schreiben, mich interessierts halt)
-
Wundert mich ehrlichgesagt, dass dabei ueberhaupt was ausgegeben wird
Zuersteinmal solltest du die Datensegmente (vor allem den Stack!) hinter das Codesegment setzen. Als kleinen Bonus sollte das Sogar dein .exe-File um einiges verkleinern
Bei deinem Code wird der Input vom Keyboard in den Stack geschrieben. Sowas ist generell fuer die allgemeine Stabilitaet nicht gesund. Abhilfe: Uninitialisierte Byte array (in deinem Fall reichen 16 Byte) dahintersetzen.
*
mov [Str2],36
*
was soll das bringen? Damit ueberschreibst du lediglich die Laenge des eingelesenen Strings...--
ohne int 21h Text ausgeben:
Ich nehme mal an, du willst voellig ohne Interrupts Text ausgeben?(sonst gaebe es da zB. noch int 10h):
Der VGA Textbuffer liegt normalerweise bei B8000.
Ein Hellgelber Text auf blauem Untergrund (zB. Hallo!), mit Position in der linken oberen Bildschirmecke, wuerde im Textbuffer so aussehen:
B8000: "H",1Eh,"a",1Eh,"l",1Eh,"l",1Eh,"o",1Eh,"!",1Eh
Also immer zuerst das Zeichen und dann sein Farbattribut.
(Hintergrundfarbe*16+Zeichenfarbe => hier 16*1+14)Hier habe ich also deinen Code mal ein bisschen umgebastelt. Gibt jetzt auch Text ohne int 21h aus.
CODE SEGMENT
ASSUME CS:CODE,DS:IDATEN,ES:NOTHING,SS:STAPEL
START:
mov ax,IDATEN
mov ds,axmov dx,OFFSET MaxInput
mov ah,0AH
int 21Hmov ax,0B800h ;Segment des Textbuffers
mov es,ax
mov ah,02h ;gruener Text auf schwarzem Hintergrund
mov si,offset StrLen
lodsb ;laenge des eingelesenen Strings laden
xor di,di ;links oben am Bildschirmrand anfangen...
xor cx,cx
mov cl,al
;si zeigt jetzt zum Anfang des eingelesenen Texts. (offset InputStr)
Ausgabeschleife:
lodsb ;Zeichen vom Eingabestring laden
stosw ;mit Farbattribut (ah) in den Textbuffer schreiben.
loop AusgabeschleifeAus: mov ah,4CH
int 21HCODE ENDS
DATEN SEGMENT
MaxInput DB 0FH ;maximal einlesbare chars: 14 (+enter)
StrLen DB ? ;der 2. Byte wird vom int 21h gesetzt => muss nicht initialisiert werden.
InputStr DB 10h DUP (?) ;auch uninitialisiert: hier wird der Text abgelegt.
;Anm.: Uninitialisierte Variablen muessen IMMER hinter initialisierten Daten stehen (code oder Daten), sonst wird ihnen der Wert 0 zugewiesen.DATEN ENDS
STAPEL SEGMENT BYTE STACK
DW 128 DUP (?) ;? bedeutet, dass uninitialisierter Speicher fuer den Stack benutzt wird. Macht das .exe-file um einiges kleiner...
STAPEL ENDSEND START
-
Groooosses thx erstmal.
mov [Str2],36 war die erste Zeile eines geplanten Versuches, bei dem ich in der zweiten Zeile schon merkte dass er Müll war, vergass die zu löschen. Mich wundert das auch, dass was ausgegeben wurde.
Es muss nicht ganz ohne Interrupts sein, hat mich halt interressiert. Dein Code geht super, hab mich schon mit diversen Farben gespielt, nur einen kleinen "Haken" hat die Sache. Den bunten Text schreiben geht ganz gut, ausser es wurde schon was von DOS an die Position geschrieben(durch´s "raufsachieben" der Zeilen), dann tut sich nix.
Gehört lodsb und stosw eigentlich zur Intel Syntax oder geht das nur unter DOS?Sorry für die dummen Fragen und thx
Noob
-
lodsb/stosw und Konsorten gehören alle zur Intel-Syntax
Generell lässt sich sagen, dass alles zur Intel-Syntax gehört was man als Befehl in einem Assembler-Prog benutzt. OS-Spezifisch wirds erst in dem Moment, wo du externe Funktionen oder interrupts aufrufst (insbesondere int 21h für DOS :))
-
Das sich der Text nur so lange ausgeben lässt, bis schon was dort steht hab ich schon übergangen.
In dem Beispiel Code wurde immer in die oberste Zeile gezeichnet, wenn ich aber Enter drücke, wird die Zeile oben rausgeschoben und das wars. Jetzt hab ich den Wert in di verändert und Schreibe irgendwo in die 2. Zeile.
Wie adressiert der Textbuffer? Ich kann zwar die Position des Textes verändern, aber der landet dann irgendwo.
Der eingelesene String steht in MaxInput soweit ich das gesehen habe.
Theorethisch könnte ich dann mit mov [MaxInput + 2], 65 das erste gelesene Zeichen ändern (auf ein A), oder?Ich fahr eh bald weg, dann geh ich euch eine Woche lang nimmer auf die Nervern.
mfg
Noob
-
Ich glaube, du hast da was falsch verstanden:
Natuerlich kannst du auch dorthin Text setzen, wo DOS schonmal geschrieben hat. Das Problem bei diesem Code ist folgendes: wenn der Cursor im DOS Prompt auf der letzten Zeile ist, schiebt DOS beim Oeffnen einer neuen Zeile/beim Verlassen des Programms den Bildschirm um eine Zeile nach oben. So wird direkt nach der Ausgabe die erste Zeile schon wieder geloescht => du siehst nichts davonTextbuffer Addressieren...
Normalerweise hat so ein Textfeld Horizontal 80 und Vertikal 25 Zeichen. Der Rest ist jetzt eigentlich einfach : Textposition=(Y*80+X)*2
oder auch:
ax=Y
mov bx,ax
shl ax,06h
shl bx,04h
add ax,bx
add ax,X
add ax,ax
ax=Textpositionund next:
Eigentlich liegt der Text eher bei offset InputStr...
Aber mit deinem "MaxInput+2" triffst du auch genau das offset von InputStr, wuerde also auch funktionieren... ist halt nur ein bisschen unuebersichtlich.Also: Viel Spass im Urlaub
-
Anfangs hab ichs wirklich falsch verstanden, aber dann
wenn ich aber Enter drücke, wird die Zeile oben rausgeschoben und das wars
hab ich´s gecheckt.
Morgen gehts los mit Urlaub, hab sogar ein alten 386 25MHz(eher Kg) Laptop mit, sonst könnte mir unter Umständen noch langweilig werden, aber das passiert sicher nicht.mfg und THX
Noob