Frage

Wie würde ich mich über ...

  • Multiplizieren zwei 64-Bit-Zahlen

  • Multiplikation zweier 16-stellige hexadezimale Zahlen

... mit Assembly Language.

Ich bin nur zu verwenden Register% eax, ebx% erlaubt,% ECX% edx und den Stapel.

EDIT: Oh, ich bin mit ATT Syntax auf dem x86-
EDIT2: Nicht erlaubt in Montage zu dekompilieren ...

War es hilfreich?

Lösung

Verwenden Sie, was wahrscheinlich Kurslehrbuch sein sollte, Randall Hyde "The Art of Assembly Language".

Siehe 4.2.4 - Erweiterte Precision Multiplikation

  

Obwohl eine 8x8, 16x16 oder 32x32 mehrfach in der Regel ausreichend ist, gibt es Zeiten, wenn Sie größere Werte zusammen multiplizieren können wollen. Sie werden die x86 einzelnen Operanden MUL und IMUL Anweisungen für erweiterte Präzision Multiplikation verwenden ..

     

Wahrscheinlich die wichtigste Sache zu erinnern , wenn eine erweiterte Präzision Multiplikation durchzuführen ist, dass Sie auch eine mehrfache Präzision zusätzlich zur gleichen Zeit durchführen muss, . Addiert man alle Teilprodukte erfordert mehrere Ergänzungen, die das Ergebnis produzieren wird. Die folgende Auflistung zeigt die richtige Art und Weise zwei 64-Bit-Werte auf einem 32-Bit-Prozessor zu multiplizieren ..

(Siehe den Link für eine vollständige Montage Auflistung und Abbildungen.)

Andere Tipps

Wenn dies 64x86,

function(x, y, *lower, *higher)
movq %rx,%rax     #Store x into %rax
mulq %y           #multiplies %y to %rax
#mulq stores high and low values into rax and rdx.
movq %rax,(%r8)   #Move low into &lower
movq %rdx,(%r9)   #Move high answer into &higher

Da Sie auf x86 sind benötigen Sie 4 Mull Anweisungen. Teilen Sie die 64-Bit-Mengen in zwei 32-Bit-Worte und multiplizieren die niedrigen Worte auf die niedrigste und 2. niedrigste Wort des Ergebnisses, dann beide Paare von niedrigen und hohen Wort aus verschiedenen Zahlen (sie gehen in die 2. und 3. niedrigste Wort des Ergebnisses) und schließlich beide hohe Wörter in die zwei höchsten Worte des Ergebnisses. Fügen Sie sie alle zusammen nicht mit tragen umgehen zu vergessen. Sie haben nicht das Speicherlayout der Eingänge angeben und Ausgänge, so dass es unmöglich ist, Beispielcode zu schreiben.

Dieser Code wird davon ausgegangen Sie x86 wollen (nicht x64-Code), dass Sie wahrscheinlich nur ein 64-Bit-Produkt wünschen, und dass Sie kümmern sich nicht um Überlauf oder Zahlen mit Vorzeichen. (A signierte Version ist ähnlich).

MUL64_MEMORY:
     mov edi, val1high
     mov esi, val1low
     mov ecx, val2high
     mov ebx, val2low
MUL64_EDIESI_ECXEBX:
     mov eax, edi
     mul ebx
     xch eax, ebx  ; partial product top 32 bits
     mul esi
     xch esi, eax ; partial product lower 32 bits
     add ebx, edx
     mul ecx
     add ebx, eax  ; final upper 32 bits
; answer here in EBX:ESI

Dies berücksichtigt nicht die genauen Register Einschränkungen OP, aber das Ergebnis paßt vollständig in den von der x86 angebotenen Registern. (Dieser Code ist nicht getestet, aber ich denke, es ist richtig).

[Anmerkung: Ich übertrage (my) diese Antwort von einer anderen Frage, die geschlossen wurde, weil keine der anderen „Antworten“ hier direkt die Frage beantwortet]

.

Es hängt davon ab, welche Sprache Sie verwenden. Von dem, was ich vom Lernen MIPS Montage erinnern, gibt es eine Bewegung von High-Befehl und ein Verschieben von Lo-Befehl oder MFLO und mfhi. mfhi speichert die Top-64-Bit während MFLO speichert die unteren 64 Bit der Gesamtzahl.

ah Montag, schon eine Weile her, seit ich es benutzt habe. also ich nehme an, dass das eigentliche Problem hier ist, dass der Mikrocontroller (was ich verwenden, um Code zu schreiben für in der Montage sowieso) Sie arbeiten, nicht 64-Bit-Register hat? wenn das der Fall ist, Sie gehen der Pause die Zahlen haben Sie mit auseinander arbeiten und mehrere Multiplikationen mit den Stücken durchführen.

das klingt wie es eine Hausaufgabe aus dem Weg, Sie es formuliert haben, so dass ich werde es nicht buchstabiert viel weiter: P

Sie einfach normale lange Multiplikation, als ob Sie ein Paar 2-stellige Zahlen multipliziert, außer jeden „digit“ ist wirklich ein 32-Bit-Integer. Wenn Sie sich die Multiplikation zweier Zahlen an den Adressen X und Y und das Ergebnis in Z speichern, dann, was Sie (in Pseudo-Code) tun möchte, ist:

Z[0..3] = X[0..3] * Y[0..3]
Z[4..7] = X[0..3] * Y[4..7] + X[4..7] * Y[0..3]

Beachten Sie, dass wir die oberen 64 Bits des Ergebnisses sind zu verwerfen (seit einer 64-Bit-Zahl mal eine 64-Bit-Zahl ist eine 128-Bit-Zahl). Beachten Sie auch, dass diese Little-Endian annimmt. Auch seien Sie vorsichtig über einen im Vergleich zu einer Multiplikation ohne Vorzeichen unterzeichnet.

Finden Sie eine C-Compiler, der 64-Bit (GCC funktioniert IIRC) kompilieren ein Programm unterstützt, das genau das tut, dann die Demontage erhalten. GCC kann es ausspucken auf seine eigenen, und Sie können es mit den richtigen Werkzeugen aus der Objektdatei.

OTOH sie ist ein 32bX32b = 64b op auf x86

a:b * c:d = e:f
// goes to
e:f = b*d;
x:y = a*d;  e += x;
x:y = b*c;  e += x;

alles andere überläuft

(ungetestet)

Bearbeiten Unsigned nur

Ich wette sie ist ein Student, so sehen, wenn Sie diese Arbeit machen können: Tun Sie es Wort für Wort, und die Verwendung Bit-Verschiebungen. Denken Sie die effizienteste Lösung auf. Hüten Sie sich vor dem Vorzeichenbit.

Wenn Sie 128-Modus versuchen, diese ...

__uint128_t AES::XMULTX(__uint128_t TA,__uint128_t TB)
{
    union
    {
        __uint128_t WHOLE;
        struct
        {
            unsigned long long int LWORDS[2];
        } SPLIT;
    } KEY;
    register unsigned long long int __XRBX,__XRCX,__XRSI,__XRDI;
    __uint128_t RESULT;

    KEY.WHOLE=TA;
    __XRSI=KEY.SPLIT.LWORDS[0];
    __XRDI=KEY.SPLIT.LWORDS[1];
    KEY.WHOLE=TB;
    __XRBX=KEY.SPLIT.LWORDS[0];
    __XRCX=KEY.SPLIT.LWORDS[1];
    __asm__ __volatile__(
                 "movq          %0,             %%rsi           \n\t"       
                 "movq          %1,             %%rdi           \n\t"
                 "movq          %2,             %%rbx           \n\t"
                 "movq          %3,             %%rcx           \n\t"
                 "movq          %%rdi,          %%rax           \n\t"
                 "mulq          %%rbx                           \n\t"
                 "xchgq         %%rbx,          %%rax           \n\t"
                 "mulq          %%rsi                           \n\t"
                 "xchgq         %%rax,          %%rsi           \n\t"
                 "addq          %%rdx,          %%rbx           \n\t"
                 "mulq          %%rcx                           \n\t"
                 "addq          %%rax,          %%rbx           \n\t"
                 "movq          %%rsi,          %0              \n\t"
                 "movq          %%rbx,          %1              \n\t"
                 : "=m" (__XRSI), "=m" (__XRBX)
                 : "m" (__XRSI),  "m" (__XRDI), "m" (__XRBX), "m" (__XRCX)
                 : "rax","rbx","rcx","rdx","rsi","rdi"
                 );
    KEY.SPLIT.LWORDS[0]=__XRSI;
    KEY.SPLIT.LWORDS[1]=__XRBX;
    RESULT=KEY.WHOLE;
    return RESULT;
}

Wenn Sie 128-Bit-Multiplikation wollen, dann sollte diese Arbeit des in AT & T-Format ist.

__uint128_t FASTMUL128(const __uint128_t TA,const __uint128_t TB)
{
    union
    {
        __uint128_t WHOLE;
        struct
        {
            unsigned long long int LWORDS[2];
        } SPLIT;
    } KEY;
    register unsigned long long int __RAX,__RDX,__RSI,__RDI;
    __uint128_t RESULT;

KEY.WHOLE=TA;
__RAX=KEY.SPLIT.LWORDS[0];
__RDX=KEY.SPLIT.LWORDS[1];
KEY.WHOLE=TB;
__RSI=KEY.SPLIT.LWORDS[0];
__RDI=KEY.SPLIT.LWORDS[1];
__asm__ __volatile__(
    "movq           %0,                             %%rax                   \n\t"
    "movq           %1,                             %%rdx                   \n\t"
    "movq           %2,                             %%rsi                   \n\t"
    "movq           %3,                             %%rdi                   \n\t"
    "movq           %%rsi,                          %%rbx                   \n\t"
    "movq           %%rdi,                          %%rcx                   \n\t"
    "movq           %%rax,                          %%rsi                   \n\t"
    "movq           %%rdx,                          %%rdi                   \n\t"
    "xorq           %%rax,                          %%rax                   \n\t"
    "xorq           %%rdx,                          %%rdx                   \n\t"
    "movq           %%rdi,                          %%rax                   \n\t"
    "mulq           %%rbx                                                   \n\t"
    "xchgq          %%rbx,                          %%rax                   \n\t"
    "mulq           %%rsi                                                   \n\t"
    "xchgq          %%rax,                          %%rsi                   \n\t"
    "addq           %%rdx,                          %%rbx                   \n\t"
    "mulq           %%rcx                                                   \n\t"
    "addq           %%rax,                          %%rbx                   \n\t"
    "movq           %%rsi,                          %%rax                   \n\t"
    "movq           %%rbx,                          %%rdx                   \n\t"
    "movq           %%rax,                          %0                      \n\t"
    "movq           %%rdx,                          %1                      \n\t"
    "movq           %%rsi,                          %2                      \n\t"
    "movq           %%rdi,                          %3                      \n\t"
    : "=m"(__RAX),"=m"(__RDX),"=m"(__RSI),"=m"(__RDI)
    :  "m"(__RAX), "m"(__RDX), "m"(__RSI), "m"(__RDI)
    : "rax","rbx","ecx","rdx","rsi","rdi"
);
KEY.SPLIT.LWORDS[0]=__RAX;
KEY.SPLIT.LWORDS[1]=__RDX;
RESULT=KEY.WHOLE;
return RESULT;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top