Frage

Ich versuche die folgende Funktion anzurufen:

long long RtlLargeIntegerDivide(long long dividend, long long divisor, long long* pRemainder)

im Montagecode (NASM). Es verwendet die STDCall -Anrufkonvention und gibt den Quotienten zurück. Dies sind die Spezifikationen:

Eingabe: [EDX, EAX] (Dividend), [ECX, EBX] (Divisor)

Ausgabe: [EDX, EAX] (Quotienten), [ECX, EBX] (Rest)

Wie mache ich das? (Mein Hauptproblem ist nicht genau das Verständnis von EBP und ESP und wie sie sich auf lokale Variablen beziehen.)

(Und nein, das ist keine Hausaufgaben; ich versuche, eine Laufzeitbibliothek um eine Wrapper-C-Bibliothek zu implementieren.)

Vielen Dank!

War es hilfreich?

Lösung

Im 32 -Bit -Modus müssen Sie EBP nicht verwenden, um auf lokale Variablen zuzugreifen. Dies ist nur ein Kongressrest von 16 Bit und betrifft uns jetzt sowieso nicht.

ESP ist Ihr Stackzeiger, ich nehme an, Sie wissen das. Sie können Platz für Ihre lokalen Variablen "zuweisen", indem Sie ESP verringern.

stdcall Calling Convention verwendet den Stapel für das Bestehen von Argumenten. Sie sind in normaler Reihenfolge, wenn Sie auf dem Stapel sind, aber wenn Sie es verwenden PUSH Das heißt, Sie schieben sie umgekehrt. Integrale Rückgabewerte sind in EAX (und bei Bedarf EDX). Die aufgerufene Funktion reinigt die Argumente aus dem Stapel.

Der folgende Code sollte also das tun, was Sie wollen:

sub  ESP, 8; make room for remainder
push ESP   ; pass pointer to remainder as argument
push ECX
push EBX   ; pass divisor argument
push EDX
push EAX   ; pass dividend argument
call RtlLargeIntegerDivide
; quotient returned in EDX:EAX
; so just load remainder from stack
pop  EBX
pop  ECX

(Für Geschwindigkeit können Sie verwenden MOV Anstatt von PUSH/POP)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top