Page 1 of 1
C Backend : (ASM level) volatile registers
Posted: Fri Jun 25, 2021 5:56 pm
by Olli
Hello,
on C backend, on ASM level, are the volatile registers the same as X64 backend ?
Thank you
Re: C Backend : (ASM level) volatile registers
Posted: Sun Jun 27, 2021 12:49 pm
by juergenkulow
Hello Olli,
Code: Select all
; Compare Backend_C and Backend_ASM exe-Code with x64dbg
Procedure Limit_(n)
If n<0
ProcedureReturn 0
ElseIf n>255
ProcedureReturn 255
Else
ProcedureReturn n
EndIf
EndProcedure
MessageRequester(Str(Limit_(254)),Str(Limit_(256))+" "+Hex(@Limit_()))
; Result with #PB_Backend_C and /OPTIMIZER:
; 000000013F701000 | B8 FF000000 | mov eax,FF |
; 000000013F701005 | BA 00000000 | mov edx,0 |
; 000000013F70100A | 48:81F9 FF000000 | cmp rcx,FF |
; 000000013F701011 | 48:0F4EC1 | cmovle rax,rcx |
; 000000013F701015 | 48:85C0 | test rax,rax |
; 000000013F701018 | 48:0F48C2 | cmovs rax,rdx | rdx:EntryPoint
; 000000013F70101C | C3 | ret |
; Result with #PB_Backend_ASM
; 000000014000117D | 48:894C24 08 | mov qword ptr ss:[rsp+8],rcx |
; 0000000140001182 | 41:57 | push r15 |
; 0000000140001184 | 48:31C0 | XOr rax,rax |
; 0000000140001187 | 50 | push rax |
; 0000000140001188 | 48:83EC 28 | sub rsp,28 |
; 000000014000118C | 4C:8B7C24 40 | mov r15,qword ptr ss:[rsp+40] |
; 0000000140001191 | 4D:21FF | And r15,r15 |
; 0000000140001194 | 7D 07 | jge limit_asm.14000119D |
; 0000000140001196 | 48:31C0 | XOr rax,rax |
; 0000000140001199 | EB 25 | jmp limit_asm.1400011C0 |
; 000000014000119B | EB 20 | jmp limit_asm.1400011BD |
; 000000014000119D | 4C:8B7C24 40 | mov r15,qword ptr ss:[rsp+40] |
; 00000001400011A2 | 49:81FF FF000000 | cmp r15,FF |
; 00000001400011A9 | 7E 0B | jle limit_asm.1400011B6 |
; 00000001400011AB | 48:C7C0 FF000000 | mov rax,FF |
; 00000001400011B2 | EB 0C | jmp limit_asm.1400011C0 |
; 00000001400011B4 | EB 07 | jmp limit_asm.1400011BD |
; 00000001400011B6 | 48:8B4424 40 | mov rax,qword ptr ss:[rsp+40] |
; 00000001400011BB | EB 03 | jmp limit_asm.1400011C0 |
; 00000001400011BD | 48:31C0 | XOr rax,rax |
; 00000001400011C0 | 48:83C4 30 | add rsp,30 |
; 00000001400011C4 | 41:5F | pop r15 |
; 00000001400011C6 | C3 | ret |
Re: C Backend : (ASM level) volatile registers
Posted: Sun Jun 27, 2021 1:34 pm
by STARGÅTE
@juergenkulow: How does your code answer the question?
The question is:
In the current ASM backend, rax, rcx, rdx, r8, r9, xmm0, xmm1, xmm2 and xmm3 are volatile.
Is that still the case within the C backend?
I think this is a platform regulation:
https://docs.microsoft.com/en-us/cpp/bu ... ster-usage
It is independent from the compiler backend, but from the output platform.
Re: C Backend : (ASM level) volatile registers
Posted: Tue Jun 29, 2021 1:42 am
by Olli
It's ever interesting to compare ASM source codes : it seems that C backend has a right use of the CPU. It should not lie between X64 and ARM64 performancies in the future.
I find some rules from
Intel document. (
Source)
For the Microsoft* x64 calling convention, the additional register space let fastcall be the only calling convention (under x86 there were many: stdcall, thiscall, fastcall, cdecl, etc.). The rules for interfacing with C/C++ style functions:
- RCX, RDX, R8, R9 are used for integer and pointer arguments in that order left to right.
- XMM0, 1, 2, and 3 are used for floating point arguments.
- Additional arguments are pushed on the stack left to right.
- Parameters less than 64 bits long are not zero extended; the high bits contain garbage.
- It is the caller's responsibility to allocate 32 bytes of "shadow space" (for storing RCX, RDX, R8, and R9 if needed) before calling the function.
- It is the caller's responsibility to clean the stack after the call.
- Integer return values (similar to x86) are returned in RAX if 64 bits or less.
- Floating point return values are returned in XMM0.
- Larger return values (structs) have space allocated on the stack by the caller, and RCX then contains a pointer to the return space when the callee is called. Register usage for integer parameters is then pushed one to the right. RAX returns this address to the caller.
- The stack is 16-byte aligned. The "call" instruction pushes an 8-byte return value, so the all non-leaf functions must adjust the stack by a value of the form 16n+8 when allocating stack space.
- Registers RAX, RCX, RDX, R8, R9, R10, and R11 are considered volatile and must be considered destroyed on function calls.
- RBX, RBP, RDI, RSI, R12, R14, R14, and R15 must be saved in any function using them.
- Note there is no calling convention for the floating point (and thus MMX) registers.
- Further details (varargs, exception handling, stack unwinding) are at Microsoft's site.
Re: C Backend : (ASM level) volatile registers
Posted: Wed Jun 30, 2021 12:21 pm
by Olli
Let's note that the
syscall requires a different set of non-volatile registers.
Source.
On Linux, syscall arguments set is :
Code: Select all
1st arg : rdi
2nd arg : rsi
3th arg : rdx
4th arg : r10
5th arg : r8
6th arg : r9
What it differs to deduce volatile registers, in this way.
The second calling convention (for Linux/Mac) seems described as below. What it lets think that there is no really volatile registers everytime.
Source.
The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, R9 (R10 is used as a static chain pointer in case of nested functions), while XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 and XMM7 are used for the first floating point arguments. As in the Microsoft x64 calling convention, additional arguments are passed on the stack. Integer return values up to 64 bits in size are stored in RAX while values up to 128 bit are stored in RAX and RDX. Floating-point return values are similarly stored in XMM0 and XMM1. The wider YMM and ZMM registers are used for passing and returning wider values in place of XMM when they exist.
If the callee wishes to use registers RBX, RSP, RBP, and R12–R15, it must restore their original values before returning control to the caller. All other registers must be saved by the caller if it wishes to preserve their values.
For leaf-node functions (functions which do not call any other function(s)), a 128-byte space is stored just beneath the stack pointer of the function. The space is called the red zone. This zone will not be clobbered by any signal or interrupt handlers. Compilers can thus utilize this zone to save local variables. Compilers may omit some instructions at the starting of the function (adjustment of RSP, RBP) by utilizing this zone. However, other functions may clobber this zone. Therefore, this zone should only be used for leaf-node functions. gcc and clang offer the -mno-red-zone flag to disable red-zone optimizations.
If the callee is a variadic function, then the number of floating point arguments passed to the function in vector registers must be provided by the caller in the AL register.
Unlike the Microsoft calling convention, a shadow space is not provided; on function entry, the return address is adjacent to the seventh integer argument on the stack.
Re: C Backend : (ASM level) volatile registers
Posted: Wed Jun 30, 2021 10:56 pm
by juergenkulow
Registers in AArch64 state
A64 instructions
Hello Olli,
how can my programs take full advantage of the power of the ARM A64 chip family(e.g. Apple M1)?
Re: C Backend : (ASM level) volatile registers
Posted: Fri Jul 02, 2021 3:57 pm
by Olli
Good question ! Maybe through
this, and by checking this is executable from pureBasic in
an example of sq4.
Re: C Backend : (ASM level) volatile registers
Posted: Fri Jul 02, 2021 8:02 pm
by Olli
@Juergenkulow
Note that you can execute 14 teraflops, while I can execute 0.23 teraflops...
Further from pureBasic, I can see "NEON" too. But it seems the version 64 is not free...
To go back to subject (

), I think it is recommanded to save and restore all the registers in a professionnal program/library, when an ASM optimization is added.