Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   [ASM] Dividieren von Ganzzahlen (https://www.delphipraxis.net/78353-%5Basm%5D-dividieren-von-ganzzahlen.html)

Balu der Bär 3. Okt 2006 17:11


[ASM] Dividieren von Ganzzahlen
 
Ja, ihr hab richtig gelesen, diesmal gehts um Assembler. Meine ersten Erfahrungen (ASM betreffend) liegen ein paar Monate zurück, wegen einem Bekannten bin ich heute wieder dazu gekommen ein bisschen mehr herumzuspielen. Ich habe derzeit ein kleines Problem, und zwar mit dem Dividieren von zwei Ganzzahlen. Bei der Multiplikation mach ich des ja einfach so:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
 test : Integer;
begin
 test := 7;
 asm
   MOV EAX,test // <- lese test ein
   IMUL EAX, 5 // <- multipliziere mit 5
   MOV test, EAX //<- schriebe Wert zurück in test
 end;
 ShowMessage(IntToStr(test));
end;
Deshalb vermutete ich das Dividieren verläuft ähnlich, folgendes habe ich versucht:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
 test : Integer;
begin
 test := 20;
 asm
   MOV EAX,test // <- lese test ein
   MOV BH, 5 // <- teile BH 5 zu
   IDIV BH // <- dividiere durch 5
   MOV test, EAX //<- schriebe Wert zurück in test
 end;
 ShowMessage(IntToStr(test));
end;
Egal ob ich IDIV oder ein normales DIV nehme, als Ergebnis erhalte ich 5. 20 durch 5 ist bei mir aber 4, wieso bekomme ich dort 5 heraus? Bitte nehmt Rücksicht, bin absoluter Assembler-Anfänger. :oops: Irgendwie steh ich gerade ziemlich auf dem Schlauch, weiß jemand was da los ist? Danke euch.

3_of_8 3. Okt 2006 17:17

Re: [ASM] Dividieren von Ganzzahlen
 
Also bei mir kommt 4 raus.

Balu der Bär 3. Okt 2006 17:25

Re: [ASM] Dividieren von Ganzzahlen
 
Ja, wie ich bemerkt hatte kommt wirklich 4 raus. :wall: Der Quellcode in diesem Thread war nur ein Auszug, ich hab gerade erst gesehen ich hatte aus Versehen noch ein INC EAX weiter unten mit drin, deshalb kam eins mehr heraus. :wall:
Ich bitte um Verzeihung und glaube ich schalte den PC jetzt lieber aus. :cry:

Hawkeye219 3. Okt 2006 17:41

Re: [ASM] Dividieren von Ganzzahlen
 
Hallo Balu,

hast du einmal versucht, mit deinem Code 21 durch 5 zu teilen? Hier ist die Erklärung für das möglicherweise überraschende Ergebnis.

Gruß Hawkeye

Balu der Bär 3. Okt 2006 17:50

Re: [ASM] Dividieren von Ganzzahlen
 
Hallo Hawkeye,

jupp versucht habe ich es, es kommt ein Ergebnis raus das garantiert nicht stimmt. Ich versuch mich mal da einzulesen und eine Lösung zu finden, danke für den Link. :thumb:

Wie gesagt ich bin noch Anfänger und die Materie ist nicht sonderlich leicht verständlich. ;)

Amateurprofi 3. Okt 2006 19:36

Re: [ASM] Dividieren von Ganzzahlen
 
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
 test : Integer;
begin
 test := 20;
 asm
   MOV EAX,test // <- lese test ein
   MOV BH, 5 // <- teile BH 5 zu
   IDIV BH // <- dividiere durch 5
   MOV test, EAX //<- schriebe Wert zurück in test
 end;
 ShowMessage(IntToStr(test));
end;
Das Problem ist, daß Du durch BH dividierst.
Dann wird AX (die unteren 2 Bytes von EAX) durch BH geteilt. Der Quotient kommt in AL, der Modulo in AH.

Benutze als Divisor ECX (EBX sollte nie verändert werden) als Divisor.
Dann kommt der Quotient in EAX, der Modulo in EDX
Also
Delphi-Quellcode:
mov  eax,test
cdq
mov  ecx,5                   
idiv ecx
mov  test,eax

Balu der Bär 3. Okt 2006 20:12

Re: [ASM] Dividieren von Ganzzahlen
 
Hallo,

funktioniert gut diese Lösung, danke. :thumb:

Aber sagmal was macht denn der Befehl "cdq", von dem hab ich bis jetzt noch gar nichts gehört? :gruebel:

3_of_8 3. Okt 2006 20:19

Re: [ASM] Dividieren von Ganzzahlen
 
cdq macht folgendes:

Wenn das Vorzeichenbit von eax gesetzt ist, wird edx auf 0xFFFFFFFF gesetzt, ansonsten auf 0x00000000.

Balu der Bär 3. Okt 2006 20:29

Re: [ASM] Dividieren von Ganzzahlen
 
Aha, danke.

Gibt es eigentlich irgendwo eine Tabelle wo kurz die wichtigsten Befehle mit kurzer Beschreibung aufgelistet sind?

3_of_8 3. Okt 2006 20:31

Re: [ASM] Dividieren von Ganzzahlen
 
Du könntest dir das Prozessorhandbuch von Intel ansehen. Ansonsten einfahc mal googeln.

Dax 3. Okt 2006 20:32

Re: [ASM] Dividieren von Ganzzahlen
 
Örm, falsch.

x86 Instruction Set Reference
CWD/CDQ—Convert Word to Doubleword/Convert Doubleword
to Quadword

Description

Doubles the size of the operand in register AX or EAX (depending on the operand size) by
means of sign extension and stores the result in registers DX:AX or EDX:EAX, respectively.
The CWD instruction copies the sign (bit 15) of the value in the AX register into every bit position
in the DX register (see Figure 7-6 in the IA-32 Intel Architecture Software Developer’s
Manual, Volume 1). The CDQ instruction copies the sign (bit 31) of the value in the EAX
register into every bit position in the EDX register.
The CWD instruction can be used to produce a doubleword dividend from a word before a word
division, and the CDQ instruction can be used to produce a quadword dividend from a doubleword
before doubleword division.
The CWD and CDQ mnemonics reference the same opcode. The CWD instruction is intended
for use when the operand-size attribute is 16 and the CDQ instruction for when the operand-size
attribute is 32. Some assemblers may force the operand size to 16 when CWD is used and to 32
when CDQ is used. Others may treat these mnemonics as synonyms (CWD/CDQ) and use the
current setting of the operand-size attribute to determine the size of values to be converted,
regardless of the mnemonic used.


Sprich: es füllt EDX mit Sign(EAX).

@Balu: Intel x86 Instruction Set Reference - Google mal danach ;)

3_of_8 3. Okt 2006 20:34

Re: [ASM] Dividieren von Ganzzahlen
 
Habe ich das nicht gesagt?

Muetze1 3. Okt 2006 20:44

Re: [ASM] Dividieren von Ganzzahlen
 
Zitat:

Zitat von Dax
Örm, falsch.

Öhm, nö. Und deine gepostete Doku sagt dies sogar aus. 3_of_8 hat es zwar in Kurzform geschrieben aber vollkommen richtig.

/EDIT: Mitten im POST ein Discon... *grml*

Amateurprofi 3. Okt 2006 20:47

Re: [ASM] Dividieren von Ganzzahlen
 
Zitat:

Zitat von Dax
Örm, falsch..

FALSCH. Was 3_of_8 schrieb ist völlig korrekt.


Zitat:

Zitat von Dax
Sprich: es füllt EDX mit Sign(EAX)...

FALSCH.
Würde CDQ EDX mit Sign(EAX) füllen, dann wäre EDX, je nach Interpretation von "Sign(EAX)", entweder $80000000 oder $00000001 oder $00000000

Richtig ist, daß CDQ Bit 31 aus EAX in jedes Bit von EDX kopiert also ist EDX dann entweder $FFFFFFFF oder $00000000, also exakt so, wie 3_of_8 es schrieb.

Dax 3. Okt 2006 20:56

Re: [ASM] Dividieren von Ganzzahlen
 
Ach verdammt, ich hab statt edx da oben eax gelesen :oops: Und beim schreiben nich gedacht :wall: Ich meinte, das Sign(EAX) in jedes Bit geschrieben wird, nicht ins ganze Register...

*jetzt besser die klappe hält*


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:25 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz