Autor Thema: kurzes NASM-Programm  (Gelesen 5231 mal)

bscreator

  • Gast
Gespeichert
« am: 14. March 2010, 22:50 »
Hallo,
hab ein kleines Programm geschrieben, das Tastatureingaben mit dem String "exit" vergleicht. Das Programm soll erst beendet werden, wenn "exit" eingegeben wurde.

Problem :
Es erscheint zwar "Press any key to continue..." (Programm beendet) aber der vorherige String msg ("richtige Eingabe") wird nicht ausgegeben.

Finde leider keinen Fehler, wisst ihr wo der Fehler liegt ?

Hier der komplette Source:
BITS 16
ORG 0x0100

jmp start

command db 0
msg db 10,'richtige Eingabe',13,10,0
com_end db 'exit',0

start:
call input
lea si,[com_end]  ;Lade "exit" in DS:SI
call compare   ;Vergleiche Tastatureingabe mit "exit"
cmp al,1   ;AL=1 ?
je exit_func      ;falls ja, springe zu Funktion exit_func
jmp start


;*************************************
;Funktion für Tastenein- und -ausgaben
;*************************************
input:
xor di,di
input_loop:
mov ah,0x00    ;Funktion Tastatureingabe
int 0x16
cmp al,0x0D ;Carriage-Return ?
je input_end ;Falls ja, Ende
mov [command+di],al ;Zeichen in command schreiben
mov ah,0x0E
mov bx,0x0007
int 0x10
inc di ;nächstes Byte von command
jmp input_loop

input_end:
mov al,0
mov [command+di],al  ;0 ans Stringende hängen
ret
;***************************************


;***************************************
;Funktion zum Vergleichen zweier Strings
;***************************************
compare:
xor di,di                                  ;DI=0
compare_loop:
lodsb                                      ;Lade Byte von String com_end
mov ah,[command+di]           ;Lade Byte von command
cmp ah,al                               ;Buchstaben gleich ?
jne compare_false                 ;falls nein, Ende
cmp al,0                                 ;Byte = 0
je compare_true                    ;falls ja -> Stringende erreicht -> Strings gleich
inc di                                      ;nächstes Byte in command auswählen
jmp compare_loop

compare_true:
mov al,1
ret
compare_false:
mov al,0
ret
;***************************************



;***************************************
;Funktion zum Ausgeben eines Strings
;(dieselbe wie in  lowlevel, Ausgabe 1)
;***************************************
print_string:
lodsb
or al,al
jz print_string_end
mov ah,0x0E
mov bx,0x0007
int 0x10
jmp print_string

print_string_end:
ret
;***************************************



;***************************************
;Funktion exit_func
;***************************************
exit_func:
mov si,msg           
call print_string
retf
;***************************************


Vielen Dank,
bsc

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 14. March 2010, 23:24 »
Das retf in exit_func sollte ein ret sein. Dann funktionierts bei mir (abgesehen von der Sache mit dem Puffer für command.)
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #2 am: 15. March 2010, 16:57 »
Zitat
Das retf in exit_func sollte ein ret sein. Dann funktionierts bei mir (abgesehen von der Sache mit dem Puffer für command.)
Also wenn ich das retf durch ret ersetze, kommt nach der Eingabe von exit nicht "richtige Eingabe", sondern "xit", also auf deutsch :
"exitxit Press any key to continue..."

Aber ich versteh immer noch nicht die Sache mit dem command. Für den String "richtige Eingabe" reicht doch auch eine Byte Variable aus. Warum gehts dann nicht auch für command ?

Bzw. Wie würdet ihr es machen ?
« Letzte Änderung: 15. March 2010, 17:03 von bscreator »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 15. March 2010, 17:24 »
Für den String "richtige Eingabe" reicht nicht ein Byte aus. Die Zeichenkette ist 20 Bytes oder so lang, und belegt auch direkt diesen Speicherplatz.

Beispiel: db "foobar" ist dasselbe wie db 'f', 'o', 'o', 'b', 'a', 'r' und beides belegt 6 Bytes.

Das "e" von "exit" landet in dem Byte, das du in der Zeile "command db 0 reserviert hast. Das "x" überschreibt dann bereits die 10 in der nächsten Zeile, und das "i" dann das "r", und so weiter. Du musst also mehr Speicher für command reservieren.

Beispiel:
command db 0, 0, 0, 0, 0

Das reserviert 5 Bytes, in die das "exit" und das terminierende Nullbyte reinpassen. Das ist natürlich etwas knapp, und du kannst da noch mehr Nullen hinschreiben, oder den times-Präfix nutzen.

Beispiel, das 100 Bytes reserviert:
command: times 100 db 0
« Letzte Änderung: 15. March 2010, 17:26 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #4 am: 15. March 2010, 17:42 »
Hab jetzt mal die Zeile command db 0 durch command: times 5 db 0 ersetzt.
Wenn ich jetzt bspw. "tester" eingebe, Return drücke und dann "exit" eingebe, kommt nach exit noch ein "r" also :
testerexitr Press any key to continue...

Warum wird der String "richtige Eingabe" (msg) nicht ausgegeben ?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 15. March 2010, 17:48 »
Weil 5 zu wenig ist. Das Wort Tester ist 6 Zeichen lang, plus 1 für das terminierende Nullbyte macht 7 Bytes. Versuch es einfach mal mit mehr Bytes.
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #6 am: 15. March 2010, 18:04 »
Da hast du recht. Mit mehr Bytes funktioniert es. Aber 100 Bytes kann ich nicht für eine Variable reservieren, das ist zu viel für ein Real-Mode OS.
Wieviel würdest Du reservieren ?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 15. March 2010, 18:08 »
Mindestens die Länge des längsten gültigen Befehls plus 1. Und dann bei der Eingabefunktion drauf achten, dass nicht mehr Zeichen eingegeben werden, damit nichts aus Versehen überschrieben wird.

Zum Vergleich: command.com (nicht cmd.exe) hat auch eine Begrenzung von rund 120 Zeichen.
« Letzte Änderung: 15. March 2010, 18:10 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

 

Einloggen