I tried explicitly setting the data segment register to the data
segment in my DLL before pushing the message box parameters onto the
stack (thinking that may be the problem), but the linker wouldn't let
me do that.
What am I missing? Any help that anyone could offer would be greatly appreciated.
I'm running this on a Pentium III based machine under Windows 2000. My
code follows.
~~~~~ GMENCRPT.ASM ~~~~~
; GMENCRPT.DLL
;
; Author: George F Marcus Jr
; Edition: 09.17.2003
GLOBAL EncryptA
EXPORT EncryptA
GLOBAL GMEncrptVer
EXPORT GMEncrptVer
EXTERN MessageBoxA
[SEGMENT CODE PUBLIC USE32 CLASS=CODE]
; STDCALL Entry Point - Flag success & return 3 parameters (DWORD)
..start:
mov EAX, 1 ;Flag success
ret 12 ;Remove 3 parameters (DWORD) from stack
EncryptA: ;Expects one DWORD on stack - Address of C
string
ret 4 ;Clean up stack
GMEncrptVer:
push dword 0 ;OK button
push dword VerTitle ;Title
push dword VerText ;MsgBox Text
push dword 0 ;Window Handle
call MessageBoxA ;Call API Function
ret
[SEGMENT DATA PUBLIC USE32 CLASS=DATA]
VerTitle: db 'GMarc Encryption Library',0
VerText: db 'Version 1.0.1',0
~~~~~ End GMENCRPT.ASM ~~~~~
~~~~~ GMLIB.ASM ~~~~~
; GMLIB.OBJ
;
; Author: George F Marcus Jr
; Edition: 09.17.2003
GLOBAL MessageBoxA
IMPORT MessageBoxA User32.DLL
~~~~~ End GMLIB.ASM ~~~~~
I assembled the above two files using the following:
NASMW -fobj -E GMLIB.ERR GMLIB.ASM
NASMW -fobj -E GMENCRPT.ERR GMENCRPT.ASM
I linked the two object files with ALINK using the following:
ALINK -oPE -dll GMENCRPT.OBJ GMLIB.OBJ
The declaration and function call I'm using within VB is as follows:
Public Declare Sub GMEncrptVer Lib "GMEncrpt" ()
Sub ShowGMEncrptVer
GMEncrptVer
End Sub
I'm not sure if this is true of Nasm, but when I do inline assembly in VC
all the functions I call in other DLLs are really function pointers, and you
have to use an extra level of indirection. This is probably the problem
since you make a direct call. The way DLLs work is that you link against a
"stub" for the function. You get a 4-byte pointer in your data segment, and
when you load the loader places the address of that function in the stub.
The symbol MessageBoxA points to the stub, not the function MessageBoxA.
Here's an example if it helps to elaborate:
section .data
funptr dd myfunc
section .text
...start:
call myfunc ; Direct call
call dword [funptr] ; Indirect call like DLL imports
mov [funptr], dword myfunc2
call dword [funptr] ; Calls myfunc2 this time
ret
myfunc:
ret
myfunc2:
ret
Now, it is also possible to do this:
MessageBoxA: ; symbol visible to you
jmp MessageBoxAStub ; dummy stub for loader (it doesn't care about
symbol name)
MessageBoxAStub resd 1 ; Loader fills this in with MessageBoxA
But that would depend on your libraries, and I doubt that is the case.
Oh, and btw, you should never need to play with cs, ds, es, or ss. In fact,
don't. Windows assumes that cs = base 0, limit 4 GB - 1,
read-only/executable and ds = es = ss = base 0, limit 4 GB - 1, read-write.
The other segment registers are also off-limits.
-Matt
"George Marcus" <george...@encompassins.com> wrote in message
news:f93e2486.03091...@posting.google.com...
Thank you very much for your help. Dereferencing the typed pointer
worked like a charm. I tried this with out explicitly declaring the
function pointer as a 'dword' (ex. call [MessageBoxA]) before making
my initial post. That didn't work and I was really at a loss as to
what the problem was. Again, thanks for your help. I guess programming
in assembly is all in the details.
George
"Matt Taylor" <pa...@tampabay.rr.com> wrote in message news:<NZIab.9946$Od.4...@twister.tampabay.rr.com>...