2010-12-26 3 views
2

Я пытаюсь вызвать следующую функцию:Вызов Лунлун RtlLargeIntegerDivide (Лунлун, Лунлун, LONGLONG *) в NASM (STDCALL)

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

в коде сборки (NASM). Он использует соглашение о вызове stdcall и возвращает частное. Эти характеристики:

Входной сигнал: [EDX, EAX] (дивидендов), [ECX, EBX] (делитель)

Выход: [EDX, EAX] (фактор), [ECX, EBX] (остаток)

Как мне это сделать? (Моя основная проблема заключается не в том, чтобы точно понимать EBP и ESP, и как они относятся к локальным переменным.)

(И нет, это не домашнее задание, я пытаюсь реализовать библиотеку времени выполнения оболочки C).

Спасибо!

ответ

4

В 32-битном режиме вам не нужно использовать EBP для доступа к локальным переменным вообще, это всего лишь условный остаток с 16-битного времени и в любом случае нас не касается.

ESP - ваш указатель на стек, я полагаю, вы это знаете. Вы можете «выделить» пространство для ваших локальных переменных, уменьшив ESP.

stdcall Конвенция о вызове использует стек для передачи аргументов. Они находятся в обычном порядке, когда на стеке, но если вы используете PUSH, это означает, что вы нажимаете на них в обратном порядке. Интегральные возвращаемые значения находятся в EAX (и EDX при необходимости). Вызываемая функция очищает аргументы из стека.

Итак, следующий код должен делать то, что вы хотите:

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 

(для скорости, вы можете использовать MOV вместо PUSH/POP)

+0

Красивого ответа, спасибо! :) – Mehrdad