Hallo, guten Tag. Frohen Weihnachtstag, Ich habe hier eine kleine Demo für DOS: ------------------------------------------- DIM HUGE buff1(63999) as byte DIM bufseg1 as WORD bufseg1 = varseg(buff1(0)) DIM HUGE buff2(63999) as byte DIM bufseg2 as WORD bufseg2 = varseg(buff2(0)) ! mov ax,bufseg1 ! push ax ! pop es ! mov cx,320 ! mov di,0 forloop: ! mov al,1 ! mov es:[di],al ! inc di ! loop forloop ....... ....... ----------------------------------------- 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? Danke.
:
Bearbeitet durch User
mov ax, bufseg1 push ax pop es mov bx, bufseg2 push bx pop fs mov di,0 forloop: mov al, es:(di) mov es:(di), al inc di loop forloop ... so ähnlich sollte es gehen schönes Fest
:
Bearbeitet durch User
Sorry, so sollte das heissen: mov fs:(di),al 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.
Danke für die Info. Habe es jetzt geschafft: Angangsdaten in bufseg1 rein. Daten aus bufseg1 raus und bei bufseg2 rein. Diese fs funktionniert nicht in Powerbasic 3.5 Es funktioniert. Weiß nicht wie man es einfacher machen kann ohne dauernd mit dem Wechsel in es.
1 | DIM HUGE buff1(63999) as byte |
2 | DIM bufseg1 as WORD |
3 | bufseg1 = varseg(buff1(0)) |
4 | |
5 | DIM HUGE buff2(63999) as byte |
6 | DIM bufseg2 as WORD |
7 | bufseg2 = varseg(buff2(0)) |
8 | |
9 | dim a as WORD |
10 | |
11 | a=0 |
12 | |
13 | ! mov es,bufseg1 |
14 | ! mov cx,40000 |
15 | ! mov di,a |
16 | forloop: |
17 | ! mov al,1 |
18 | ! mov es:[di],al |
19 | ! inc di |
20 | ! loop forloop |
21 | |
22 | ! mov cx,40000 |
23 | ! mov di,a |
24 | forloop1: |
25 | ! mov es,bufseg1 |
26 | ! mov al,es:[di] |
27 | |
28 | ! mov es,bufseg2 |
29 | ! mov es:[di],al |
30 | ! inc di |
31 | ! loop forloop1 |
:
Bearbeitet durch User
Bitte mal die Stringbefehle anschauen. rep movsb rep movsw direction flag beachten. Eine gute Hilfe war mir immer der Norton Guide.
> 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
:
Bearbeitet durch User
Purzel H. schrieb: > 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.
Ben B. schrieb: > 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
Das stimmt nicht uneingeschränkt, sie sind nicht beliebig nutzbar. Sowas wie MOV AL, DS:[CX] geht nicht, weil solche Adressierungen nur mit BX, SI, DI und BP möglich sind.
Genau sowas meinte ich mit "es gibt bestimmte Instruktionen, die sie auch für spezifische Zwecke nutzen". Deshalb ja auch nur "im Grunde".
Rolf M. schrieb: > 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).
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.