News:

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

Annoyingly Vague Inquiry

Started by baltoro, August 08, 2009, 06:57:45 PM

Previous topic - Next topic

baltoro

I've been working on a project in C++, using Visual Studio as my main development tool. It's a DirectX application, and really, kind of boring. Anyway, I found it necessary to write a couple of routines in assembly for it using MASM (and, compiling these as a DLL that the main application is dependent on). Naturally, I made vast numbers of incredibly dumb mistakes. But the thing that I had the hardest time getting to work OK, was finding the correct format for the assembly PROC declaration, and the corresponding function declaration that best fit the circumstances in the C++ header file. The book that I am using to learn assembly language ("Assembly Language for Intel-Based Computers, Fifth Edition", 2007 by Kip Irvine) is practically useless in this regard (especially it's description of FPU instructions), and an extended search of the Internet failed to turn up anything really comprehensive. I eventually got the project working correctly (mainly by trial and error), but I found the entire process frustrating, and time consuming.
What I'm wondering is: do any of you know of any really useful websites that explain the techniques involved with interfacing an assembly DLL to a Visual C++ application?
Baltoro

dedndave

we have a few members that are very handy to have around
Vortex, Donkey, Agner Fog, and RandallHyde are all members that have sites to learn a great deal from
for FPU - Raymond has a nice html tutorial on his site
the GoAsm and JWAsm guys also have sites that you might find useful
there are others i am forgetting, of course - my appologies guys
also, there are several members that do not have sites that know their way around pretty well
that list is too long to mention - lol

baltoro

Dave,   
Actually, that is a good suggestion. And, it's one of the first things I tried when I started frequenting the MASM forum site. Edgar's code, especially, is a goldmine. Raymond's Simply FPU Tutorial is better than the entire FPU chapter of Irvine's book. But, the interface between Visual Studio and MASM is a HUGE black hole for me. The basic concept is simple, but, I end up guessing at every instance. Basically, I'm a lousy programmer.   
For instance, in Irvine's book he states that a REAL4 can be contained in a DWORD. So, in my initial assembly routine, I was trying to export a 32-bit single precision float declared as a DWORD in the assembly routine PROC. Just could not get it to work. I wasn't even sure if it was a pointer or not (or, say, a pointer to a pointer). Anyway, finally, I exported the variable as a REAL4 and in the C++ header, declared it as a PFLOAT (the standard Visual Studio Windows headers don't even define a REAL4). To my amazement, this worked perfectly (using, __declspec(import) which, I think is compatible with a pointer to the REAL4). Otherwise, I was crashing the C++ application (and, tearing out my hair).
Baltoro

Astro

#3
Hi,

REAL4 in C++ is type float (or unsigned float), and occupies 4 bytes.

REAL8 in C++ is type double (or unsigned double), and occupies 8 bytes.

Hope this helps!

I found the easiest way to think of it is not in terms of data type (floating point, integer) but in terms of data length. After all, the computer doesn't really know or care - YOU give this bunch of bits a meaning.  :U

The other thing to remember is the computer can only operate on numbers. Everything is a number at the end of the day. This sentence is just a bunch of numbers. I found that once I started thinking of it in those terms, it all fell into place. Now I'm just figuring out how to marshal those numbers to where I want them.  :8)

Best regards,
Astro.

ecube

baltoro,
you can compile the MASM code in a static link library and link that code right into your c++ code, here's an example lib

;mylib.asm

include \masm32\include\masm32rt.inc

MsgBox proto C :DWORD,:DWORD,:DWORD,:DWORD
.code

MsgBox proc iwnd:DWORD,iMsg:DWORD,iTitle:DWORD,iIcon:DWORD
invoke MessageBox, iwnd,iMsg,iTitle,iIcon
ret
MsgBox endp
End


;build.bat
:MAKE
\MASM32\BIN\ML /c /coff /Cp mylib.asm
\MASM32\BIN\link /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm32\lib mylib.obj
pause


then you can include the newly built lib by copyin the lib to 1 of vs's search directories(or same dir as your project) and using
#pragma comment(lib, "mylib.lib")

MichaelW

#5
I have not touched C++ in years, so I used C to create an example app that interacts with a DLL created with MASM. I assumed that the goal is to use Load-Time Dynamic Linking. See the attachment.

The only even slightly difficult part was figuring out how to export data from the DLL, and I found the necessary information here:

http://support.microsoft.com/kb/90530

A fair amount of related information is available in Agner Fog's Calling Conventions PDF, available here:

http://www.agner.org/optimize/
eschew obfuscation

baltoro

Thanks for the answers, the information is useful. I know the question was kind of simple, and easy to solve, but, I wanted to know if there was anything else to it that I should be aware of.
And, thanks MichaelW, that was really my main source of confusion: what the C++ compiler was doing with the __declspec (dllimport) modifier of the function declaration. I had been told by another assembly programmer that everything in assembly language is a pointer (slight oversimplification). But, I wasn't sure what the correct syntax was supposed to be associationg the assembly PROC statement and the imported C++ function declaration. The Visual Studio compiler will allow any type declaration for a variable as long as the number of parameters in the signature is the same, and it compiles (and, it has the LIB file, the Exports file, and the actual DLL). But, it doesn't work correctly if you don't treat it as a pointer in the C++ code.   
Anyway, thanks again.
Baltoro

MichaelW

One detail that I intended to mention is that floating-point values are commonly passed directly on the stack instead of through a pointer, and Invoke and Proc are designed to handle this. A float (REAL4, 32 bits) is placed on the stack with a single push, and a double (REAL8, 64 bits) with two pushes, high-order 32 bits first, followed by the low-order 32 bits.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      float   REAL4 ?
      double  REAL8 ?
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
testproc proc _float:REAL4, _double:REAL8
    fld _float
    fld _double
    fmul
    ret
testproc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke testproc, float, double

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

00401000                    fn_00401000:
00401000 55                     push    ebp
00401001 8BEC                   mov     ebp,esp
00401003 D94508                 fld     dword ptr [ebp+8]
00401006 DD450C                 fld     qword ptr [ebp+0Ch]
00401009 DEC9                   fmulp   st(1),st
0040100B C9                     leave
0040100C C20C00                 ret     0Ch
0040100F                    start:
0040100F FF3508304000           push    dword ptr [403008h] ;double+4
00401015 FF3504304000           push    dword ptr [403004h] ;double
0040101B FF3500304000           push    dword ptr [403000h] ;single
00401021 E8DAFFFFFF             call    fn_00401000

eschew obfuscation