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 21H

    wird 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 ENDS

    STAPEL SEGMENT BYTE STACK
    DW 128 DUP(0)
    STAPEL ENDS

    CODE SEGMENT
    ASSUME CS:CODE,DS:DATEN,ES:NOTHING,SS:STAPEL
    START:
    mov ax,DATEN
    mov ds,ax

    mov dx,OFFSET TempStr
    mov ah,0AH
    int 21H

    mov [Str2],36

    mov ah,09H
    mov dx,OFFSET Str2
    int 21H

    Aus: mov ah,4CH
    int 21H

    CODE ENDS
    END START

    Ich würd gern aus der Eingabe nur den Eingegeben Text mit einem $ hinten drann machen.

    thx im Voraus
    Noob

    P.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,ax

    mov dx,OFFSET MaxInput
    mov ah,0AH
    int 21H

    mov 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 Ausgabeschleife

    Aus: mov ah,4CH
    int 21H

    CODE 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 ENDS

    END 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 davon 😉

    Textbuffer 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=Textposition 😮

    und 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


Anmelden zum Antworten