[TASM] Sortieren eines Array funktioniert nicht richtig
-
Ich brauche wieder Hilfe bei Assembler
Es sollen Elemente sortiert und aufsteigend ausgegeben werden. Ich habe das mit Countingsort gemacht. Allerdings zeigt er dann ins Nirvana. Wenn ich den Stack nicht imlementiere, erscheint eine Warnung, dass kein Stack da ist. Ich glaube aber, dass das nicht unbedingt wichtig ist.
.model small ;.stack 100h org 100h .data len db 0 array db 255 dup(0) count db 256 dup(0) jumps .code start: mov ax,@DATA mov ds,ax ;Eingabe mov ah,0ah mov dx,offset array-2 int 21h ;Sortierung mit Hilfe des Countingsort xor si,si xor ax,ax mov al,[len] sort: xor bx,bx mov bl,byte ptr [array+si] inc [count+bx] inc si cmp si,ax jne sort xor si,si mov di,offset array how: xor cx,cx mov cl,[count+si] test cx,cx jz increm mov ax,si rep stosb increm: inc si cmp si,256 jne how mov byte ptr es:[di],'$' ;Ausgabe des Arrays mov ah,9 mov dx,offset array int 21h mov ah,7 int 21h cmp al,1 jnz quit quit: mov ah,4ch int 21h ret end start
-
1. Die Funktion 0Ah des Interrupts 21h braucht zwei Werte am Anfang des Eingabepuffers:
maxlen db 254 len db 0 array db 255 dup(0)
2. Der Befehl 'rep stosb' schreibt einen Block nach ES:DI. Du musst also noch ES initialisieren:
mov ax,@DATA mov ds,ax mov es,ax
Nach meinen groben Tests funktioniert es dann.
Die Sache mit dem Stack ist hier nicht wichtig, da er nicht benutzt wird. Du solltest ihn aber auf jeden Fall einrichten, sonst gibt es unerklärliche Effekte, wenn mal auf ihn zugegriffen wird.
viele grüße
ralph
-
dedmazay schrieb:
Ich brauche wieder Hilfe bei Assembler
Wie wäre es aber erstmal mit einem Blick mit dem Debugger?
mov ah,0ah mov dx,offset array-2 int 21h
Nicht gerade sehr aussagekräfig bei dieser Funktion. Was geht hier vor?
Ein Blick auf den Datendump hilfreich...
(und wer kein Interrupt Handbuch dabei hat, versteht das vielleicht auch nicht gleich sofort, z.B. wenn man ein Jahr später wieder draufguckt...)dedmazay schrieb:
mov bl,byte ptr [array+si]
Kann bl eigentlich auch word ptrs aufnehmen oder tbyte ptrs ?
dedmazay schrieb:
inc [count+bx] inc si cmp si,ax
Es ginge auch inc ah, bzw. cmp ah,al, da ja mit bytes gearbeitet wird...aber wie das jetzt handlen?
Z.B. ginge ja sowas wiemov cl,[len] mov bx,count ;aber (Count) mit Alignement, sonst gibts eventuell einen ;Überlauf... ;oder man nimmt lea wenn es zusätzlich noch was zu rechnen gibt. repl: cmp al,0dh ;wegen der Interruptfunktion 0A, die am Ende des Strings 0Dh setzt. jz out lodsb ;byte von DS:SI nach al, si=si+1 add bl,al ;der Zeiger auf den Hilfsarray (Count), für die statistische Datenerfassung inc [bl] ;Statistik sub bl,al loop repl
Und wenn man später wieder von hinten anfängt, braucht man nur die Direction verändern, und Si wird wieder heruntergezählt
Aufsummieren:
;den Wert in Si um 1 vermindern ;oder irgendwas mit cl rechnen, wegen dem ;Aufsummier-Loop 1 weniger wegen ;den ersten Bytes, die vor dem Loop aufsummiert werden. mov cx,si sub cx,1 ;und jetzt müsste man sowas machen können wie add [bl],[bx-1]; aber das geht überhaupt nicht, shit ! ;) ;also... mov al,[bx] ;oder ...*count... inc bl add [bx],al loop
dedmazay schrieb:
increm: inc si cmp si,256 jne how mov byte ptr es:[di],'$'
hier kann man sich das auch etwas einfacher machen, wir haben ja noch die Länge der 0Ah Interruptfunktion
dedmazay schrieb:
mov ah,7 int 21h cmp al,1 jnz quit quit: mov ah,4ch int 21h ret end start
Und was soll das? Und was hat der ret Befehl da unten zu suchen? Der macht vermutlich auch Ärger
Ganz allgemein: bei org 100h kann man ein .Com Programm erstellen, und braucht keine Segmenteinrichtung. Aber falls man die doch braucht, kann man sogar selber machen, allerdings braucht es dafür ein besseres Verständnis vom Real Mode.
fasm http://www.flatassembler.net/ macht es in dieser Phase recht einfach, einfach org 100h und assembliert den Code zum Com-Proggie. Auch directx Programmierung geht damit sehr gut.
Falls man das Programm später nochmal anguckt, dann ist eine Strukturierung, Kommentierung und aussagefähige Variablen usw. hilfreich
Man braucht für Funktion 0Dh vom Interrupt 21 2 Bytes (vorne) für Maximaleingabe (Max) und tatsächlichen gezählten Eingabebytes, hat ja rkhb auch schon gepostet.Statt array hätte man Inputstring und Outputstring oder "new order" schreiben können, um zu strukturieren bzw. Jahre später noch zu erkennen, was man eigentlich gemacht hatte.
Naja, und Windowsprogramme/Dosfenster kann man zum Teil mit der Maus so einstellen, dass sie offen bleiben, oder man bleibt gleich in der Konsole, schreibt z.B. mit Konsoleneditor wie dem Vi von Watcom und dann guckt man sich mit debug an, wie was läuft. Und man könnte auch im Programm selber transparent fragen: "nochmal?"
Bei Com Programmen gibt es übrigens nur (typischerweise) nur ein Segement (wie bei Windows eigentlich auch), so gesehen braucht man keinen stack. Dass Assembler (masm) darauf hinweisen, dass kein Stack da ist (nur ein Segment), ist ganz normal, aber keine Fehlermeldung.
-
nachtfeuer schrieb:
dedmazay schrieb:
mov bl,byte ptr [array+si]
Kann bl eigentlich auch word ptrs aufnehmen oder tbyte ptrs ?
Das geht mit bl nicht und deswegen genügt hier auch ein:
mov bl, [array+si]"
[quote="dedmazay"]
inc [count+bx]
Aber weil der Assembler in diesem Fall es nicht genau wissen kann, ob auf ein Byte, Word, oder DWORD zugegriffen werden soll, deswegen müssen wir es hier mit angeben.
inc word ptr[count+bx]
Dirk
-
freecrac schrieb:
Aber weil der Assembler in diesem Fall es nicht genau wissen kann, ob auf ein Byte, Word, oder DWORD zugegriffen werden soll, deswegen müssen wir es hier mit angeben.
inc word ptr[count+bx]
Hier sinnvollerweise mit byte ptr, aber man kann gerade als Anfänger/Mitleser an dieser Stelle wegen den zwei Zeigern auf Zahlen und Statistik und wegen den unterschiedlichen Registergrößen durcheinanderkommen.