Ich möchte einige lange Ganzzahl Mathe (128 Bit) mit Intel I64 Assembler tun und müssen ein Zweierkomplement erstellen. Nehmen wir an, mein positiver Wert liegt in RDX: RAX.Zweierkomplement der langen Ganzzahl
2er Komplement erfolgt durch "Flip die Bits und add 1". Also die meisten naive Implementierung (4 Anweisungen und 14 Byte-Code):
NOT RAX
NOT RDX
ADD RAX,1 ; Can't use INC, it doesn't set Carry
ADC RDX,0
Wenn ich die NEG-Befehl auf RAX statt NICHT verwenden, ist es nicht die „+1“ für mich, aber die Carry ist falsch, NEG RAX löscht Carry, wenn RAX gleich Null war, aber ich brauche NUR in diesem Fall. So könnte der nächstbeste Ansatz sein (4 Instruktionen und 11 Bytes Code):
NOT RDX
NEG RAX
CMC
ADC RDX,0 ; fixed, thanks lurker
Noch 4 Anweisungen. Aber anstatt +1 zu addieren, kann ich -1 subtrahieren und da SBB das Carry-Bit zum Subtrahend addiert, werde ich +1 addieren, wenn Carry klar ist. Also mein nächster bester Versuch das ist, mit 3 Anweisungen und 10 Byte Code:
NOT RDX
NEG RAX
SBB RDX,-1
Wie Sie aus meinem langen umständlichen Text sehen können, ist dies nicht offensichtlich zu verstehen. Gibt es eine bessere, verständlichere Möglichkeit, ein kaskadiertes Zweierkomplement in Assembler zu erstellen?
Sie scheinen davon auszugehen, dass "besser" gleich "kürzerer Code" ist, und das ist etwas, das nicht für einen Multi-skalaren Out-or-order-Prozessor gelten muss, wie der x86-64 ist. Ich würde sagen, dass die unterste Tabelle Ihrer Implementierungen die erste ist, und ich wäre nicht überrascht, wenn alle die gleiche Zeit zur Ausführung benötigen. –
BTW: Haben Sie überlegt, die XMM-Register zu verwenden?Sie sind breit genug, um eine 128-Bit-Nummer zu halten und (ich habe nicht überprüft) sie haben möglicherweise Integer-Anweisungen, um mit der ganzen Zahl –
@mcleod_ideafix sie nicht tun, so dass Sie immer noch mit dem Problem der Durchführung der tragen übrig manuell. – harold