Ich lese 320x eine 1 ein in die Variable-Segment bufseg1.
Es funktioniert auch.
Wie kann ich jetzt bitte wieder die 320 Werte auslesen aus der bufseg1 und in bufseg2 rein in den nächsten Befehlen mit ASM?
Allerdings ist mir nicht klar, wie der Inhalt von CX in bi kommt, bi ist doch die Zählvariable. bi müsste mind. ein double sein, sonst kannst ja nur bis 255 zählen. Ich kenn sowas anders.
Allerdings ist mir nicht klar, wie der Inhalt von CX in bi kommt,
bi ist doch die Zählvariable. bi müsste mind. ein double sein,
sonst kannst ja nur bis 255 zählen. Ich kenn sowas anders.
CX, (SI) und DI sind alle immer 16 Bit breit, kannst damit also von 0..65535 zählen. CX lässt sich in CL und CH aufgeteilt ansprechen, diese repräsentieren jeweils die unteren und oberen 8 Bits.
SI und DI lassen sich nicht so einfach aufteilen bzw. man muss sie dazu in ein anderes Register laden. Ihre Aufgabe beschreibt sich aus dem Namen. SI ist Source Index und DI ist Destination Index. LODSB z.B. lädt ein Byte von DS:[SI] in AL (die unteren 8 Bit von AX) und erhöht SI um 1. STOSB speichert ein Byte von AL in ES:[DI] und erhöht DI um 1.
Yep, wollte jetzt nur nicht gleich den kompletten x86er erklären. Daß man sich mit solchen Flags auskennen oder belesen sollte, setze ich mal voraus, denn die braucht man praktisch für alles.
Die Zaehlvariable ist uebrigens immer CX, das wird implizit auf Null runtergezaehlt. Der Befehl loop enthaelt ein dec-cx @ jumpnz, und ein vorheriges mov CX, 320 macht nachher 320 Durchgaenge
Der Befehl loop enthaelt ein dec-cx @ jumpnz, und ein
vorheriges mov CX, 320 macht nachher 320 Durchgaenge
Diesen Befehlszusammenhang gab es früher gar nicht, da musste man sich die Schleifen von Hand zusammenstricken.
Unabhängig davon wurden in professionellen Programmen mehr die rep-Goodies eingesetzt.
Die Norton-Guides waren hervorragend, u.a. weil P.N auch viel mit BASIC referenzieren konnte, und so auch schnell programmiertechnische Zusammenhänge deutlich machen konnte.
Naja... doch schon. Ich habe durch mein Interesse an damaligen Computerviren in meiner Jugend recht viele Assemblerprogramme auseinandergepflückt und selbst geschrieben. Die Schleifen mit LOOP <blah> waren überall anzutreffen, genau wie die REP-basierten Wiederholungen z.B. REP SCASB, REP MOVSB oder auch REPZ/REPNZ. Gibt ja praktisch nichts woraus man nicht irgendwie eine Schleife basteln könnte und gerade bei Assembler wurde jeder dieser Kniffe auch irgendwo verwendet wenn es gerade ins Programm passt.
Oder wenn man Programme "optimiert" hat. XOR AX,AX ist beispielsweise zwei Byte kürzer als MOV AX,0 (müsste, XOR AX,AX ist glaube ich nur ein 8 Bit OpCode wenn ich mich korrekt erinnere) oder XCHG AX,CX ist ein Byte kürzer als MOV AX,CX.
Ihre Aufgabe beschreibt sich aus dem
Namen. SI ist Source Index und DI ist Destination Index.
Übrigens ist das auch bei den allgemeinen Registern so. Die Sind zwar im Grunde beliebig nutzbar, aber es gibt bestimmte Instruktionen, die sie auch für spezifische Zwecke nutzen.
AX = Akku
BX = Base
CX = Count
DX = Data
Genau sowas meinte ich mit "es gibt bestimmte Instruktionen, die sie
auch für spezifische Zwecke nutzen". Deshalb ja auch nur "im Grunde".
Was man sich merken sollte, ist, dass frühere CP-Systeme oft nur ein Register hatten, den typischen "Akkumulator".
Die Folge könnte sein, dass dann eben bestimmte Rechnungen über AX bevorzugt behandelt werden, bzw. schneller laufen.
Ob das noch aktuell Sinn macht, sei mal dahin gestellt.
Nette Lernhilfe ist eigentlich LEA (https://stackoverflow.com/questions/12869637/trouble-understanding-assembly-command-load-effective-address)
wo auch nur die üblichen Verdächtigen (zum Zusammenrechnen) gehen.
LEA ist ja eigentlich nur ein Assembler-Hilfsmittel und kein echter Befehl, beim Assemblieren wird aus LEA SI,<label> ein MOV SI,<address>. Einer der Punkte, der das Disassemblieren von Programmen geringfügig erschwert, weil man erst ergründen muss, daß sowas z.B. mal ein LEA auf einen Puffer war. Viele Assembler erlauben auch sowas wie MOV SI,offset <label>, Ergebnis ist das Gleiche.
Register-Operationen sind alle sehr schnell, weil keinerlei Daten aus dem Speicher geholt oder hineingeschrieben werden müssen. Wenn man ein System mit langsamem Speicherzugriff hat, lohnt es sich natürlich, die Speicherzugriffe zu vermeiden.
Der Akkumulator ist so gut wie überall erforderlich, weil die Prozessoren sonst einfach sehr unflexibel werden. Ich finde Prozessoren mit ausschließlich einem Akkumulator ohne vollständigen Registersatz schon unflexibel. Deswegen bin ich bei µCs z.B. sehr schnell bei den AVRs gelandet, weil diese einen großen Register- und Befehlssatz bieten und nicht so eng genäht sind wie die PICs, die eher auf eine Programmierung mit Hochsprachen (C) optimiert zu sein scheinen. Da ist's egal was der Compiler aus dem Hochsprachenprogramm macht, aber kleiner und schneller (in der Ausführungsgeschwindigkeit) geht's natürlich mit dem AVR. Ansonsten bringt der Akkumulator schon viel für Rechenoperationen, beim x86 z.B. spielen AX und DX eine größere Rolle. Da muss man bei der Multiplikation oder Division den ersten Operanden ablegen und nach der Rechenoperation erhält man dort das Ergebnis. Andere Prozessoren verwenden die untersten Bytes des Arbeitsspeichers als Register-File (bspw. der 6502 mit seiner 256 Byte großen Zero Page, auf die der besonders schnell zugreifen kann), beim AVR bilden die ersten 32 Bytes ihres Speichers/Adressraumes den Registersatz, wobei das im Gegensatz zum x86 und 6502 eine Harvard-Architektur ist (getrennter Befehls- und Datenspeicher, wodurch auf beides gleichzeitig zugegriffen werden kann und daher kein Puffern von Daten im Prozessor erforderlich ist).