NASM - The Netwide Assembler
NASM Forum => Example Code => Topic started by: dapleal on June 16, 2013, 04:31:51 AM
-
Since I´ve been getting help from this Forum for months, I feel like it´s time to share either. I hope this small contribution could be of any use to somebody. So, here goes an example of how to write a .DLL file. Note: it´s written as a .ASM file, and then it has to be compiled as .DLL.
;[size=10pt] ?
GLOBAL DllMain
EXPORT DllMain
GLOBAL myFuncX1
EXPORT myFuncX1
GLOBAL myFuncX2
EXPORT myFuncX2
section .code use32
..start:
DllMain: ; This code is required in .dll files
mov eax,1
ret 12
myFuncX1:
; FUNCTION #1
; A- passed parameters:
; required: value#1 , value#2
;
; example:
; push dword [0x500]
; push dword [0x010]
; call [myFuncX1]
;
; B- this function returns:
; EAX= value#1 + value#2
push ebp
mov ebp, esp
mov eax, dword [ebp+08] ; eax=value#1
mov ecx, dword [ebp+12] ; ecx=value#2
add eax, ecx ; eax=eax+ecx
xor ecx, ecx ; ecx=0
pop ebp
ret 8
myFuncX2:
; FUNCTION #2
; A- passed parameters:
; required: value#1 (e.g.: 0xabcd1234)
;
; example:
; push dword [0xabcd1234]
; call [myFuncX2]
;
; B- this function returns:
; EAX= Pointer to zero-terminated string.
; ( e.g.: if value#1 = 0xabcd1234
; then [EAX]= db "ABCD1234",0 )
;
; Use: This simple routine helped me monitor and fix bugs by
; displaying the resulting string using a message box.
; NOTE: the code for displaying the message box is not
; part of this .dll.
push ebp
mov ebp,esp
mov eax,[ebp+08] ; gets the passed argument (value#1) and stores it in EAX
; from now on, the code gets the ASCII value corresponding to
; each one of the 8 digits of (value#1)
; (e.g.: value#1= 0xabcd1234
; the code gets: "A","B","C","D","1","2","3","4"
; and store those values into a memory buffer
; beginning at [ebp-4088] ; (ebp-4096+9) **decimal
; and ending at [ebp-4096]= 0
; (Note: 0 not "0", at the end)
push ebx
push ecx
push edx
push edi
push esi
xor edx,edx
xor ebx,ebx
xor ecx,ecx
mov cl,0x04
mov bl,0x08
mov edx,eax
mov edi,ebp
sub edi,4096
mov al,0x00
mov [edi],al
dec edi
mov eax,edx
bjmp1lbl:
and eax,0x0000000f
cmp al,0x09
ja bjmp2lbl
add al,0x30
jmp bjmp3lbl
bjmp2lbl:
sub al,0x09
add al,0x40
bjmp3lbl:
mov [edi],al
dec edi
shr edx,cl
mov eax,edx
dec bl
jnz bjmp1lbl
inc edi
lea ebx,[edi] ; EBX= memory address of beginning of text data
; (zero-terminated string)
mov eax, ebx ; EAX returns as szPointer value
;(all other registers are restored their original values)
pop esi
pop edi
pop edx
pop ecx
pop ebx
pop ebp
ret 4
; [/size] ?
-
Thanks for the contribution, Daniel! I put "code tags" around it for ya (hope I didn't edit anything else!). Just the word "code" in square brackets (like a Nasm memory reference), and "/code" at the end. To my dismay, it doesn't say that anywhere obvious...
Anyway... how do we compile it as a .dll? I think I know the answer... "nasm -f obj ..." and "alink -oDLL ...", but it might be nice to have the "official" (your) instructions. Nasm does so many things that I think it's useful to put Nasm and linker command lines as a comment at the top of the code (I don't always do it!).
Another possible nit... where you declare your "section .code", the "use32" is absolutely necessary (in a 32-bit "-f obj" file). As I recall, it helps to add "class=CODE" here. As I recall, Ollydbg complains about "entrypoint outside .text section" (or some such), and Agner Fog's "objconv" gets confused without it. Experiment for me (if you're so inclined) and see what, if any, difference it makes.
Best,
Frank
-
Ok. Thanks for the feedback.
This is how I compiled the .dll file:
nasm -fobj fileName.asm
alink fileName.obj -oPE -dll
-
Good. Thanks!
But "-f obj" is rather an obsolete format (OMF), and Nasm does a half-baked job with the 32-bit extensions. You might be better off to use "-f win32" if you can figure out how to do it...
Best,
Frank