flat assembler
Message board for the users of flat assembler.

Index > Main > How to pass parameters? How to preserve registers?

Author
Thread Post new topic Reply to topic
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 27 Jun 2017, 20:38
Returning back to FASM, I'm failing to see how to call my procedures. I can't use invoke and call doesn't support parameters, so how do I pass arguments to my procedures? I thought that you define a procedure with proc or just a label with manual stack frame and then call it with invoke, but that obviously isn't the case.

The second question concerns register preservation. How exactly are these registers supposed to be preserved? In the code below, rbx was modified while printf was executing. This doesn't matter as long as the scope of the function restores rbx upon exit, right? There's nothing that printf could rely upon in rbx, right?

Let's say I have:

Code:
main:
  sub rsp, 8
  
  push rbx
  xor rbx, rbx
  cinvoke printf, <"Something", 13, 10>
  pop rbx

  invoke ExitProcess, 0
    


Sorry for the probably basic questions. Learning assembly after I programmed in it 5 years ago makes it really hard to consolidate all that I remember and what I forgot or only think I remember correctly. It's really confusing.
Post 27 Jun 2017, 20:38
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 19869
Location: In your JS exploiting you and your system
revolution 28 Jun 2017, 01:54
It looks like you are writing Windows 64-bit code and using the C library functions. So what you need to know about is the calling conventions used. They tell you which registers need to be preserved and how the parameters are passed.

For Windows 64-bit the calling convention is fastcall
Post 28 Jun 2017, 01:54
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2340
Furs 28 Jun 2017, 10:39
fastcall is a 32-bit calling convention, even the wiki article you linked says it, why do people insist on calling the 64-bit one this way is beyond me. Just to confuse newbies I guess since they're totally different calling conventions. If MS64 ABI call convention is fastcall then what's the name for Linux's? "fastercall"?

BTW you don't have to save rbx, rbx is a saved register in the function (i.e. printf saves it). That's what "preserved" or "callee saved" register means. So you can guarantee their value between function calls won't change.

"Volatile" registers as Microsoft calls them, are those which will get trashed/clobbered by the function call with such calling convention. This means you cannot rely on their values, unless they are returned by the function (typically rax/eax).
Post 28 Jun 2017, 10:39
View user's profile Send private message Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 28 Jun 2017, 19:53
Ok, could I please ask any of you to write a simple function that just passes its first parameter to printf and returns. How do you call this function?

I was hoping I could do:

Code:
main:
  sub                   rsp, 8

  invoke               myOwnPrintf, "Some text"

  invoke               ExitProcess, 0

myOwnPrintf:
  push                 rbp
  mov                  rbp, rsp
  sub                   rsp, 8

  cinvoke             printf, "%s", rcx   

  pop                   rbp
  ret
  
    


But I cannot use invoke on it. Is the stack frame correct? I had a hard time getting a straight answer.

The windows calling convention says that there's at least 32bytes reserved on the stack on every call before the return address, so it's the callers responsibility. That's where I though the invoke macro or something similar is used.

Can someone help me with specific answers? I'm just having a hard time finding the right path right now.


Last edited by Inagawa on 29 Jun 2017, 09:12; edited 1 time in total
Post 28 Jun 2017, 19:53
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 19869
Location: In your JS exploiting you and your system
revolution 28 Jun 2017, 23:54
If you define "myOwnPrintf" with proc and endp then the stack is setup correctly. The way you have it there is not correct. You shouldn't have the extra 'sub rsp, 8' because the 'push rbp' already does this for you. Alternatively you don't need a stack frame so you can leave out all the instructions using rbp and only use the 'sub rsp, 8'.
Post 28 Jun 2017, 23:54
View user's profile Send private message Visit poster's website Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 29 Jun 2017, 00:39
But I don't want to use the proc macros exactly because they obfuscate something that I obviously don't undestand.

Thanks for the 'sub rsp, 8' mention, I totally missed that I was actually misaligning the stack.

How would you call the above function? Can you show me how exactly such a function is invoked in the same convenient fashion that Windows functions have? I.e. 'invoke myFunction, "something"' instead of having to manually put the parameters in the registers. Is there such a macro?
Post 29 Jun 2017, 00:39
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 19869
Location: In your JS exploiting you and your system
revolution 29 Jun 2017, 01:31
For the Win64 macros the call is the same. fastcall and invoke are the same macro. What you have there already should work fine.

The problem you have when you call printf there is that fasm uses left-to-right argument order for the register elements. So rcx is overwritten first and then the next parameter uses the new value of rcx, so your input value of rcx is lost. You can fix this:
Code:
mov rdx,rcx
cinvoke printf, "%s", rdx    
Post 29 Jun 2017, 01:31
View user's profile Send private message Visit poster's website Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 29 Jun 2017, 08:54
Well "invoke" doesn't work on these simple 'label' procedures, only call. But call doesn't pass parameters. So what macro do you use to call procedures that you defined?

Because the above in my post doesn't compile.
Post 29 Jun 2017, 08:54
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 19869
Location: In your JS exploiting you and your system
revolution 29 Jun 2017, 09:40
Inagawa wrote:
Well "invoke" doesn't work on these simple 'label' procedures ...
Oh yeah, You probably want ccall or fastcall.
Post 29 Jun 2017, 09:40
View user's profile Send private message Visit poster's website Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 29 Jun 2017, 10:03
Thank you!
Post 29 Jun 2017, 10:03
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8263
Location: Kraków, Poland
Tomasz Grysztar 29 Jun 2017, 14:23
Furs wrote:
fastcall is a 32-bit calling convention, even the wiki article you linked says it, why do people insist on calling the 64-bit one this way is beyond me. Just to confuse newbies I guess since they're totally different calling conventions. If MS64 ABI call convention is fastcall then what's the name for Linux's? "fastercall"?
It was called this way by Microsoft (well, it called it __fastcall, to be exact). The wiki may not always contain a complete view of naming conventions used by different parties, especially when one writing the article was inclined to treat only select ones as "correct".
Post 29 Jun 2017, 14:23
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2340
Furs 29 Jun 2017, 15:31
But that's wrong, did you even click the link on Microsoft's site linked?

Links to: https://docs.microsoft.com/en-us/cpp/cpp/fastcall

^ describes the 32-bit fastcall, in particular that the called function cleans the stack, which is not the case for x64 calling convention, even if we ignore that they forgot to mention the x64 registers...
Post 29 Jun 2017, 15:31
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8263
Location: Kraków, Poland
Tomasz Grysztar 29 Jun 2017, 15:44
Furs wrote:
But that's wrong, did you even click the link on Microsoft's site linked?
Since that link leads to a description of 32-bit fastcall, it has little relevance here. This name was applied to many different conventions, originally 16-bit ones, so it is better to look at it as a family of conventions that share some common characteristics.
What was relevant in my link was the passage that shows that even Microsoft has been using this name (even if inconsistently) with respect to 64-bit world:
Microsoft wrote:
Given the expanded register set, x64 uses the __fastcall calling convention and a RISC-based exception-handling model. The __fastcall convention uses registers for the first four arguments and the stack frame to pass additional arguments.
This naming was so prevalent at the time when 64-bit support was implemented into fasm, that fasm's macro was also called this way and it was accepted and understood norm at the time.
Post 29 Jun 2017, 15:44
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2340
Furs 29 Jun 2017, 19:54
I still think it's confusing as heck, especially since even MS state that it is ignored on x64 (the keyword), so it seems someone got it wrong there for sure when it was "prevalent".

FWIW, GCC's sources never refer to it as fastcall, there's only one fastcall there and it's the 32-bit one only (well I've patched it to add custom calling convention support via a plugin, so I had to dig deep).
Post 29 Jun 2017, 19:54
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.