Autor Beitrag
Passi077
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 125

Win XP
D7 Pers
BeitragVerfasst: Fr 26.01.07 16:31 
Hi,

bin gerade bei meinen ersten Versuchen von Assembler in Delphi (bisher nur auf nem Intel 8051 Assembler programmiert).

Problem1: Ich möchte große Bitzahlen Und-Verknüpfen. Bis 32 Bit mit einem LongWord kein Problem soweit, aber was mache ich, wenn ich größere Zahlen als 32 Bit habe? Des weiteren möchte ich eine logische Rechts-/Linksverschiebung auf diese großen Zahlen anwenden.

Problem2: Wie kann ich denn Arrays in Assembler benutzen?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function astest(): integer;
var
  Testvar: array [0..1of longword;
asm

   MOV Testvar[0], 10011111101b
   SHR Testvar, 10b
   MOV EAX, Testvar
   AND EAX,     1100000001b
   MOV @Result, EAX   

end;


funktioniert leider nicht ("Operandengröße stimmt nicht überein")

Danke + Grüße
Passi
OldGrumpy
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 82



BeitragVerfasst: Fr 26.01.07 16:57 
Am bequemsten ist es, wenn man Zahlen mit mehr als 32 Bit einfach in ausreichend viele 32-Bit-Gruppen aufteilt. Eine Und-Verknüpfung führt man dann halt mit entsprechend vielen Nullbits aufgefüllt für jede Gruppe durch. Bitschiebereien sind auch kein größeres Problem, musst nur halt drauf achten, dass Du immer nur ein Bit auf einmal schiebst und das von einer 32-Bit-Gruppe korrekt zur nächsten weiterleitest. Dafür gibts die Assemblerbefehle RCR und RCL. Ab dem 386er gibts auch elegantere Methoden namens SHLD und SHRD. Ich bin momentan arg erkältet, deswegen spar ich mir mal Beispielcode, Google dürfte da auch einiges liefern :)
Passi077 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 125

Win XP
D7 Pers
BeitragVerfasst: Fr 26.01.07 17:34 
Hi,

Danke für die Antwort, somit wäre das Schiebe- und Addierproblem schonmal zumindest teilweise gelöst. Denn ohne die Benutzung von Arrays kann ich damit jetzt immer noch ziemlich wenig anfangen leider :(

Ich könnte meiner Assembler Funktion natürlich auch einfach die Longword Werte direkt übergeben und die Arrays dann normal in Delphi auslesen. Aber das muss doch auch anders gehen..
OldGrumpy
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 82



BeitragVerfasst: Fr 26.01.07 17:44 
Bei welcher Zeile kommt denn die Fehlermeldung? Falls gleich beim ersten MOV, dann ist Delphi vielleicht etwas blond und Du musst wirklich 32 Bit für die Binärzahl benutzen. Es kann natürlich auch sein, dass Delphi diese Adressierungsart (mem, const) nicht kennt, ich kanns so auf Anhieb nicht sagen. Alternativ halt die Adresse des Arrays in ein Register laden und das dann zum Zugriff benutzen.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: So 28.01.07 19:09 
Hi,

Die Nutzung von Arrays in ASM-Sources passiert im Allgemeinen über die Displacements beim Adressieren der Daten.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
type TDWORDArray = array[0..15of DWORD;

procedure AddArrays(Const InArr1, InArr2: TDWordArray; var OutArr: TDWordArray);
//  =>  EAX     @InArr1[0]
//  =>  EDX     @InArr2[0]
//  =>  ECX     @@OutArr[0]
asm
    PUSH    EBX //EBX wird von Delphi benutztt ... muss wiederhergestellt werden

    MOV     EBX, DWORD PTR [ECX] //OutArr[0] adressieren - Delphi übergibt für Var-Parameter nur einen Zeiger

    XOR     ECX, ECX

    PUSHF   //Flags sichern - für Übertrag

@@add_loop:
    POPF    //Flags wiederherstellen - für Übertrag

    MOV     ESI, DWORD PTR [EAX+4*ECX] //InArr1[ECX]
    ADC     ESI, DWORD PTR [EDX+4*ECX] //InArr2[ECX]
    MOV     DWORD PTR [EBX+4*ECX], ESI //OutArr[ECX]

    PUSHF   //Flags sichern - für Übertrag

    INC     ECX
    CMP     ECX, $10
    JNZ     @@add_loop

    POPF    //Flags verwerfen

    POP     EBX
end;


Im Normalfall optimiert man das aber noch ein wenig ;-) (Denn mein Prof für Rechnerarchitektur würde mich für den Source prügeln :P)

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: Mo 29.01.07 15:02 
Eine Implementation mittels des shld/shrd (shift left double precision) Befehls kann man unter meinem Beitrag in open source Projekte>> Bigints große Zahlen ansehen. Die Funktion heißt dort glaube ich (shfl und shfr shiftleft shiftright) die shiften meine Bigints, die sind aber praktisch ein array aus longword.
Passi077 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 125

Win XP
D7 Pers
BeitragVerfasst: Di 30.01.07 15:55 
Hi,

danke für eure Antworten.

Wie ich sehe, schiebt Dein Code allesquarks die Zahlen "von Hand". Ist mir gestern auch gekommen, dass das anders ja gar nicht funktionieren kann. Da nutzt mir auch der Befehl zum Schieben von 2 Registern nix, weil es ja auch vorkommen kann das ich >64Bit Zahlen hab.

Jetzt zweifele ich langsam daran, dass es sich lohnt das Ganze in Assembler zu schreiben. Wenn es fertig ist, soll es eine pixelgenaue Kollisionserkennung mit Hilfe von Alphamasken werden. Jetzt folgendes Beispiel:

2 Objekte, jeweils 50x50 groß.
Die 2 zu kollidierenden Objekte überlappen sich als Rechteck in einem Bereich von 5x30 Pixeln, dieser muss also überprüft werden. Mit Assembler muss ich nun die eine Alpha Maske um die Distanz der Objekte verschieben, in diesem Beispiel also um 45 Bit. Die Gesamtschleife, die es braucht um auf Kollision zu prüfen, läuft nun also 45x30 durch (linienweise überprüft). Dazu kommt noch ein Faktor von x2, da ich die einzelnen Words ja einzeln miteinander Und-Verknüpfen muss. (Hier 2x32Bit)

Programmiere ich das Ganze direkt in Delphi, kann ich einfach mit einem Array arbeiten und nur den zu überprüfenden Bereich Pixel für Pixel überprüfen. Wäre in obigen Beispiel dann nur eine Schleife von 5x30, in der ich dann ganz normal 2 Boolean Werte miteinander verknüpfe.

Lohnt es sich also überhaupt, das in Assembler zu schreiben? Ich weiß ja nicht wie effektiv Delphi compiled und wie viele Zyklen dann jeweils benötigt werden.. und natürlich kann man obiges Beispiel auch umdrehen und dann sieht es eben genau andersrum aus.

Was meint Ihr dazu?
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Di 30.01.07 16:36 
Der Compiler von Delphi ist schlichtweg lahmarschig ;-)

Aber warum solltest Du den Algorithmus, so wie Du ihn in Delphi schreiben würdest, nicht auch in ASM schreiben können?

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.