Problem bei Einlesen von Zeichen
-
Also ich bin nun etwas weiter vorgestoßen und hänge gerade beim Einlesen fest. Dieser Code:
TITLE Programmbibliothek MODEL SMALL,CPP IDEAL P386 STACK 1024 DATASEG cHeadline_01 db '===========================================',0Ah,0Dh,'$',00h cHeadline_02 db 'Programmbibliothek 1.0.0 (c) by Kevin Jakob',0Ah,0Dh,'$',00h cText_01 db 'Bitte geben Sie ihren Namen ein : $',00h cInput db 32h db 00h db 54 DUP (?) CODESEG start: STARTUPCODE call WriteText,OFFSET cHeadline_01 call WriteText,OFFSET cHeadline_02 call WriteText,OFFSET cHeadline_01 call WriteText,OFFSET cText_01 mov ah,0Ah lea dx,[cInput] int 21h mov es,dx mov di,SIZE cInput dec di mov al,'$' stosb call WriteText,OFFSET cInput call ExitProg EXITCODE PROC WriteText near Output:word mov ah,09h mov dx,[Output] int 21h ret ENDP PROC ExitProg mov ah,04Ch int 21h ret ENDP END start
funktioniert nicht. Ich weiß nichtmal ob etwas eingelesen wird, jedoch habe ich eher ein Problem mit dem Anhängen des '$'. Wo liegt mein Denkfehler?
Das FAQ hat mir dabei nicht wirklich weitergeholfen
EDIT:
Der Assemblierer ist TASM!
-
bin den code mal durchgegangen und hab mich zuerst hier schlau gemacht:
http://www.fh-wedel.de/~bek/asm/int21.html#int210awie im link beschrieben, wird der offset des puffers in dx geschrieben. an dieser position steht dann auch die größe des puffers, also für wie viele zeichen er platz bietet. nach dem interrupt steht in der nächsten adresse die tatsächliche anzahl an zeichen/bytes die eingelesen wurde. ich würde dann zuerst platz für 32h (50) zeichen reservieren, wobei du den kompletten block mit '$' initialisierst.
cInput db 32h dup ('$')
damit das letzte zeichen (stringende) beim einlesen nicht überschrieben wird, gibst du dem interrupt ein zeichen weniger an
mov ax, 31h mov bx, offset cInput mov [bx], ax
(ich glaube den blöden umweg muss man so gehn)
das sollte jetzt nach startupcode folgen, wobei warscheinlich auch noch das enter hintendran gehängt wird (habe da 2 widersprüchliche links gefunden), also u.u. nur eine 30h reinschreiben. wenn jetzt der text im puffer steht musst noch ein enter ausgeben (10, 13) da sonst die zeile "bitte geben Sie ihren Namen ein:" überschriben wird. hab da mal sowas gemacht:proc endl near push ax push dx mov ah, 02h mov dl, 13 int 21h mov dl, 10 int 21h pop dx pop ax ret endp endl
nach dem enter kannst du den string direkt ausgeben, ohne noch ein '$' anhängen zu müssen. bei einem uninitialisierten block dürftest du aber so an das letzte zeichen drankommen
mov bx, offset cInput+1 add bx, [bx]
(ungetestet)
mich würde aber noch eins interessieren: was willst du mit zeile 12/13 bezwecken?
-
Naja ich hatte gelesen das bei int21h Funktion 0Ah einen sozusagen formatierten string erwartet, also das erste Byte enthält die Zeichen, die eingelesen werden können, das zweite Byte die tatsächlich eingelesene Anzahl. Daher hab ich das so gemacht und dann hinten dran noch einen speicherbereich mit 50 Zeichen, naja hab ich vielleicht falsch irgendwo aufgeschnappt, zumindest diese Schreibweise...
EDIT:
So habe jetzt den String schonmal ordnungsgemäß formatiert, hoffe ich zumindest. Folgender Code:TITLE Stringtest IDEAL P386 MODEL SMALL STACK 1024 DATASEG cOutput db 'Geben Sie ihren Namen ein : $' cInput db 07h,00h,010h dup (' '),'Test',0Dh,0Ah,'$' CODESEG start: mov ax,@data mov ds,ax mov ah,09h lea dx,[cOutput] int 21h mov ah,0Ah lea dx,[cInput] int 21h mov ah,02h mov dl,0Dh int 21h mov dl,0Ah int 21h mov ah,09h lea dx,[cInput] int 21h mov ax,4C00h int 21h END start
Nun mein problem, er liest zwar aus dem 1. Byte von cInput, wie viele Zeichen man eingeben kann, jedoch landet davon nichts in cInput selbst, wenn ich also(wie im Code zu sehen) das dann ausgeben lasse, so steht dann nur das Test, dann der Zeilenumbruch und fertig. Was fehlt noch?
-
Kevinus schrieb:
Naja ich hatte gelesen das bei int21h Funktion 0Ah einen sozusagen formatierten string erwartet,
ne. es wird einfach nur der ascii-code der zeichen in einem puffer gespeichert, wobei das problem ja nicht an der formatierung lag.
Kevinus schrieb:
also das erste Byte enthält die Zeichen, die eingelesen werden können, das zweite Byte die tatsächlich eingelesene Anzahl.
ja ist ja soweit auch korrekt, bzw. siehe link dort stehts auch. das erste zeichen ist ja die startadresse, also praktisch das element mit dem index 0 und dort soll auch die größe des speicherblocks stehn.
Kevinus schrieb:
Daher hab ich das so gemacht und dann hinten dran noch einen speicherbereich mit 50 Zeichen
ja genau, aber das hab ich nicht verstanden. warum teilst du (wie jetzt auch wieder) den speicher auf? und du brauchst noch ein enter vor der ausgabe. der cursor steht nämlich immer noch in der zeile "bitte namen eingeben" und das wird dann überschrieben.
Kevinus schrieb:
Nun mein problem, er liest zwar aus dem 1. Byte von cInput, wie viele Zeichen man eingeben kann
wie soll er das lesen? du schreibst es ja gar nicht rein. hier mal ein code der sich mit dem tasm problemlos assemblieren lassen sollte.
TITLE Stringtest IDEAL P386 MODEL SMALL STACK 1024 DATASEG cOutput db 'Geben Sie ihren Namen ein : $' cInput db 32h dup ('$') CODESEG start: mov ax, @data mov ds,ax mov bx, offset cInput mov ax, 30h ; zur sicherheit wegen dem enter mov [bx], ax ; beim mov befehl sind nicht alle kombinationen möglich, deshalb der umweg. mov ah, 09h mov dx, offset cOutput int 21h mov ah, 0Ah mov dx, offset cInput int 21h call endl ; newline wird ausgegeben mov ah,09h mov dx, offset cInput+2 ; die ersten beiden bytes sind ja schon belegt. int 21h mov ax, 4C00h int 21h proc endl near push ax push dx mov ah, 02h mov dl, 13 int 21h mov dl, 10 int 21h pop dx pop ax ret endp endl END start
ob du jetzt nur 2 oder 20 zeichen eingibst, das folgende is immer ein '' und dann is schluss.
-
Aber auch bei Daniel's Homepage steht doch:
Das erste Byte des Puffers gibt an, wie viele Zeichen (inklusive des Carriage Return am Ende) der Puffer maximal aufnehmen kann. Es muß von dem Programm vor Aufruf der Funktion in den Puffer eingetragen werden, damit die Funktion weiß, wie viele Zeichen sie maximal einlesen darf.In die Speicherstelle 1 trägt DOS nach Beendigung der Eingabe die Anzahl der eingelesenen Zeichen inklusive des Carriage Return ein.
Ab der Speicherstelle 2 befinden sich nach der Beendigung der Funktion die eingelesenen Zeichen.
MMm deswegen dachte ich, ich muss das erste Byte mit der Anzahl der zeichen, die eingelesen werden können, belegen und das zweite Byte mit 0, wo dann eingetragen wird, wie viele Zeichen eingelesen wurden, ab 3. Byte folgt dann die eingelesene Zeichenkette, hab ich da was falsch verstanden?
Du lädst in den bx register die Anzahl der Zeichen, was bringt das? Greift den der Einleseinterrupt auf bx überhaupt zu, weil auf Daniel's Homepage finde ich kein Wort über den bx register, im Zusammenhang mit diesem Interrupt 0Ah
-
Kevinus schrieb:
Aber auch bei Daniel's Homepage steht doch:
Das erste Byte des Puffers gibt an, wie viele Zeichen (inklusive des Carriage Return am Ende) der Puffer maximal aufnehmen kann. Es muß von dem Programm vor Aufruf der Funktion in den Puffer eingetragen werden, damit die Funktion weiß, wie viele Zeichen sie maximal einlesen darf.Stimmt ja so auch.
Kevinus schrieb:
In die Speicherstelle 1 trägt DOS nach Beendigung der Eingabe die Anzahl der eingelesenen Zeichen inklusive des Carriage Return ein.
Ab der Speicherstelle 2 befinden sich nach der Beendigung der Funktion die eingelesenen Zeichen.
War vielleicht ein Missverständnis. mit index 0 meinte ich die erste Speicherstelle, ja. dannach in der folgenden die tatsächliche anzahl einegelesener zeichen.
Kevinus schrieb:
MMm deswegen dachte ich, ich muss das erste Byte mit der Anzahl der zeichen, die eingelesen werden können, belegen und das zweite Byte mit 0.
aber durch die zahlen zwischen den kommata weist du doch den speicherstellen keine werte zu. du reservierst doch nur speicher und vor allem wie kommst du auf die 0? meinst du da addiert die funktion eine zahl zum bisherigen wert der an dieser speicherstelle steht? ne, da kann drinstehn was will.
Kevinus schrieb:
ab 3. Byte folgt dann die eingelesene Zeichenkette, hab ich da was falsch verstanden?
wenn man das, so wie ich, als array betrachtet isses das zweite element
.
aber ich weiss was du meinst, also nein, du hast es schon richtig verstanden.Kevinus schrieb:
Du lädst in den bx register die Anzahl der Zeichen, was bringt das? Greift den der Einleseinterrupt auf bx überhaupt zu, weil auf Daniel's Homepage finde ich kein Wort über den bx register, im Zusammenhang mit diesem Interrupt 0Ah
der greift nicht auf bx zu. aber wenn ich den kompletten block mit '' initialisiere, dann steht im ersten ja immer noch nicht die größe des blocks sondern ein '' (ascii wert 36, es soll aber eine 50 (hex 32h) drinstehn). also muss ich dieser speicherstelle noch extra einen wert zuweisen. und das ist dann die größe, nur akzeptiert der mov befehl eben nicht jede beliebige kombitnation. ich kann anscheinend nicht sowas schreiben
mov speicher, wert
und muss deshalb den umweg über das register gehn.
hat denn mein code bei dir geklappt?
-
Joar hat geklappt ich hatte einen Denkfehler:
Ich dachte mitcInput db 07h,00h,010h dup (' '),'Test',0Dh,0Ah,'$'
kann ich einfach wie normal Zeichen aneinander hängen, was ja auch geht bei normalen db's. Jedoch kann ich dann natürlich nicht mittendrin mit dup so und so viele Byte reservieren. Da hat er dann was verkackt *G*. Aber jetzt weiß ich wie. Mit bx hat sich auch erledigt, war ebenfalls ein Logikfehler von mir. Thx für die Hilfe.