Search code examples
winapiassemblynasmcalling-conventionstdcall

Calling LONGLONG RtlLargeIntegerDivide(LONGLONG, LONGLONG, LONGLONG*) in NASM (stdcall)


I'm trying to call the following function:

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

in assembly code (NASM). It uses the stdcall calling convention, and it returns the quotient. These are the specifications:

Input: [EDX,EAX] (dividend), [ECX,EBX] (divisor)

Output: [EDX,EAX] (quotient), [ECX,EBX] (remainder)

How do I go about doing this? (My main problem is not exactly understanding EBP and ESP, and how they relate to local variables.)

(And no, this isn't homework; I'm trying to implement a wrapper C run-time library.)

Thank you!


Solution

  • In 32 bit mode you don't have to use EBP to access local variables at all, that is just a convention remnant from 16 bit times and doesn't concern us now anyway.

    ESP is your stack pointer, I assume you know that. You can "allocate" space for your local variables by decrementing ESP.

    stdcall calling convention uses the stack for argument passing. They are in normal order when on the stack, but if you are using PUSH that means you push them reversed. Integral return values are in EAX (and EDX when necessary). The called function cleans up the arguments from the stack.

    So the following code should do what you want:

    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
    

    (For speed, you can use MOV instead of PUSH/POP)