![]() |
Assembler: Reihenfolge eines Bitfelds umdrehen
Hallo Leute,
ich such einen einfachen Assembler-Befehl der die Reihenfolge der Bits in einem Byte umdreht: Es soll also aus 12345678 das werden: 87654321 mit den Ziffern meine ich natürlich die Stellen nicht den Wert (Der kann ja nur 0 oder 1 sein). Wer kann mir helfen? Danke TO |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
BSWAP ist dein Freund.
|
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Hy,
danke für die schnelle Antwort, leider bringt mich der Tip nicht weiter, denn der Befehl wird von meinem Microkontroller nicht unterstzütz. Es handelt sich hierbei um einen AVR von Atmel, also um einen 8bit-Controller. Sonst noch jemand eine Idee? Danke auf jeden Fall TO |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Zitat:
Du kannst es "manuell" machen. Hast du Rotate- und Shift-Befehle zur Verfügung in deinem ASM? Am besten gib mal einen Link zur Prozessordoku. |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Hy,
ja, ich gebe zu, ich hätte die Info reinschreiben müßen, sorry. Hier ist eine Befehlsliste für den MC: ![]() Wäre super wenn du mir helfen könntest Gruß und Danke TO |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Zitat:
![]() ![]() ![]() |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
so gehts
Delphi-Quellcode:
sollte also mit einer anweisung getan sein da die zweite hier wohl dazu dient das ganze auf result zu schieben (kenn mich da nicht so aus mit asm)
function RotateLeft(Value: Longint;Rotate: Byte): Longint; assembler;
asm mov cl, dl rol eax, cl end; function RotateRight(Value: Longint; Rotate: Byte): Longint; assembler; asm mov cl, dl ror eax, cl end; |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Zitat:
Code:
er will aber (natürlich nur sofern ich das richtig verstanden habe) die bitreihenfolge komplett umdrehen, und das ist nicht so ohne weiteres möglich, dafür brauchts schon ein wenig (aber wirklich nur ein wenig :wink:) mehr
Bit#: 76543210
Bits: 10101100 -------------- rol 2 -------------- Bit#: 76543210 Bits: 10110010 (und es geht net um standard inline-assembler, wie aus der ersten antwort von theomega deutlich wird) |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Delphi-Quellcode:
aus meinem DEC,
{reverse the bit order from a integer}
function SwapBits(Value, Bits: LongWord): LongWord; register; asm BSWAP EAX MOV ECX,EAX AND EAX,0AAAAAAAAh AND ECX,055555555h SHR EAX,1 SHL ECX,1 OR EAX,ECX MOV ECX,EAX AND EAX,0CCCCCCCCh AND ECX,033333333h SHR EAX,2 SHL ECX,2 OR EAX,ECX MOV ECX,EAX AND EAX,0F0F0F0F0h AND ECX,00F0F0F0Fh SHR EAX,4 SHL ECX,4 OR EAX,ECX AND EDX,01Fh JZ @@1 MOV ECX,32 SUB ECX,EDX SHR EAX,CL @@1: end; gruß Hagen |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
[offtopic]
@Hagen: wo ich deinen Assembler-Code gerade so sehe: kann man da an zwei Stellen nicht noch etwas (zugegeben: minimal) optimieren, indem man Zuweisung + links Schieben durch LEA mit Faktor ersetzt? Die beiden Operanden für OR haben ja keine gemeinsamen Bits, also kann man statt dessen auch einfach addieren. (das Semikolon soll einen Kommentar einleiten. Ich weiß jetzt aus dem Kopf nicht mehr, ob der Delphi-Assembler das unterstützt)
Code:
oder (2. Variante)
{reverse the bit order from a integer}
function SwapBits(Value, Bits: LongWord): LongWord; register; asm BSWAP EAX LEA ECX,[2*EAX] ; <-- x2 schon drin ;MOV ECX,EAX AND EAX,0AAAAAAAAh AND ECX,0AAAAAAAAh ; <-- SHR EAX,1 ;SHL ECX,1 ; <-- OR EAX,ECX LEA ECX,[4*EAX] ; <-- x4 schon drin ;MOV ECX,EAX AND EAX,0CCCCCCCCh AND ECX,0CCCCCCCCh ; <-- SHR EAX,2 ;SHL ECX,2 ; <-- OR EAX,ECX MOV ECX,EAX AND EAX,0F0F0F0F0h AND ECX,00F0F0F0Fh SHR EAX,4 SHL ECX,4 OR EAX,ECX AND EDX,01Fh JZ @@1 MOV ECX,32 SUB ECX,EDX SHR EAX,CL @@1: end;
Code:
Ich weiß natürlich nicht, ob das irgendwelche negativen Einflüsse auf den Instruction-Cache hat und die ganze Sache ggf. vielleicht doch langsamer macht.
{reverse the bit order from a integer}
function SwapBits(Value, Bits: LongWord): LongWord; register; asm BSWAP EAX MOV ECX,EAX AND EAX,0AAAAAAAAh AND ECX,055555555h SHR EAX,1 LEA EAX,[EAX+2*ECX] ;<-- Keine gemeinsamen Bits ;SHL ECX,1 ;OR EAX,ECX MOV ECX,EAX AND EAX,0CCCCCCCCh AND ECX,033333333h SHR EAX,2 LEA EAX,[EAX+4*ECX] ;<-- Keine gemeinsamen Bits ;SHL ECX,2 ;OR EAX,ECX ;MOV ECX,EAX LEA ECX,[4*EAX] ;<-- Erstes x4 AND EAX,0F0F0F0F0h AND ECX,03C3C3C3Ch ;<-- SHR EAX,4 LEA EAX,[EAX+4*ECX] ;<-- Zweites x4 ;SHL ECX,4 ;OR EAX,ECX AND EDX,01Fh JZ @@1 MOV ECX,32 SUB ECX,EDX SHR EAX,CL @@1: end; [/offtopic] |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
BSWAP steht theomega doch nicht zur Verfügung :roll: Also bringt Hagen's Idee nicht unbedingt etwas
|
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Danke für die vielen Antworten, ich habe es inzwischen durch ein achtfaches rausschieben links und wieder reinschieben auch links gelöst. Dummerweise braucht die Sache damit 16 Prozessorzyklen, ist ein bischen ärgerlich, aber es funktioniert zumindest.
Gruß TO |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
@Flocke: ja diese optimierungen wären möglich, natürlich sollte man dann wieder einige OpCodes in ihrer reihenfolge verschieben. Das bewirkt dann das der Code auf Piplined CPU's (alle neueren CPU's) wieder schneller ausgeführt werden kann.
Das BSWAP EAX kann ohne Problem vermieden werden. 16 Taktzyklen für eine Schleifenbasierte Lösung halte ich für zu optimistisch. Ich würde eher ca. 64 Zyklen abschätzen wollen. Das liegt am Konstruktionsdesign der heutigen CPU's. Diese CPU's bevorzugen Atomare, Flag-unabhängige und parallelisierbare Instruktionen. Im Grunde sind also Operationen wie RCL,ROL,ROR,RCR das genaue Gegenteil von "guten" Instruktionen auf neueren CPU's. Verschlimmert wird das dann noch wenn diese OpCodes in einer Schleife programmiert werden. Zu den rein theoretischen Taktzyklen muß man dann noch einige Branches, Misses und Waitstates in den U/V Pipelines hinzu rechnen. Das macht die 16 Taktzyklen Angabe eher unwahrscheinlich. Ganz im Gegensatz dazu steht mein Source. Dieser vermischt die Registerbenutzung, Flagauswertungen und Abhängigkeiten der einzelnen Register, so daß der Code quasi in parallel in zwei Pipelines getrennt ablaufen kann. Statt für 2 OpCodes 2 Taktzyklen zu benötigen werden diese 2 OpCodes nur noch 1 Taktzyklus benötigen, ergo der Code läuft doppelt so schnell als die theoretisch errechneten Taktzyklen laut OpCodes. Hinzukommt dann noch das der Source nur einen einzigsten Branch besitzt, der Hauptcode ist also ein unrolled und Schleifenloser Code. Solch Code kann durch die CPU viel viel schneller abgearbeitet werden. In meinen eigenen Test's habe ich auf einem P4/1.5Ghz eine Durchschnittliche Laufzeit von 10 Taktzyklen gemessen. @Flocke: obige Ausführungen erklären auch warum ich den LEA Trick vermieden habe, dieser OpCode kann nur in der U Pipeline der CPU ausgeführt werden, im Gegensatz zu MOV,SHR,SHL,ADD,SUB,OR,AND usw. Es ist (nach meinem Gefühl) sehr wahrscheinlicher das das LEA zwar den Code verkürzt und vereinfacht, aber eben NICHT beschleunigt. Das müsste man aber praktischer Weise noch beweisen (statt sich auf mein Gefühl zu verlassen, bin mir aber ziemlich sicher das es so ist). Der Nachteil vom LEA ist nämlich dessen OpCode Länge, sprich die Anzahl der benötigten Bytes im Codesegment. Der Prozessorteil der diese Instruktionen aus dem Speicher in die CPU lädt und dann diesen OpCode Dekodieren muß benötigt somit mehr Zeit für LEA als für zb. MOV EAX,ECX o.ä. Gruß Hagen |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
@Hagen: Du hast sehr wahrscheinlich Recht. Mit Pipelining habe ich mich noch nicht so intensiv befasst, meine Assembler-Zeit endete so ca. vor 8 Jahren, so dass ich eher für 486 optimiert gedacht habe.
Zu den 16 Taktzyklen: theomega hat doch nur einen 8-Bit Mikroprozessor, und da werden wohl 16 Instruktionen = 16 Taktzyklen sein (8x LSR plus 8x ROL), wenn auch vielleicht nicht im GHz-Bereich! |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Wieso benutzt ihr nicht einfach eine Lookuptabelle? Das dürfte IMHO das bei weitem schnellste sein (1-2 Takte pro Byte), sämtliche Optimierungsüberlegungen sind damit hinfällig, und zur Not gehts auch in nativem Delphi:
Delphi-Quellcode:
Wobei in rbLookup[b] der die Bit-Inverse der Zahl b (0..255) steht.
Type TFourBytes = Array [0..3] Of Byte;
Function ReverseBits (aValue : Integer) : Integer; Begin TFourBytes(Result)[3] := rbLookup[TFourBytes(aValue)[0]]; TFourBytes(Result)[2] := rbLookup[TFourBytes(aValue)[1]]; TFourBytes(Result)[1] := rbLookup[TFourBytes(aValue)[2]]; TFourBytes(Result)[0] := rbLookup[TFourBytes(aValue)[3]]; End; |
Re: Assembler: Reihenfolge eines Bitfelds umdrehen
Zitat:
@theomega: schau mal hier rein ![]() Auf einem AVR wird selbstverständlich eine Schleife oder sogar auch unrolled Loop mit den OpCodes RCL, RCR seine 32 Taktzyklen für 16 Bitwerte ergeben. Im obengenannten Forum finden sich aber auch bessere Varianten, die im Grunde auf dem gleichen Trick wie mein Intel Code arbeiten. Gruß Hagen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:36 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