This example illustrates how to make a DLL in assesmbly language and uses in Gamemaker.
Below is everything you need to compile this example including the example too.
if that doesn't work try this: Link Be sure to choose the "Automated" Installer.
Okay, this example will use Nasm to assemble the assembly source into an object file and will use MinGW compiler set to link everything into a DLL.
Below in small print is the explaination of the assembly example. Read it if you want to know how to use assembly with game maker.
Alright, let's go through the source.
SEGMENT code Use32What this directive does is make all the code after this line be assigned to the "code" segment. Segments allow object files and executives have separate parts in their code and data so that everything isn't in one place at once. And if that we're to happen, code would unintentionally be executing data and it's practically a nightmare after that. Use32 makes the generate machine code 32-bit, so and addressing mode specifiers in the opcode is made 32-bit instead of 16. Which I think 16-bit is the default. But you don't need to know about the opcode bytes in this case.
global _DllMain global _myfuncThese two lines make the symbols _DllMain and _myfunc global. It's like in game maker, other objects can see global variables but not local. And this source file is the game object in this case. So since these two symbols are global, the scope of these two symbols will remain visible to other objects and the linker. Though sometimes when referencing a global symbol you have to use the extern keyword to tell the assembler that there is an external symbol. Why these are global are for two reasons, one is _DllMain needs to be global so the compiler can acknowledge it and use it as an entry point, where as all Dll's have the common entry point of "DllMain". And second _myfunc is the test function that the GM example will use and definitely needs to be global so that the linker can find the location of the symbols when trying to export.
_myfunc: push ebp mov ebp, esp fld qword [ebp + 8];Load/Push the argument onto the FPU register stack fadd st0, st0;//Add it by itself or multiply by 2 ;mov esp, ebp; Would need this line if we messed with stack pointer pop ebp retHere is the code that follows after the defined _myfunc symbol and ends at the procedure's return instruction. The first two instructions establishes a stack frame by saving the stack frame pointer ebp by pushing it onto the stack and moves ebp values to the stack pointer register's value. If this routine had local variables, then ESP(Stack pointer register) would have been subtracted to dynamically allocate space for these variables. Esp is subtracted because the stack grows down to lower addresses.
The next two lines are the two FPU instructions that add the given argument by itself thus making a multiplication by two. The first one is "fld", its an instruction that pushes the given operand onto the register stack. when dealing with double's or floats, these are floating point data types that are different than integers because they have extra information that gives the decimal place of the number. A double is called double because it is twice of a float, or a single precision float point unit, hence double-precision. Certain fields of bits in these FPU data types are the exponential part, which gives it it's decimal place. The FPU is a coprocessor that has it's own enviroment on the CPU, it's a co-processor because of the sheer amount of work it would take the CPU to do these float points or fractional calculations without the loss of speed. So "stack" is used to perform algebraic operations. There are 7 64-bit registers that act as the FPU stack. I won't get into more of this but all you need to know is that the instruction takes the argument given by the GM code and pushes it onto the top of the stack. The next two instructions adds the top of the register stack by it's self thus multiplying it by two. And the ret instruction simply restores the instruction pointer thus returning back to the caller.
And the rest you can see in the comments is explained.
When exporting, a .def file is used to list all the symbols to be external. You can find more about those on google.
I made a slight mistake in the code, when stdcall is used, the dll is suppose to clean up the arguments passed. But game maker obviously has a calling facility that checks the stack pointer register before the call to the enternal routine and saves it and restores it when coming back from the external procedure. So I'm glad mark added that.
So yeah, when writing procedures in ASM, be sure to globalize them and add a "_" suffix to the real name of the symbol that you want exported. And in the export definition file(.def file) specify the name of the symbol without the add underscore prefix. And then to make the DLL, compile the dll with the already compiled assembly object files, and you can also mix C/C++ code in there too. And don't forget to pass the definition file to the compiler also.
And that's about it, to compile it you must use MinGW. MinGW is a set of exe's that act as compilation tools. And they will make your source from your assembly code into a DLL.
When using doubles in gamemaker always use FPU instructions in assembly when handling these values.