News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

An Extensive Dll Sample

Started by AkinforASM, October 07, 2006, 08:55:10 AM

Previous topic - Next topic

AkinforASM

Dear Friends,

I read the rules and had the impression that campus section seems to be for newbies like me.

Recently I have downloaded RadASM and was really impressed by the power of MASM used thereon. Previously I was an amateur Delphi developer. However, I want to harness power of (M)ASM and have embarked on the learning process.

But the main difficulty I had while studying ASM, as an amateur high level developer (Delphi, formerly object pascal), the asm seems to be lacking data types in the sense of high level languages.

I downloaded several tutorials, authors of which I believe are members here. The normal development process with RadASM by means of Tutorials are really a good experience. The authors of the tutorials did quite a good and extensive job, I belive. For this reason, I take this opportunity to thank them.

Since, nevertheless, the ASM lacks the types in the sense of high level languages, I'm a little bit confused while I was trying to write a dll by means of MASM (on RadASM).

I have created a test dll by using the dll sample provided in the tutorials and by RadASM templates.

I have no problem with the dll entry point. However, I noticed I can not even code a simple arithmetic function like addition, let alone string manipulations (which are piece of cake in Object Pascal).

I would like to present what I did up till now and humbly ask you to show the right direction if you please:

.code
Dll:
DllEntry proc hInstDLL:HINSTANCE, reason:DWORD,reserved1:DWORD
.if reason==DLL_PROCESS_ATTACH
invoke GetModuleHandle,NULL
mov hInstDLL,eax
mov eax,TRUE
.elseif reason==DLL_PROCESS_DETACH
.endif
ret

DllEntry endp

AddTwoIntegers proc Integer1:DWORD,Integer2:DWORD
mov eax,[Integer1]
add eax,[Integer2]
ret

AddTwoIntegers endp

TestFunction proc
;invoke OutputDebugString,addr BurayaNicinGiriyor
invoke MessageBox,NULL,addr MsgText,addr MsgCaption,MB_OK
ret

TestFunction endp

AddTwoStrings proc Text1:LPSTR, Text2:LPSTR
push edx
invoke OutputDebugString, Text1
invoke OutputDebugString, Text2
mov edx, Text1
mov eax, edx
pop edx
ret
AddTwoStrings endp

end Dll


I could not get it working unfortunately. (I exported the relevant functions in .def file too.)

The test function was already in the tutorial, I downloaded. However the other two functions, I tried to code with no results. When I call this two functions through delphi, I cannot either get correct total for two integers, I passed to the function nor appended result of two strings I passed to the other function, although I can load the library and find the procedure addresses successfully.

In addition the tutorial had another tutorial to load and find function addresses and call them accordingly.

However, I would like to learn, how I shall declare a function without having a lib file for that. I can do it on delphi like this:

function AddTwoIntegers(var Integer1, Integer2: Integer):Integer;stdcall;external 'Testdll.dll'


I would be very grateful if someone could tell me how I shall define an external function on MASM (RadASM).

In addition, in the dll use tutorial, the author shows how to load a library and find the procedure addresses dynamically.

However in case of dynamically loading a library and finding address of the functions, how one shall pass parameters the function whose address is found?

I hope I don't violate any rules. Regards and TIA

hutch--

Hi AkinforASM,

Welcome on board. Its a piece of cake to code a DLL in MASM as well, have a look at the DLL tutorial in the MASM32 project, you will find it simple enough to get going.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Vortex

AkinForAsm,

Welcome to the forum.

If I am not wrong, Delphi uses the PASCALL calling convention. This means that you need to specify the PASCALL calling convention when you write your MASM prototypes for Delphi functions designed to be used with MASM.

As I know, Delphi emits OMF object modules, you need to check your Delphi documentation to see if the MS linker converts correctly Delphi object files to MS COFF, the standard used by MS tools.

MASM has a powerfull macro engine and it supports a lot of HLL constructs. Have a look at MASM Programmer's Guide : ( Chapter 7 & 9 )

http://webster.cs.ucr.edu/Page_TechDocs/MASMDoc/index.html

If you are asking about Run-Time Dynamic Linking, I can provide you a simple example :

.386
.model flat, stdcall
option casemap :none

include Demo.inc

.data
library     db 'Console.dll',0
function    db 'StdOut',0
message     db 'Hello world!',13,10,0
message2    db 'This is a console application.',13,10,0

.data?
hLibrary    dd ?
pFunc       dd ?

fcall       TYPEDEF PTR pr1
StdOut      EQU <fcall PTR pFunc>


.code

start:
    invoke  LoadLibrary,ADDR library            ; Run-Time Dynamic Linking
    mov     hLibrary,eax
    invoke  GetProcAddress,eax,ADDR function    ; get the address of the function StdOut
                                                ; exported by Console.dll
    mov     pFunc,eax
    push    OFFSET message                      ; push the OFFSET of the string to the stack
                                                ; the push & call pair is equivalent to
                                                ; invoke StdOut,ADDR message
    call    eax                                 ; eax holds the address of the function
    invoke  StdOut,ADDR message2                ; pFunc ( the address of StdOut ) is prototyped
                                                ; via "fcall PTR pFunc"
    invoke  FreeLibrary,hLibrary                ; unload the DLL                                               
    invoke  ExitProcess,0

END start

[attachment deleted by admin]

japheth

Hi,

the real problem might be your usage of 'var' in

> function AddTwoIntegers(var Integer1, Integer2: Integer):Integer;stdcall;external 'Testdll.dll'

since this will cause Delphi to pass the address of the two integers as arguments, not the integers itself.

Regards


Vortex

QuoteHowever, I would like to learn, how I shall declare a function without having a lib file for that.

AkinForAsm,

Here is an example for you.

The main application CallMsgBox calling the external function :

.386
.model flat, stdcall
option casemap :none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\user32.lib      ; MessageBox ( called by MsgBox ) is exported
                                        ; by user32.dll


MsgBox  PROTO :DWORD,:DWORD             ; prototype for our external function

.data

title1  db 'Hello!',0
msg     db 'I am a message box',13,10
        db 'called from the MsgBox module',0

.code

start:

invoke  MsgBox,ADDR msg,ADDR title1     ; call the function
invoke  ExitProcess,0

END start



MsgBox called by the main module :

.386
.model flat, stdcall
option casemap :none

include \masm32\include\windows.inc
include \masm32\include\user32.inc

.code

MsgBox  PROC message:DWORD,caption:DWORD       ; define a function taking two parameters
                                                ; note that the function is declared public
                                                ; by default
    invoke  MessageBox,0,message,caption,MB_OK  ; display a message box
    ret                                         ; return back to the main module

MsgBox  ENDP                                    ; terminate function definition

END                                             ; end of the file
                                                ; no need to define an entry point


Building the example :

\masm32\bin\ml /c /coff MsgBox.asm

\masm32\bin\ml /c /coff CallMsgBox.asm
\masm32\bin\link /SUBSYSTEM:WINDOWS CallMsgBox.obj MsgBox.obj

[attachment deleted by admin]

AkinforASM

Quote from: Vortex on October 07, 2006, 12:34:01 PM
AkinForAsm,

Welcome to the forum.

If I am not wrong, Delphi uses the PASCALL calling convention. This means that you need to specify the PASCALL calling convention when you write your MASM prototypes for Delphi functions designed to be used with MASM.

Thank you all,

However when you declare an external function with the option stdcall in Delphi, you may use stdcall too. Otherwise it would be very difficult for delphi to call many APIs.

But these answers taught me that I have to read a lot of materials, since, as it seems, I don't understand the fundamentals of ASM, although it's the most basic (or lowest level) programming language. I hope I shall learn the fundamentals by reading through this forum.