flat assembler
Message board for the users of flat assembler.
Index
> Windows > Calling FASM dll from C# in x86-64 |
Author |
|
revolution 03 Oct 2014, 09:50
The 64-bit fastcall standard says that float parameters are returned in the XMM registers.
|
|||
03 Oct 2014, 09:50 |
|
jaytea 03 Oct 2014, 09:56
Thanks revolution. I'll try again in the morning, but what I have suspected is that the FPU registers coincide with the XMM registers because I have successfully used either to return from my function the first value passed into my functiom. It could be that MS code checks which I use. In any event I'm pretty sure my return method is not the issue since I can successfully (if not correctly) use FPU registers to return floating point values. If the issue was which register I used to return then why did my code ever work? What I'm personally suspicious of is the handling of the parameters. I could be too tired to see my mistake, either way thanks for your response!
|
|||
03 Oct 2014, 09:56 |
|
jaytea 03 Oct 2014, 10:20
Revolution,
Thanks again for your input, would you care to provide a link to the source of your information? I tried to google the subject and found very little new information, so that would be appreciated. -John Thoits |
|||
03 Oct 2014, 10:20 |
|
revolution 03 Oct 2014, 11:15
The x64 Application Binary Interface (ABI) is a 4 register fast-call calling convention, with stack-backing for those registers. There is a strict one-to-one correspondence between arguments in a function, and the registers for those arguments. Any argument that doesn’t fit in 8 bytes, or is not 1, 2, 4, or 8 bytes, must be passed by reference. There is no attempt to spread a single argument across multiple registers. The x87 register stack is unused. It may be used, but must be considered volatile across function calls. All floating point operations are done using the 16 XMM registers. The arguments are passed in registers RCX, RDX, R8, and R9. If the arguments are float/double, they are passed in XMM0L, XMM1L, XMM2L, and XMM3L. 16 byte arguments are passed by reference. Parameter passing is described in detail in Parameter Passing. In addition to these registers, RAX, R10, R11, XMM4, and XMM5 are volatile. All other registers are non-volatile. Register usage is documented in detail in Register Usage and Caller/Callee Saved Registers. |
|||
03 Oct 2014, 11:15 |
|
jaytea 03 Oct 2014, 23:02
Thanks again revolution, I got it working using the information you linked! It has joined the exclusive ranks of my bookmarks.
Since the macros handle the input of a double array well in 32-bits I was expecting what worked there to also work in 64-bits, but I guess I was either wrong, did it wrong or there is some bug in the proc macro in handling the parameters. Doing it manually and using the registers is working fine. Clearly the reason I thought that I was able to return the first parameter of a call double(double) was because that parameter was already in the return register! My 32-bit code (called as a double(double[]) and works fine): Code: proc return input:qword fld qword [input] ret endp Didn't work when translated into 64-bit code (also called the same): Code: proc return input movsd xmm0,[input] ret endp But by following the guide on the 64-bit calling convention this accomplished the same as the 32-bit code: Code: proc return movsd xmm0,[rcx] ret endp I did try specifying the input as input:qword in 64 even though I'm pretty sure that doesn't mean anything different, but that didn't help. I'll just program for 64 using the more manual approach to handling paramters. |
|||
03 Oct 2014, 23:02 |
|
typedef 04 Oct 2014, 02:42
If you want to return a value so bad why not just pass a memory pointer and fill that space with the return value? Make it a struct and you can return more than one value.
|
|||
04 Oct 2014, 02:42 |
|
Tomasz Grysztar 04 Oct 2014, 08:29
jaytea wrote: Since the macros handle the input of a double array well in 32-bits I was expecting what worked there to also work in 64-bits, but I guess I was either wrong, did it wrong or there is some bug in the proc macro in handling the parameters. Doing it manually and using the registers is working fine. You may find the explanation for this in the fasm's documentation: '1.4 Procedures (64-bit)' wrote: It should be noted however that in the calling convention used in 64-bit Windows first four parameters are passed in registers (RCX, RDX, R8 and R9), and therefore, even though there is a space reserved for them at the stack and it is labelled with name provided in the procedure definition, those four parameters will not initially reside there. They should be accessed by directly reading the registers. You may also note this part in the fasm's template for 64-bit application (examples/win64/template/template.asm): Code: proc WindowProc uses rbx rsi rdi, hwnd,wmsg,wparam,lparam ; Note that first four parameters are passed in registers, ; while names given in the declaration of procedure refer to the stack ; space reserved for them - you may store them there to be later accessible ; if the contents of registers gets destroyed. This may look like: ; mov [hwnd],rcx ; mov [wmsg],edx ; mov [wparam],r8 ; mov [lparam],r9 cmp edx,WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,rcx,rdx,r8,r9 jmp .finish .wmdestroy: invoke PostQuitMessage,0 xor eax,eax .finish: ret endp |
|||
04 Oct 2014, 08:29 |
|
jaytea 04 Oct 2014, 21:57
Thanks Tomasz, now I understand my error.
|
|||
04 Oct 2014, 21:57 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.