NOTE: Probably should have mentioned everything is developed using assembly.
Maybe what I'm calling an ABI might be a little misleading. The volatility of any register would be dictated by the procedures intent. To clarify what I mean consider this example that could be thought of as STRLEN, but not necessarily looking for NULL.
Code:
mov rsi, WideTxt ; Points to a wide text buffer
mov eax, 0x1D2A ; Just a hypothetical terminating character
mov ecx, 1024 ; Maximum
call STRLEN
So in this case, RAX & RCX will be the only two registers modified and callee would be responsible for preserving anything else it needs to accomplish the task. Return values would be in their respective registers meaning RCX would be text buffer length. If RCX = 0 && EAX = Original value then string was the exact length as specified by caller, otherwise EAX = whatever character is a ESI + ECX. Now to accomplish something like STRCAT
Code:
mov rdi, DestBuff
rep movsw
So that is considerably more compact than;
Code:
mov ecx, 1024
mov rdx, WideTxt
mov r8, 0x1D2A
sub rsp, 32
call StrLen ; Then function would have move them again or at least R8 & RDX.
add rsp, 32
Obviously, at some point, I will need documentation, but that's the other objective I hope to address that when writing code what needs to be passed to callee be a little more intuitive based on target architecture.