flat assembler
Message board for the users of flat assembler.
 Home   FAQ   Search   Register 
 Profile   Log in to check your private messages   Log in 
flat assembler > Main > How to pass parameters? How to preserve registers?

Author
Thread Post new topic Reply to topic
Inagawa



Joined: 24 Mar 2012
Posts: 153
How to pass parameters? How to preserve registers?
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 rsp8
  
  push rbx
  xor rbxrbx
  cinvoke printf, <"Something"1310>
  pop rbx

  invoke ExitProcess0




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: 15152
Location: GW170817
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: 814
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
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                   rsp8

  invoke               myOwnPrintf"Some text"

  invoke               ExitProcess0

myOwnPrintf:
  push                 rbp
  mov                  rbprsp
  sub                   rsp8

  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: 15152
Location: GW170817
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
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: 15152
Location: GW170817
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
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: 15152
Location: GW170817

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
Thank you!
Post 29 Jun 2017, 10:03
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6585
Location: Kraków, Poland

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: 814
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
Assembly Artist


Joined: 16 Jun 2003
Posts: 6585
Location: Kraków, Poland

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: 814
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


Powered by phpBB © 2001-2005 phpBB Group.

Main index   Download   Documentation   Examples   Message board
Copyright © 2004-2016, Tomasz Grysztar.