cdecl version

by Michael Calkins (Login MCalkins)
ASM Forum

 
---- testrnddll2.asm ----
global _rnd

section .text                  ; read-only code

_DllMain@12:                   ; int __stdcall DllMain(void *, unsigned int, void *)
mov eax,1
ret 0xc

_rnd:                          ; extern "C" __declspec(dllexport) unsigned int rnd(unsigned int * const);
mov ecx,[esp+4]
mov eax,0xfd43fd
mul dword [ecx]
add eax,0xc39ec3
and eax,0xffffff
mov [ecx],eax
ret
----

---- testrndexe2.asm ----
extern __imp__GetStdHandle
extern __imp__WriteFile
extern __imp__rnd

STD_OUTPUT_HANDLE equ -11

section .text                  ; read-only code

_main:                         ; int mainCRTStartup(void)

mov dword [_seed],0x50000
mov word [_crlf],0xa0d
push _seed

push STD_OUTPUT_HANDLE         ; nStdHandle
call [__imp__GetStdHandle]
mov [_stdout],eax

mov byte [_i],8
.outerloop:                    ; outer loop iterates 8 times, calling rnd and printing result

call [__imp__rnd]              ; rnd leaves the constant pointer to seed on the stack
mov edx,eax
mov edi,_crlf-1
std

.innerloop:                    ; inner loop converts result to hex numerals

mov al,dl
and al,0xf
cmp al,9
jbe .skip
add al,'a'-('9'+1)
.skip:
add al,'0'
stosb

shr edx,4
jnz .innerloop

cld                            ; otherwise WriteFile to console fails
push 0                         ; lpOverlapped
push _trash                    ; lpNumberOfBytesWritten
inc edi
mov eax,_endbuffer
sub eax,edi
push eax                       ; nNumberOfBytesToWrite
push edi                       ; lpBuffer
push dword [_stdout]           ; hFile
call [__imp__WriteFile]

dec byte [_i]
jnz .outerloop

pop eax                        ; remove rnd's parameter
xor eax,eax
ret                            ; from mainCRTStartup to operating system, exiting process.

section .bss                   ; read/write uninitiallized data

_buffer: resb 8
_crlf: resb 2
_endbuffer:
_i: resb 1
resb 1                         ; padding to align 4
_seed: resd 1
_stdout: resd 1
_trash: resd 1
----

---- mtestrndasm2.bat ----
nasm -f win32 -o testrnddll2.o testrnddll2.asm
\qb64\internal\c\c_compiler\bin\ld -s -shared --enable-auto-image-base -dy --nxcompat -o testrnddll2.dll testrnddll2.o
nasm -f win32 -o testrndexe2.o testrndexe2.asm
\qb64\internal\c\c_compiler\bin\ld -s -dy --nxcompat -o testrndexe2.exe testrndexe2.o testrnddll2.dll %windir%\system32\kernel32.dll
----

2,560 testrnddll2.dll
1,536 testrndexe2.exe

In these "2" marked files, the caller EXE owns the seed, and the DLL's cdecl function leaves the constant pointer on the stack. The EXE knows that the DLL has not modified it, so just leaves it alone through the multiple function calls. It is removed at the end, in preparation to return to the operating system. (To remove a bunch of parameters, you could add to ESP. But to remove 1, I used a pop.) The function's external name is "rnd", now lowercase because it's cdecl.

The "2" marked EXEs and DLLs from the asm and mingw versions should be interchangable with each other.

Regards,
Michael

Posted on Sep 16, 2017, 8:40 PM

Respond to this message   

Return to Index

 Copyright © 1999-2017 Network54. All rights reserved.   Terms of Use   Privacy Statement  

Quantcast