dword dezimal ausgeben

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: dword dezimal ausgeben

Beitrag von oDOSseus »

DIe Varianten gehen bitweise vor. Dadurch hast du maximal 32 Durchläufe. Wenn ich 1.000.000.000 durch 10 Teile habe ich jedoch 100.000.000 Durchläufe. Das heißt, sobald der Quotient größer als 32 ist, wird meine Version zu langsam
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: dword dezimal ausgeben

Beitrag von oDOSseus »

Auf deiner verlinkten Seite gab es eine wirklich hervorragende Erklärung zur division:
http://dcla.rkhb.de/div.html
Also wenn es dich auch interessiert, kann ich das nur empfehlen. Die erklärung ist zwar nur für 8bit zahlen, aber das reicht ja auch zum Verständnis
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: dword dezimal ausgeben

Beitrag von oDOSseus »

Habe nun den Code nochmal schön gemacht. Habe anfangs den fehler gemacht und die speicherstellen nicht mit "word" gekennzeichnet. Hatte den fehler erst nach 3 stunden gefunden xD xD
Hier jedenfalls der code, von dem ich denke, dass er schöner als der auf der Seite ist:

Code: Alles auswählen

;----------------------------------------------------------
;Teilt ein dword durch ein anderes. Der Dividend ist AX:BX (AX ist das höhere
;word) und der Divisor in CX:DX (CX ist das höhere word). Das Ergebnis ist in
;CX:DX und der Rest in AX:BX
div_dword:
	mov    [div_dword_dividend],    bx  ;dividend
	mov    [div_dword_dividend+2],  ax
	mov    [div_dword_divisor],     dx  ;divisor
	mov    [div_dword_divisor+2],   cx
	;Retten unseres zukünftigen Zählers DI:SI
	push   di
	push   si
	;Setzen der variablen für den Schleifen durchlauf
	xor    di,    di      ;Ergebnis-
	xor    si,    si      ;         Register (di:si)
	xor    bx,    bx      ;bitshift-
	xor    dx,    dx      ;         Puffer (bx:dx)
	mov    cx,    0x20    ;Wir machen dies einzeln für jedes bit
	
  div_dword_loop:
	;Das oberste Bit vom dividenden hochziehen
	shl    word [div_dword_dividend],    1
	rcl    word [div_dword_dividend+2],  1
	;nach cx:dx
	rcl    dx,    1
	rcl    bx,    1
	
	;Nun überprüfen wir ob es teilbar, also größer ist
	cmp    word [div_dword_divisor+2],  bx      ;Das höhere word zuerst
	je     div_dword_low_check
	jc     div_dword_below
	jmp    div_dword_above
  div_dword_low_check:
	cmp    word [div_dword_divisor],    dx      ;Dann das tiefere word
	ja     div_dword_above
  div_dword_below:
	;Es ist teilbar!!!!
	sub    dx,    word [div_dword_divisor]
	sbb    bx,    word [div_dword_divisor+2]
	stc
  div_dword_above:
	rcl    si,    1
	rcl    di,    1	
	loop   div_dword_loop
	
	mov    ax,    bx
	mov    bx,    dx
	mov    cx,    di
	mov    dx,    si
	pop    si
	pop    di
	ret
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: dword dezimal ausgeben

Beitrag von freecrac »

oDOSseus hat geschrieben:Habe nun den Code nochmal schön gemacht. Habe anfangs den fehler gemacht und die speicherstellen nicht mit "word" gekennzeichnet. Hatte den fehler erst nach 3 stunden gefunden xD xD
Hier jedenfalls der code, von dem ich denke, dass er schöner als der auf der Seite ist:

Code: Alles auswählen

;----------------------------------------------------------
;Teilt ein dword durch ein anderes. Der Dividend ist AX:BX (AX ist das höhere
;word) und der Divisor in CX:DX (CX ist das höhere word). Das Ergebnis ist in
;CX:DX und der Rest in AX:BX
div_dword:
	mov    [div_dword_dividend],    bx  ;dividend
	mov    [div_dword_dividend+2],  ax
	mov    [div_dword_divisor],     dx  ;divisor
	mov    [div_dword_divisor+2],   cx
	;Retten unseres zukünftigen Zählers DI:SI
	push   di
	push   si
	;Setzen der variablen für den Schleifen durchlauf
	xor    di,    di      ;Ergebnis-
	xor    si,    si      ;         Register (di:si)
	xor    bx,    bx      ;bitshift-
	xor    dx,    dx      ;         Puffer (bx:dx)
	mov    cx,    0x20    ;Wir machen dies einzeln für jedes bit
	
  div_dword_loop:
	;Das oberste Bit vom dividenden hochziehen
	shl    word [div_dword_dividend],    1
	rcl    word [div_dword_dividend+2],  1
	;nach cx:dx
	rcl    dx,    1
	rcl    bx,    1
	
	;Nun überprüfen wir ob es teilbar, also größer ist
	cmp    word [div_dword_divisor+2],  bx      ;Das höhere word zuerst
	je     div_dword_low_check
	jc     div_dword_below
	jmp    div_dword_above
  div_dword_low_check:
	cmp    word [div_dword_divisor],    dx      ;Dann das tiefere word
	ja     div_dword_above
  div_dword_below:
	;Es ist teilbar!!!!
	sub    dx,    word [div_dword_divisor]
	sbb    bx,    word [div_dword_divisor+2]
	stc
  div_dword_above:
	rcl    si,    1
	rcl    di,    1	
	loop   div_dword_loop
	
	mov    ax,    bx
	mov    bx,    dx
	mov    cx,    di
	mov    dx,    si
	pop    si
	pop    di
	ret
Hura, so liebe ich es. Man kann es wohl kaum besser machen. Einfach genial und exelente Arbeit.

Was ich anders gemacht hätte:
Die push und pop Befehle rausgenommen und nur bei Bedarf durch mov-Befehle(Datenbereich) ersetzt.
Könte man ggf. auch so wie im folgenden Beispiel machen, falls die Register nicht bei jedem Aufrunf gerettet werden müssen.

Mit retten der Register:
mov [RETT_DI], di
mov [RETT_SI], si
calll div_dword
mov si, [RETT_SI]
mov di, [RETT_DI]

; und ohne zu retten:
calll div_dword

Falls aber doch immer gerettet werden soll, dann kann man die mov-Befehle auch in die Suboutine stellen.

---

Ich hätte vermutlich anstelle des "loop" ein "dec cx" und "jnz div_dword_loop" genommen.

Ich hätte anstelle des jmp-Befehl ebenfalls die Befehlsfolge "rcl si, 1", "rcl di, 1"
"dec cx", "jnz div_dword_loop" genommen. Der gesamte Code wird dadurch nur minimal länger.

So würde es dann aussehen:

Code: Alles auswählen

div_dword:
	mov    [div_dword_dividend],    bx  ;dividend
	mov    [div_dword_dividend+2],  ax
	mov    [div_dword_divisor],     dx  ;divisor
	mov    [div_dword_divisor+2],   cx
	;Retten unseres zukünftigen Zählers DI:SI
;	push   di
;	push   si

	;Setzen der variablen für den Schleifen durchlauf
	xor    di,    di      ;Ergebnis-
	xor    si,    si      ;         Register (di:si)
	xor    bx,    bx      ;bitshift-
	xor    dx,    dx      ;         Puffer (bx:dx)
	mov    cx,    0x20    ;Wir machen dies einzeln für jedes bit
	
  div_dword_loop:
	;Das oberste Bit vom dividenden hochziehen
	shl    word [div_dword_dividend],    1
	rcl    word [div_dword_dividend+2],  1
	;nach cx:dx
	rcl    dx,    1
	rcl    bx,    1
	
	;Nun überprüfen wir ob es teilbar, also größer ist
	cmp    word [div_dword_divisor+2],  bx      ;Das höhere word zuerst
	je     div_dword_low_check
	jc     div_dword_below
;	jmp    div_dword_above
	rcl    si,    1
	rcl    di,    1	
   dec  cx
	jnz    div_dword_loop

  div_dword_low_check:
	cmp    word [div_dword_divisor],    dx      ;Dann das tiefere word
	ja     div_dword_above
  div_dword_below:
	;Es ist teilbar!!!!
	sub    dx,    word [div_dword_divisor]
	sbb    bx,    word [div_dword_divisor+2]
	stc
  div_dword_above:
	rcl    si,    1
	rcl    di,    1	
;	loop   div_dword_loop
   dec  cx
	jnz    div_dword_loop

	mov    ax,    bx
	mov    bx,    dx
	mov    cx,    di
	mov    dx,    si
;	pop    si
;	pop    di
	ret
Edit: Zumindest deine Version davon solltes du unbedingt auch bei unseren "Codeschnippsels" mit reinstellen: http://www.dosforum.de/viewtopic.php?f=15&t=6021
Dann finde ich es nächstes Mal wenn ich es suche schneller. Danke.

Dirk
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: dword dezimal ausgeben

Beitrag von oDOSseus »

Vielen dank für das Lob =)
Es freut mich, dass der Code verständlich ist.
Soweit ich weiß ist der loop-Befehl schneller als ein decrease und ein bedingter jump, denn der loop befehl ist ja in der cpu optimiert (genauer: im Microcode). Und da diese Schleife bei dem ausgeben einer Zahl 32 * 2 (1 für die Potenz und 1 für die wirkliche division) * 10 (10 Stellen sind Maximum bei dwords) = 640 mal durchlaufen wird, sollte man schon darauf achten. Vor allem weil man beim Ausgeben von Dateigrößen schnell mal 15 Ausgaben hat (9600 Durchläufe). Aber wenn das nicht so relevant ist, ist dein code natürlich verständlicher, es weiß ja nicht jeder auf anhieb, dass der loop befehl bei 0 aufhört und dass er cx verwendet etc. Den Code poste ich nun bei Codeschnipsel.
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: dword dezimal ausgeben

Beitrag von freecrac »

oDOSseus hat geschrieben:Vielen dank für das Lob =)
Es freut mich, dass der Code verständlich ist.
Soweit ich weiß ist der loop-Befehl schneller als ein decrease und ein bedingter jump, denn der loop befehl ist ja in der cpu optimiert (genauer: im Microcode).
Von so einer Optimierung des loop-Befehls habe ich noch nichts gehört.

Asm86faq.txt

Code: Alles auswählen

HINWEIS: Obwohl auch ein reines LOOP (Opcode E2 cb) eigentlich dazu prä-
              destiniert sein sollte (Grüße an die Intel Entwickler ;)), gibt
              es weitaus  schnellere Lösungen  als LOOP selbst (zumindest was
              386, 486 und P5 betrifft).

              Dem LOOP vorzuziehen ist imo folgende Sequenz:

                                  386    486    P5

                LOOP              11+m     6     5

                Again:
                  :
                  dec    cx     ;  2       1     1
                  jne    Again  ;  7+m     3     1
                                ;  ---   ---    --
                                ;  9+m     4     2

              Der Geschwindigkeitszuwachs  (386: 22%, 486: 50%, P5: 150%) ist
              doch wohl nicht zu verachten, oder? ;)

              Beim P5 lässt sich das Spielchen aufgrund der Pairability (DEC:
              UV, JNE: PV) sogar auf einen Geschwindigkeitszuwachs von bis zu
              400% hochtreiben ;), jedenfalls solange einem keine Branch Mis-
              prediction (3 Cycle-Penalty) dazwischenfunkt... &)

 Komplexe Instruktionen
 ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
 Komplexe Instruktionen wie z.B.  LEAVE,  ENTER und LOOP  verbrauchen unnötig
 viel Zeit. Es ist daher besser, sie durch Befehlsfolgen einfacherer Instruk-
 tionen  zu umschreiben  (siehe zu LOOP auch OPT0001).  ENTER kann  z.B.  mit
 einer  Befehlsfolge  ähnlich "PUSH eBP; MOV eBP, eSP; SUB eSP,COUNT"  besser
 ersetzt werden (siehe z.B. Source in LSG0004)...
Und da diese Schleife bei dem ausgeben einer Zahl 32 * 2 (1 für die Potenz und 1 für die wirkliche division) * 10 (10 Stellen sind Maximum bei dwords) = 640 mal durchlaufen wird, sollte man schon darauf achten. Vor allem weil man beim Ausgeben von Dateigrößen schnell mal 15 Ausgaben hat (9600 Durchläufe).
Ja genau, darauf sollte man schon achten. Mir ging es darum den Code zu beschleunigen und dafür gibts es eine einfache Regel. Man nimmt nur einfache Befehle die in der Regel auch weniger Taktzyklen benötigen und die sich auch auf modernen CPUs besser paralelisieren lassen.
Aber wenn das nicht so relevant ist, ist dein code natürlich verständlicher, es weiß ja nicht jeder auf anhieb, dass der loop befehl bei 0 aufhört und dass er cx verwendet etc. Den Code poste ich nun bei Codeschnipsel.
Ich denke die meisten Assembler-Progrmmierer kennen den loop-Befehl auch. Danach wäre dein Code lesbarer, weil dort weniger Befehle benutzt werden.

Dirk
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: dword dezimal ausgeben

Beitrag von oDOSseus »

Aber... aber... Warum gibt es einen loop befehl, wenn er so unnötig ist? Ich dachte immer, dass man das, wass die CPU selber kann, auch genau so tun sollte. Das ist doch dämlich, dass loop langsamer als dec und jne ist... Ich bin erschüttert^^
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: dword dezimal ausgeben

Beitrag von Dosenware »

Von so einer Optimierung des loop-Befehls habe ich noch nichts gehört.
http://support.microsoft.com/kb/192841/de

K6 CXT-Core Patch
[Windows 95B/C]
Bestimmte Windows-Versionen verwenden beim Booten eine LOOP-Schleife als Zeitverzögerung, um während dessen Gerätetreiber zu initialisieren. Der AMD K6 mit CXT-Core (K6-2 350 und höher) verarbeitet den LOOP-Befehl jedoch "in Hardware", sodaß der Prozessor mit der Zeitschleife viel zu früh fertig ist, was Windows beim Booten zum Absturz bringt. Dieser Patch behebt das Problem.
siehe: http://www.planet3dnow.de/faq/files/index.shtml

Und als kleiner Schmunzler:

Auch das noch!
Vor Jahren bezog AMD mit dem K6 noch Schelte, weil der Prozessor bei höherem Takt mit Windows 95 nicht zusammenspielte. Zu Unrecht, denn nicht der Prozessor war schuld, sondern schlampig programmierte Windows-Treiber, die bei zu schneller Ausführung des Loop-Befehls einfach ‘überlaufen’ wurden. Nun ereilt dieses Schicksal auch den Pentium 4, der bei 2 GHz in seiner Loop-Performance so allmählich auf K6-300-Niveau kommt. Wer also unbedingt den P4 mit Windows 95 betreiben möchte, benötigt die gleichen Patches wie der K6 anno dazumal. siehe: http://www.heise.de/ct/artikel/Prozesso ... 85254.html

schade das Wiki von alledem nichts weis, den 585,99999999999999762 Witz versteht es hingegen

Ähhdit:
Wiki weiß es doch noch:

Die CPUs der AMD K6-2-Baureihe mit einer Geschwindigkeit von 350 MHz oder mehr sind ohne einen Patch nicht mit Windows 95 kompatibel, weil im Windows 95-Treiber IOS.VXD eine Zeitschleife implementiert ist, die auf Grund der hohen Geschwindigkeit des Prozessors zu schnell abgearbeitet wird und dann eine Division durch Null durchführt. Der Patch wurde von Microsoft und AMD entwickelt und war bei AMD auf der Homepage erhältlich. Um den Patch auszuführen, muss die CPU unter 350 MHz, praktisch meist auf 300 MHz, getaktet werden. Nach Ausführung des Patches kann die CPU wieder auf ihren nominellen Takt hochgetaktet werden und so die volle Leistung genutzt werden.
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: dword dezimal ausgeben

Beitrag von freecrac »

oDOSseus hat geschrieben:Aber... aber... Warum gibt es einen loop befehl, wenn er so unnötig ist? Ich dachte immer, dass man das, wass die CPU selber kann, auch genau so tun sollte.
Das ist bei vielen der komplexeren Befehlen so dass sie mehr Taktzyklen brauchen, auch lassen sich diese Befehl in der Regel nur schlecht paralelisieren.
Beim hardwareseitiges Loop-unrolling wird ja auch nur in kleine Häpchen zerlegt, die dann vergleichbar wie unsere nicht so komplexen Befehle abgearbeitet werden.
Alle x86-Befehle werden auch beim AMD K6 in Micro-Ops zerlegt, denn ein AMD K6 ist auch ein CISC/RISC-Zwitter.
Das ist doch dämlich, dass loop langsamer als dec und jne ist... Ich bin erschüttert^^
Vom Schaltungsdesign habe ich keine Ahnung. Aber ich wunder mich auch über manche Dinge.

Was passiert denn schon Schlimmes wenn man durch null teilt, dann konnte das Ergebniss davon doch ebenfall im Zielregister landen, ohne das ein hardwareseitiger Ausnahme-Zustand ausgelöst wird.
Beim Addieren, Subtrahieren und Multiplizieren mit Null wird ja auch kein Exception ausgeführt. Wofür soll so ein Exception(divede by zero error) überhaupt gut sein?

Dirk
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: dword dezimal ausgeben

Beitrag von freecrac »

Dosenware hat geschrieben:
Von so einer Optimierung des loop-Befehls habe ich noch nichts gehört.
http://support.microsoft.com/kb/192841/de

K6 CXT-Core Patch
[Windows 95B/C]
Zwar haben auch Windows 98 SE und ME noch erhebliche Fehler, aber alle Windows "95" kann man wohl in den Müll werfen.
Ob sich etwas beim Resourcenhunger verändert hat müsste man mal nach schauen. Die Hardware-Kompatibilität wurde seit "98" erheblich verbessert.

Dirk
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: dword dezimal ausgeben

Beitrag von Dosenware »

freecrac hat geschrieben:alle Windows "95" kann man wohl in den Müll werfen.
W95b OSR 2.1 super Sache, AGP, Fat32, gefixtes himem.sys, USB - KEIN Active Desktop
Die Hardware-Kompatibilität wurde seit "98" erheblich verbessert.
naja, hier ging es eigentlich mehr um eine Zählschleife zur Verzögerung, die durch den Hardware-Loop des K6 zu schnell fertig wurde - so ähnlich wie der TP-Bug (unit CRT; Initialisierung von Delay).

zur Exception:
x/0 führt zu einem undefiniertem Ergebnis, ist also schon recht Praktisch wenn solche Fehler abgefangen werden (gibt ja auch Weichware die nicht nur bunte Bildchen macht - wobei dort solche Fehler bereits in der Software abgefangen werden sollten)
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: dword dezimal ausgeben

Beitrag von freecrac »

Dosenware hat geschrieben:
freecrac hat geschrieben:alle Windows "95" kann man wohl in den Müll werfen.
W95b OSR 2.1 super Sache, AGP, Fat32, gefixtes himem.sys, USB - KEIN Active Desktop
Die Hardware-Kompatibilität wurde seit "98" erheblich verbessert.
naja, hier ging es eigentlich mehr um eine Zählschleife zur Verzögerung, die durch den Hardware-Loop des K6 zu schnell fertig wurde - so ähnlich wie der TP-Bug (unit CRT; Initialisierung von Delay).
Das bedeutet nur das bei den damaligen Intel-CPUs der Loop-Befehl noch langsamer ausgeführt wird als bei den AMD-CPUs.
Nicht aber das ein Loop-Befehl im Vergleich zur Befehlsfolge "dec cx + jnz Adresse" schneller ist, denn diese Befehlsfolge wurde vermutlich erst mit dem Patch geliefert, in dem wohl die Anzahl der Schlefendurchläufe noch weiter erhöht wurde, damit dann endlich eine ausreichend lange Verzögerung für beide CPUs erfolgt.
zur Exception:
x/0 führt zu einem undefiniertem Ergebnis, ist also schon recht Praktisch wenn solche Fehler abgefangen werden (gibt ja auch Weichware die nicht nur bunte Bildchen macht - wobei dort solche Fehler bereits in der Software abgefangen werden sollten)
Das mag für viele Fälle ja nützlich sein.

Doch wofür soll ein Exception "divide by zero" genau nützlich sein?

Und warum soll es von einer Software abgefangen werden, um dann bestenfalls dahinter weiter zu machen wo die Exception ausgelöst wurde?

Ich sehe darin einfach keinen Sinn. Bei der Entwicklung von Assemblercode/Compiler muss man doch auf jeden Fall auf richtige Werte achten.

Dirk
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: dword dezimal ausgeben

Beitrag von Dosenware »

freecrac hat geschrieben: Und warum soll es von einer Software abgefangen werden, um dann bestenfalls dahinter weiter zu machen wo die Exception ausgelöst wurde?
Es zwingt dich ja niemand dazu genau dort weiterzumachen.
Ich sehe darin einfach keinen Sinn. Bei der Entwicklung von Assemblercode/Compiler muss man doch auf jeden Fall auf richtige Werte achten.
Bei Rot musst du stehenbleiben, erst bei Grün darfst du die Straße überqueren ;-)
Nebenbei gibt es viele Wege auf denen die Daten zu deinem Unterprogramm kommen können, daher kann man eben nicht immer korrekte Werte garantieren, sondern "solte" im Code nochmals die Daten auf unzulässige Werte kontrollieren.
Nicht aber das ein Loop-Befehl im Vergleich zur Befehlsfolge "dec cx + jnz Adresse" schneller ist
zumindest beim K6 schon

PS. habe jetzt mal ein einfaches:

Code: Alles auswählen

mov bx,$FFFF
@loopa:
mov cx,$FFFF
@loopi:
nop
loop @loopi
dec bx
jnz @loopa
mal mit loop, mal mit dec/jnz in der inneren Schleife, über meinen K6 III gejagt
8,57-8,62s für Loop und 17,13-17,19s für dec/jnz (da genaue Zeitmessung nicht mein Ding ist, habe ich das ganze 10mal durchlaufen lassen)
der DX/66 rödelt noch

Interressant, beim 486er ist es umgekehrt: 516,02s für den Loop, 386,02s für dec/jnz

PPS. mein Core i7 2600 braucht mit Loop 5,33s und ohne 2,20s
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: dword dezimal ausgeben

Beitrag von freecrac »

Dosenware hat geschrieben:
freecrac hat geschrieben: Und warum soll es von einer Software abgefangen werden, um dann bestenfalls dahinter weiter zu machen wo die Exception ausgelöst wurde?
Es zwingt dich ja niemand dazu genau dort weiterzumachen.
Dann wird die Aufgabe aber nicht erledigt. Und alles nur obwohl es gar nicht weiter schlimm wäre, wenn man durch Null teilt und das Ergebniss = Devidend bleiben würde.
Ich sehe darin einfach keinen Sinn. Bei der Entwicklung von Assemblercode/Compiler muss man doch auf jeden Fall auf richtige Werte achten.
Bei Rot musst du stehenbleiben, erst bei Grün darfst du die Straße überqueren ;-)
Aus Langeweile warte ich bestimmt nicht bei einer roten Ampel, nur weil sie rot ist. Eine Ampel ist dafür da, um ein Verkehrsaufkommen zu regeln. Damit man aber überhaupt von einem Verkehr reden kann, dafür bedarf es mindestens zwei Verkehrsteilnehmer die vor Ort beteiligt sein müssen. Ist kein Verkehr vorhanden, dann kann die Ampel auch keinen Verkehr regeln und dann überquere ich die Strasse, wenn ich es eilig habe und auch keine Kinder, oder Polizisten zuschauen, auch bei roter Ampel. Denn ohne einen wirklichen Grund lasse ich mir doch von einer Ampel nicht vorschreiben wann und wie ich eine Strasse zu überqueren habe. Auf diese Weise hinterfrage ich schon die Sinnhaftigkeit aller Dinge in wie fern es auch wirklich nützlich ist und ob es ohne besondere Probleme auch einfachen gehen könnte. Denn Regeln haben keinen Selbstzweck, sondern sollen uns in unserem Leben behilflich sein. Ist der Zweck einer Regel nicht wirklich anwendbar, dann sollten wir uns an eine solche Regel auch nicht stur halten und ersatzweise unser Verhalten nach dem gesunden Menschenverstand ausrichten und darüber selber entscheiden in wie fern eine Regel zur Anwendung kommt, oder ob wegen eines wichtigen Grundes von einer Regel abgewichen wird.
Nebenbei gibt es viele Wege auf denen die Daten zu deinem Unterprogramm kommen können, daher kann man eben nicht immer korrekte Werte garantieren, sondern "solte" im Code nochmals die Daten auf unzulässige Werte kontrollieren.
Das kann man bei Bedarf ja softwareseitig tun. Es gibt aber keine besondere Notwendigkeit so etwas hardwareseitig abzufangen. Denn sonst könnte vergleichsweise ja auch bei jedem add-Befehl wo eine Null addiert wird zu einem "Add with Zero--Error Exception" führen und dafür sehe ich genauso wie beim "Devide by Zero-Error-Exception" keinen wirklichen Sinn für solche hardwareseitigen Exception, wenn durch Null geteilt wird.

Denn wenn man beispielsweise folgende Multiplikation durchführt:
mov ax, 0Ah
mov dx, 0
mov bx, 0
mul bx
Dann wird ja auch kein Exception ausgeführt und das Ergebniss(= 0) davon landet in DX:AX. Wieso kann bei einer Division durch Null das Ergebniss(=Dividend) davon nicht ebenfalls nur in den Zielregistern landen?

Und wieso wird behauptet das Ergebniss einer Divison durch Null müsse undefiniert sein? Wenn man einen Wert durch Null teilt, dann bedeutet es lediglich das der Wert als Ganzes erhalten bleibt und es zu keiner Aufteilung davon kommt.
Auch ist der Wert als Ganzes doch genau definiert worden.
Nicht aber das ein Loop-Befehl im Vergleich zur Befehlsfolge "dec cx + jnz Adresse" schneller ist
zumindest beim K6 schon

PS. habe jetzt mal ein einfaches:

Code: Alles auswählen

mov bx,$FFFF
@loopa:
mov cx,$FFFF
@loopi:
nop
loop @loopi
dec bx
jnz @loopa
mal mit loop, mal mit dec/jnz in der inneren Schleife, über meinen K6 III gejagt
8,57-8,62s für Loop und 17,13-17,19s für dec/jnz (da genaue Zeitmessung nicht mein Ding ist, habe ich das ganze 10mal durchlaufen lassen)
der DX/66 rödelt noch

Interressant, beim 486er ist es umgekehrt: 516,02s für den Loop, 386,02s für dec/jnz

PPS. mein Core i7 2600 braucht mit Loop 5,33s und ohne 2,20s
Aha, gut zu wissen.

Dirk
Zuletzt geändert von freecrac am So 9. Okt 2011, 13:32, insgesamt 1-mal geändert.
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: dword dezimal ausgeben

Beitrag von Dosenware »

freecrac hat geschrieben: Das kann man bei Bedarf ja softwareseitig tun. Es gibt aber keine besondere Notwendigkeit so etwas hardwareseitig abzufangen. Denn sonst könnte vergleichsweise ja auch bei jedem add-Befehl wo eine Null addiert wird zu einem "Add with Zero--Error Exception" führen
x+0=x
x/0=undefiniert
Da ist der Unterschied, warum das /0 Hardwareseitig abgefangen wird hat wohl etwas mit der Entwicklungsgeschichte der Prozessoren zu tun, aber ein x+0 muss nun wirklich nicht abgefangen werden.

BTW. bei der Schleife macht der K6 übrigens

Code: Alles auswählen

1{mov bx}+FFFF{mov cx}+(2*FFFF*FFFF{innere Schleife})+FFFF{dec bx}+FFFF{jnz}/ 8,60s= 8.589.869.056/ 8,60= 998.8 Millionen Befehle/s mit Loop
1{mov bx}+FFFF{mov cx}+(3*FFFF*FFFF{innere Schleife})+FFFF{dec bx}+FFFF{jnz}/17,15s=12.884.705.281/17,15= 751.3 Millionen Befehle/s ohne Loop
Bei 500MHz nicht übel...mal schauen ob da ein Rechenfehler drin ist
Antworten