Hi all!
Translating from 32 bits to 64 bits a big problem is that ecx and/or edx can be arguments in other order than x64 ABI allow. And that complicate everything.
Fortunatelly this little macro remove all the problem:@reg32_64 macro reg_32, reg_64
if @WordSize eq 4
@CatStr(<_>,®_32) textequ <reg_32>
@CatStr(<__>,®_32) textequ <reg_32>
else
@CatStr(<_>,®_32) textequ <reg_64>
@CatStr(<__>,®_32) textequ <@CatStr(®_64,<d>)>
endif
endm
And in your code:@reg32_64 ecx, r10
@reg32_64 edx, r11
This generate wildcard registers _ecx and _edx that became DWORD ecx and edx in 32 bits, and QWORD r10 an r11 in 64 bits.
Because some x64 graphical API still requiere DWORD, also are generated wildcard registers __ecx and __edx that always became DWORD, ecx and edx in 32 bits, and r10d an r11d in 64 bits.
Then you don't need to create solutions for dual code:Method ComboBox.Init, uses xbx xsi, pOwner:POINTER, hParent:HWND, pDefStruc:PDEF_COMBOBOX
SetObject xsi
mov xbx, pDefStruc
assume xbx:PDEF_COMBOBOX
mov eax, [xbx].dStyle
or eax, WS_CHILD or WS_VISIBLE
invoke CreateWindowEx, [xbx].dExStyle, $OfsCStr("ComboBox"), [xbx].pTitle, eax, \
[xbx].sdPosX, [xbx].sdPosY, [xbx].dWidth, [xbx].dHeight, \
hParent, [xbx].xCtlID, hInstance, 0
assume xbx:NOTHING
ACall xsi.Init, pOwner, xax
Subclass ComboBox ;Uses xsi
MethodEnd
Instead you just use almost the pure 32 bits code:Method ComboBox.Init, uses xsi, pOwner:POINTER, hParent:HWND, pDefStruc:PDEF_COMBOBOX
SetObject xsi
mov _ecx, pDefStruc
assume _ecx:PDEF_COMBOBOX
mov eax, [_ecx].dStyle
or eax, WS_CHILD or WS_VISIBLE
invoke CreateWindowEx, [_ecx].dExStyle, $OfsCStr("ComboBox"), [_ecx].pTitle, eax, \
[_ecx].sdPosX, [_ecx].sdPosY, [_ecx].dWidth, [_ecx].dHeight, \
hParent, [_ecx].xCtlID, hInstance, 0
assume _ecx:NOTHING
ACall xsi.Init, pOwner, xax
Subclass ComboBox ;Uses xsi
MethodEnd
Indeed, in 32 bits, is exactly the original code.
Naturally this is not limited to OOP, this work in plain assembly.
Regards, HSE
Hi HSE
It is a very good idea :thumbsup:
Perhaps we can elaborate on this concept a bit further by creating aliases for the GP registers in a more general way.
I've also taken some steps in this direction by creating some macros to switch between registers and local or arguments (LocReg, ArgReg, etc.).
Turns out I don't use them that often. Only in situations where I needed heavy optimization.
Biterider
deleted
Quote from: Biterider on January 20, 2022, 08:29:02 AM
Perhaps we can elaborate on this concept a bit further by creating aliases for the GP registers in a more general way.
Of course you see a bigger picture than I do, and collisions must be avoided. But I hit first, ugly wildcard names are yours :biggrin: :biggrin: :biggrin:
Quote from: Biterider on January 20, 2022, 08:29:02 AM
Only in situations where I needed heavy optimization.
This is not exactly same priority. With pseudo push/pop and this little macro,
32 bits code become 64 bits code. Perhaps You don't even need to know 64 bits programming so much. Optimization is a further step, that involve SIMD, AVX, amount of timings and is a lot more complex. I need precision, not efficiency. Under this terms optimization usually is not so easy :thumbsup:
Quote from: nidud on January 20, 2022, 09:24:52 AM
A simple method for this is to use 64-bit registers.
Thanks for effort nidud :thumbsup:. But you are missing the most important part,
that is not my 32 bit code.
:biggrin: Example is a little elemental but is my real 32 bits code that now is working in 64 bits. 8000 SLOC in minutes (a lot of minutes obviously :biggrin: :biggrin: :biggrin:). [not in the count thousands of SLOC maked dual by Biterider]
A note aside, this is the code that work with AsmC but don't work with AsmC64 :undecided: