flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
patchariadog 26 May 2014, 15:55
I was trying to build a function for x64. the function happens to use more than 4 parameters. in x86 it works fine but I know in x64 with fastcall you have to spill the parameters into the shadow space in the order of rcx,rdx,r8,r9 I read that for 5 and etc you have to pass them onto the stack, but I don't know how to do this. this is what I tried but it keeps saying invalid operand. I know that the first 4 parameters I am doing right because I have made x64 functions before but it is the last 3 I don't know how to spill
Code: proc myfunction,inputstring,outputstring,buffer1,buffer2,buffer3,startposition,length ;spill mov [inputstring],rcx mov [outputstring],rdx mov [buffer1],r8 mov [buffer2],r9 mov [buffer3],[rsp+8*4] mov [startposition],[rsp+8*5] mov [length],[rsp+8*6] I tried this because someone suggested that this would work on http://board.flatassembler.net/topic.php?t=15131 I also tried this Code: mov [inputstring],rcx mov [outputstring],rdx mov [buffer1],r8 mov [buffer2],r9 mov rax,[rsp+8*4] mov [buffer3],rax mov rax,[rsp+8*5] mov [startposition],rax mov rax,[rsp+8*6] mov [length],rax it compiles but it leads to an APPCRASH when I use the substr function can someone please show me how to use fastcall to call a proc that has more than 4 parameters on x64 also do I need to setup more space on the stack because I read somewhere I may need to put add rsp,28h above the spill zone? I am not sure thanks |
|||
![]() |
|
patchariadog 26 May 2014, 17:21
I am still confused
I tried removing all the ;spill and using fastcall and this makes it not function properly. I tried using stdcall and it appcrashes I tried using fastcall and spilling this Code: mov [inputstring],rcx mov [outputstring],rdx mov [buffer1],r8 mov [buffer2],r9 mov [buffer3],r10 mov [startposition],r11 mov [length],r12 and it does not function properly. I am confused because I know I could never convert my x86 functions to x64 untill I learned about the spill for example x86 Code: proc stringlengthx86 uses esi, str ;usage stdcall stringlengthx86,str ;length is stored in eax ;works with rb and dd mov esi, [str] or eax,-1 .Loop: inc eax cmp byte[esi+eax], 0 jne .Loop ret endp only works in x64 when i do this Code: proc stringlengthx64 uses rsi, str ;usage fastcall stringlengthx64,str ;works with dd and rb ;length is stored in eax ;spill mov [str],rcx mov rsi, [str] or rax,-1 .Loop: inc rax cmp byte[rsi+rax], 0 jne .Loop ret endp I just don't know how to spill more than 4 parameters. thanks |
|||
![]() |
|
einar 26 May 2014, 21:14
Hi patchariadog,
I'm not familiar with FASM syntax but I'll try to help you. If you want to make your proc x64 fastcall you don't have to worry about spilling more than first four params because someone who called function already did it. Look at this: Code: ;masm syntax mov qword ptr [rsp+8*6], 16 ; length mov qword ptr [rsp+8*5], 0 ; startposition mov qword ptr [rsp+8*4], 400000h ; buffer3 mov r9, buffer2 mov r8, buffer1 mov rdx, outputstring mov rcx, inputstring call myfunction |
|||
![]() |
|
patchariadog 27 May 2014, 03:16
thanks asmguru 62 and especially einar. after playing around with it for a little bit I found that the only way it seems to work is if I spill the first 4 parameters and then ignore the rest 5-infinity
example Code: proc substr,inputstring,outputstring,buffer1,buffer2,buffer3,startposition,length ;spill mov [inputstring],rcx mov [outputstring],rdx mov [buffer1],r8 mov [buffer2],r9 ;start the regular code. ignore spilling buffer3,startposition and length |
|||
![]() |
|
revolution 27 May 2014, 03:47
Only the first four parameters are left off the stack image of the incoming values. All other parameters are put on the stack in the usual way.
It is kind of a weird calling method IMO as is encourages a lot of "mov [rsp+...],value" instructions (as opposed to "push value") which tends to inflate code size and reduce the efficiency of the code caches. I would hope that whoever designed this fastcall method did some benchmarks to justify the choices. I would hate to think that it was just simply decided without any figures to back it up. Also the 0 mod 16 thing kind of forces the use of RBP as a stack pointer in many cases and certainly leads to many silly bugs when one forgets about the alignment restrictions. |
|||
![]() |
|
einar 27 May 2014, 05:10
Quote:
Reason why it's made this way is because RSP must be always aligned to 16 byte boundry. Whenever you use PUSH you may break this alignment and this sometimes will cause crash. This forces you to tracing state of RSP in your code. So it's safer to use MOV instead. Quote:
I heard that keeping RSP alingned gives significant acceleration of the peformance. But i'm not an expert. So I'll gladly hear what others know about it. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.