News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

I thnk I have the function calls reliable at last.

Started by hutch--, July 31, 2016, 09:41:17 PM

Previous topic - Next topic

hutch--

I was starting to find limitations in Vasily's prologue and epilogue so I wrote a new pair. This is the bare procedure it produces. I prefer 2 instruction to the old "ENTER" mnemonic as it is known to be slow. I have currently overdone it with the 256 bytes of local stack space and this will need to be trimmed back if thing like recursive procedures are used but it all seems to be working OK at the moment.

----------------
bare stack frame
----------------
sub_1400010c0   proc
.text:00000001400010c0 55                         push rbp
.text:00000001400010c1 488BEC                     mov rbp, rsp
.text:00000001400010c4 4881EC00010000             sub rsp, 0x100
.text:00000001400010cb 488BC0                     mov rax, rax
.text:00000001400010ce C9                         leave
.text:00000001400010cf C3                         ret
sub_1400010c0   endp

The "invoke" in Vasily's macro system had limitations on the number of arguments it could handle and when disassembled it was doing unusually complicated things with register sizes so I wrote 2 macros, "apicall" and "stdcall" and both will handle a large number of arguments. With the apicall macro if there are less than 5 arguments they are passed directly to the 4 registers.

As neither use "invoke" I have not written support for ADDR as I have an alternative technique where you use a leading "&" character so instead of "ADDR variable" you use "&variable". Less typing.  :biggrin:

Now interestingly enough ML64 still supports normal STDCALL with the arg list for the proc so you can use the STDCALL for internal code without having to p*ss around with loading registers. Exceptions will be things like a WndProc and callbacks that are called by the system and will need to conform to the x64 ABI.

---------------
SYSTEM FASTCALL
---------------
  apicall CreateFont,16,8,0,0,600,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS, \
          CLIP_DEFAULT_PRECIS,PROOF_QUALITY,FF_DONTCARE,"fixedsys"

.text:000000014000100b FF3518200000               push qword ptr [0x140003029]
.text:0000000140001011 6A00                       push 0
.text:0000000140001013 6A02                       push 2
.text:0000000140001015 6A00                       push 0
.text:0000000140001017 6A00                       push 0
.text:0000000140001019 6A01                       push 1
.text:000000014000101b 6A00                       push 0
.text:000000014000101d 6A00                       push 0
.text:000000014000101f 6858020000                 push 0x258
.text:0000000140001024 48C7C110000000             mov rcx, 0x10
.text:000000014000102b 48C7C208000000             mov rdx, 8
.text:0000000140001032 49C7C000000000             mov r8, 0x0
.text:0000000140001039 49C7C100000000             mov r9, 0x0
.text:0000000140001040 4883EC20                   sub rsp, 0x20
.text:0000000140001044 FF15B60F0000               call qword ptr [CreateFontA]
.text:000000014000104a 4883C468                   add rsp, 0x68

-------
STDCALL
-------
  stdcall testme2,1,2,3,4,5,6,7,"That's all Folks"

.text:0000000140001040 FF350B200000               push qword ptr [0x140003051]
.text:0000000140001046 6A07                       push 7
.text:0000000140001048 6A06                       push 6
.text:000000014000104a 6A05                       push 5
.text:000000014000104c 6A04                       push 4
.text:000000014000104e 6A03                       push 3
.text:0000000140001050 6A02                       push 2
.text:0000000140001052 6A01                       push 1
.text:0000000140001054 E8D7010000                 call sub_140001230
.text:0000000140001059 4883C440                   add rsp, 0x40

testme2 proc a1:QWORD,a2:QWORD,a3:QWORD,a4:QWORD,a5:QWORD,a6:QWORD,a7:QWORD,a8:QWORD

Mikl__

Hi, hutch--!
theoretically apicall CreateFont,16,8,0,0,600,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS, \
          CLIP_DEFAULT_PRECIS,PROOF_QUALITY,FF_DONTCARE,"fixedsys"
It should look like
mov ecx,0x10
mov edx,8
xor r8,r8
xor r9,r9
lea rax,[0x140003029]
push rax
push r8
push 2
push r8
push r8
push 1
push r8
push r8
push 0x258
sub rsp, 0x20
call qword ptr [CreateFontA]

jj2007

#2
jinvoke CreateFont,16,8,0,0,600,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,PROOF_QUALITY,FF_DONTCARE, Chr$("fixedsys"), 0

Note the extra 0 at the end - my macro complained that there are not enough parameters, so I arbitrarily added a 0
No idea how reliable jinvoke is, though, so please count yourself *) ::)

Under the hood:
53                                | push rbx                           |
53                                | push rbx                           |
6A 00                             | push 0                             |
4C 8D 15 48 0F 00 00              | lea r10, qword ptr ds:[140002075]  | 140002075:"fixedsys"
41 52                             | push r10                           |
6A 00                             | push 0                             |
6A 02                             | push 2                             |
6A 00                             | push 0                             |
6A 00                             | push 0                             |
6A 01                             | push 1                             |
6A 00                             | push 0                             |
6A 00                             | push 0                             |
68 58 02 00 00                    | push 258                           |
6A 00                             | push 0                             |
4C 8B 0C 24                       | mov r9, qword ptr ss:[rsp]         |
6A 00                             | push 0                             |
4C 8B 04 24                       | mov r8, qword ptr ss:[rsp]         |
6A 08                             | push 8                             |
48 8B 14 24                       | mov rdx, qword ptr ss:[rsp]        |
6A 10                             | push 10                            |
48 8B 0C 24                       | mov rcx, qword ptr ss:[rsp]        |
FF 15 80 12 00 00                 | call qword ptr ds:[<&CreateFontA>] |
48 81 C4 80 00 00 00              | add rsp, 80                        |
90                                | nop                                |


Project is attached.

@Mikl: the xor r8, r8 -> push r8 doesn't save bytes, as push r8 is a two-byte instruction, same as push 0
maybe the stack needs to be adjusted after the call;

@Hutch: I'm not sure if it's properly aligned on entry to CreateFont:
0000000140001193  | 48 83 EC 20                       | sub rsp, 20                        | ???
0000000140001197  | CC                                | int3                               | stack is 12FE98
0000000140001198  | FF 15 72 12 00 00                 | call qword ptr ds:[<&CreateFontA>] |

...
000007FEFDCD9A38  | 48 83 EC 78                       | sub rsp, 78                        | CreateFontA
000007FEFDCD9A3C  | 48 8B 05 25 26 05 00              | mov rax, qword ptr ds:[7FEFDD2C068 | stack is 12FE18 now
000007FEFDCD9A43  | 48 33 C4                          | xor rax, rsp                       | rax:"fixedsys"


*) P.S.: Perhaps it's better to move the trailing zero before the DEFAULT_CHARSET :icon_mrgreen:

jj2007

Quote from: hutch-- on July 31, 2016, 09:41:17 PM
.text:000000014000100b FF3518200000               push qword ptr [0x140003029]

Hutch,

How did you achieve this encoding? There is an older thread discussing push offset in x64, but I couldn't see an example how to push directly the address of a string. My assemblers choke on push offset :(

hutch--

Its a pointer to a .data section address.

.data
  itm db "test here",0
  pitem dq itm
.code

jj2007

Of course - sorry, that was a stupid question ::)

It's not very size-efficient though; the lea rax/push rax combi is 6 bytes shorter.

hutch--

The downside of the new prologue and epilogue combined with the new calling procedures is they only work on QWORD sized arguments which is fine with the API functions but does not automatically handle structures in sizes other than QWORD members. Tested with MoveWindow().  :(

jj2007

Quote from: hutch-- on August 02, 2016, 09:10:50 PM
The downside of the new prologue and epilogue combined with the new calling procedures is they only work on QWORD sized arguments which is fine with the API functions but does not automatically handle structures in sizes other than QWORD members. Tested with MoveWindow().  :(

So far no problems here: MoveWindow works fine, stack is balanced and aligned...

\Masm32\MasmBasic\Res\SkelDualGUI.asc, lines 122ff:
int 3
movzx eax, word ptr lParam ; width of client area
movzx edx, word ptr lParam+2 ; height
sub eax, 17 ; these 32-bit instructions sign-extend the upper 32 bits
sub edx, 37 ; of the 64-bit registers and are one byte shorter
jinvoke MoveWindow, hEdit, 7, 30, rax, rdx, 1
jmp defwp


compiler style off:
0000000140001523  | 0F B7 45 28                       | movzx eax, word ptr ss:[rbp+28]  |
0000000140001527  | 0F B7 55 2A                       | movzx edx, word ptr ss:[rbp+2A]  |
000000014000152B  | 83 E8 11                          | sub eax, 11                      |
000000014000152E  | 83 EA 25                          | sub edx, 25                      |
0000000140001531  | 53                                | push rbx                         |
0000000140001532  | 53                                | push rbx                         |
0000000140001533  | 6A 01                             | push 1                           |
0000000140001535  | 4C 8B D2                          | mov r10, rdx                     |
0000000140001538  | 41 52                             | push r10                         |
000000014000153A  | 4C 8B C8                          | mov r9, rax                      |
000000014000153D  | 41 51                             | push r9                          |
000000014000153F  | 6A 1E                             | push 1E                          |
0000000140001541  | 4C 8B 04 24                       | mov r8, qword ptr ss:[rsp]       |
0000000140001545  | 6A 07                             | push 7                           |
0000000140001547  | 48 8B 14 24                       | mov rdx, qword ptr ss:[rsp]      |
000000014000154B  | 48 8B 0D 26 0E 00 00              | mov rcx, qword ptr ds:[140002378 |
0000000140001552  | 51                                | push rcx                         |
0000000140001553  | FF 15 AF 11 00 00                 | call qword ptr ds:[<&MoveWindow> |
0000000140001559  | 48 83 C4 40                       | add rsp, 40                      |


compiler style on:
0000000140001598  | 0F B7 45 28                       | movzx eax, word ptr ss:[rbp+28]  |
000000014000159C  | 0F B7 55 2A                       | movzx edx, word ptr ss:[rbp+2A]  |
00000001400015A0  | 83 E8 11                          | sub eax, 11                      |
00000001400015A3  | 83 EA 25                          | sub edx, 25                      |
00000001400015A6  | 41 BA 01 00 00 00                 | mov r10d, 1                      |
00000001400015AC  | 4C 89 54 24 28                    | mov qword ptr ss:[rsp+28], r10   |
00000001400015B1  | 4C 8B D2                          | mov r10, rdx                     |
00000001400015B4  | 4C 89 54 24 20                    | mov qword ptr ss:[rsp+20], r10   |
00000001400015B9  | 4C 8B C8                          | mov r9, rax                      |
00000001400015BC  | 4C 89 4C 24 18                    | mov qword ptr ss:[rsp+18], r9    |
00000001400015C1  | 41 B8 1E 00 00 00                 | mov r8d, 1E                      |
00000001400015C7  | 4C 89 44 24 10                    | mov qword ptr ss:[rsp+10], r8    |
00000001400015CC  | BA 07 00 00 00                    | mov edx, 7                       |
00000001400015D1  | 48 89 54 24 08                    | mov qword ptr ss:[rsp+8], rdx    |
00000001400015D6  | 48 8B 0D 9B 0D 00 00              | mov rcx, qword ptr ds:[140002378 |
00000001400015DD  | 48 89 0C 24                       | mov qword ptr ss:[rsp], rcx      |
00000001400015E1  | FF 15 21 11 00 00                 | call qword ptr ds:[<&MoveWindow> |
00000001400015E7  | EB 54                             | jmp skeldualgui64.14000163D      |