Bitverschiebung - Portierung von Assembler in C++
-
Habe die Suchfunktion schon genutzt und nichts passendes zu meinem Problem gefunden.
Ich versuche gerade die Bitverschiebungsfunktion SHRD in C++ zu portieren
Leider funkioniert diese bis jetzt nur bei postiven Zahlen.Erstmal die Beschreibung von SHRD:
"Der SHRD-Befehl bewirkt, daß die Bits im Zieloperanten um x Positionen nach rechts
verschoben werden und die höherwertigen Bits vom 2. Operanten nachgeschoben (aufgefüllt)
werden"Hier meine Code (geht bestimmt auch effektiver - aber naja !)
Aufruf:
AnsiString bin1, bin2, bin3, bin4; int eax, edx, RESULT; //eax (32bit) in Binär wandeln Int2Bin(eax, 32, &strbin); bin1 = strbin; //edx (32bit) in Binär wandeln Int2Bin(edx, 32, &strbin); bin2 = strbin; bin3 = bin2 + bin1; bin4 = bin3.SubString(bin1.Length() - 0x1e + 1, bin1.Length()); Bin2Int(bin4, &iVal); RESULT = iVal;
Funktionen:
void Int2Bin(__int64 value, int iBit, AnsiString *strBin) { //Variablendeklaration int arraybin[255], i = 0; __int64 temp1 = 0, temp2 = 0; AnsiString bin; temp1 = value; //in Binär wandeln while(temp1 > 0) { temp2 = fmodl(temp1, 2); arraybin[i] = temp2; temp1 = temp1 / 2; i++; } //mit Nullen auf die Anzahl der Bits auffüllen if(i < iBit) { for(i; i < iBit; i++) { arraybin[i] = 0; } } i--; //in richtige Reihenfolge bringen for(i; i > -1; i--) bin = bin + arraybin[i]; //Rückgabewert füllen *strBin = bin; } //---------------------------------------------------------------------- void Bin2Int(AnsiString strBin, __int64 *value) { //Variablendeklaration int k = 0; __int64 temp1 = 0, temp2 = 0; int arraybin[255]; AnsiString tempstr; for(k; k < strBin.Length(); k++) { tempstr = strBin.SubString(strBin.Length() - k, 1); if(tempstr.ToInt() != 0) { temp1 = tempstr.ToInt() * pow(2, k); temp2 = temp2 + temp1; } } //Rückgabewert füllen *value = temp2; } //----------------------------------------------------------------------
Das erste Beispiel mit zwei postiven Zahlen bringt auch das gewünschte Ergebnis
eax = 159976EA (dez. 362378986)
edx = 086F00E7 (dez. 141492455)
cl = 1E (dez. 30)Schiebeoperation shrd eax,edx,cl (shrd 159976EA,086F00E7,1e)
eax = 0001 0101 1001 1001 0111 0110 1110 1010
edx = 0000 1000 0110 1111 0000 0000 1110 0111edx (höherwertig-32bit)+eax (niederwertig-32bit)
0000 1000 0110 1111 0000 0000 1110 0111 0001 0101 1001 1001 0111 0110 1110 10100010 0001 1011 1100 0000 0011 1001 1100 (per Hand verschoben & mit eigener Funktion)
Rückgabewert = 21BC039C (richtig !!!)
Bei diesen Zahlen gibt's aber das Problem
eax = f00e7159 (dez. -267488935 !!!!!!!!!!!!)
edx = 08316a6e (dez. 137456238)
cl = 1E (dez. 30)Schiebeoperation shrd eax,edx,cl (shrd f00e7159,08316a6e,1e)
eax = 0000 1111 1111 0001 1000 1110 1010 0111
edx = 0000 1000 0011 0001 0110 1010 0110 1110edx (höherwertig-32bit)+eax (niederwertig-32bit)
0000 1000 0011 0001 0110 1010 0110 1110 0000 1111 1111 0001 1000 1110 1010 01110010 0000 1100 0101 1010 1001 1011 1000 (per Hand verschoben = 20c5a9b8)
0010 0000 1100 0101 1010 1001 1011 1011 (Ergebnis muss rauskommen = 20c5a9bb !!!!)wo kommen die letzten zwei Einsen beim richtigen Ergebnis her ????
(Das richtige Ergebnis gibt die SHRD-Funktion in einem Assemblerprogramm zurück
- ist also definitiv richtig)es wird sicher damit zusammenhängen das eax negativ ist.
Zitat:
"Das höchtswertige Bit einer Zahl wird zur Darstellung des Vorzeichens verwendet."das höchstwertige Bit von eax ist doch aber eine von 0.
Welches Bit soll gemeint sein und wie kann ich aus einer negativen Zahl eine positive
machen ??Hab es auch mal mit Inline-Assembler versucht - da hagelte es aber Fehlermeldungen
int RESULT; _asm { mox cl,1E mov edx,08316A6E mov eax,F00E7159 shrd eax,edx,cl } RESULT = eax;
müsste doch so langen - oder ????? (hab noch nicht mit Inline-Asm gemacht !!!)
-
skinny schrieb:
Hab es auch mal mit Inline-Assembler versucht - da hagelte es aber Fehlermeldungen.
Was denn für welche?
Hüftschuss von mir:
[cpp]
int iResult;_asm
{
mox cl,1E
mov edx,08316A6E
mov eax,F00E7159
shrd eax,edx,cl
mov iResult, eax
}
[/cpp]
-
Jo, der Inline Assembler funtzt jetzt.
Danke für den kleinen Tip!Das richtige Ergebnis 20c5a9bb (hex) wird nun auch zurückgegeben.
Aber leider in meiner C++ Funktion nicht (Wieso ???)Die Fehlermeldungen beim Inline Assembler kommen, wenn ich die Werte
nicht direkt sondern über Variablen übergebeint iEax,iEdx,iBit,iResult; iEax = Edit1->Text.ToInt(); iEdx = Edit2->Text.ToInt(); iCl = Edit3->Text.ToInt(); _asm { mox cl,iCl mov edx,iEdx mov eax,iEax shrd eax,edx,cl mov iResult, eax }
Fehlermeldung : Operants types do not match (Was passt nicht zusammen ???)
-
Keiner 'ne Ahnung ???????????????
-
Doch ich!
Also:
Bei Der Fehlermeldung drücken wir mal F1:
[C++ Fehler] Unit1.cpp(28): E2510 Operandengröße stimmt nicht überein
Und da steht als Beschreibung:
Die vom Operanden benötigte Größe stimmt nicht mit der angegebenen Größe überein.
asm mov ax,123456;
In diesem Beispiel gibt der Compiler einen Fehler aus, weil versucht wird, einen zu großen Wert in ein 8-Bit-Register zu verlagern.
asm mov eax,123456;
Die Lösung für dieses Beispiel besteht darin, den Wert in ein 32-Bit-Register zu verlagern.
So, jetzt wissen wir, dass iCl und cl von der Bit-Länge her nicht übereinstimmen.
cl ist ein 8 Bit-Register in das man keinen 32 Bit int laden kann, also muss man sich für iCl einen passenden Datentypen suchen ...
[cpp]void __fastcall TForm1::Button1Click(TObject *Sender)
{
int iEax,iEdx,iResult;
__int8 iCl; //Alles klar Herr Kommissar?iEax = Edit1->Text.ToInt();
iEdx = Edit2->Text.ToInt();
iCl = Edit3->Text.ToInt();_asm
{
mov cl,iCl
mov edx,iEdx
mov eax,iEax
shrd eax,edx,cl
mov iResult, eax
}
}[/cpp]Tipp: Hilfe + Index + "Datentypen" hilft manchmal ...
-
Alles klar CHEF !!!
Mein eigentliches Problem ist aber immer noch da.
Die portierung in C++ mit dem Fehler bei negativen zahlenDank dir trotzdem für die Nachhilfe in Assembler, vielleicht fällt dir ja was
in meinem C++-Code auf (ist ja auch mein Hauptanliegen gewesen !)MfG