uLib  User mode C/C++ extended API library for Win32 programmers.
3264_Template.asm
Go to the documentation of this file.
1 ;
2 ; Template for 32/64 bit dual mode assembly source files.
3 ; This file will contain both 32 and 64 bit versions of the functions.
4 ; Author: B.O. Love Nystrom.
5 ;
6 ; Public License: BSD - No usage restrictions.
7 ;
8 TITLE 32/64 bit assembly routines.
9 
10 IFDEF RAX
11  _WIN64 = 1
12 ELSE
13  _WIN64 = 0
14  .686P
15  .XMM
16  .MODEL FLAT
17 ENDIF
18 
19 ;==============================================================================
20 ; Common x86/x64 - Constants and parameterless functions
21 ;==============================================================================
22 
23 _TEXT SEGMENT
24 ; Your common code goes here..
25 _TEXT ENDS
26 
27 ;==============================================================================
28 IF (_WIN64 eq 0) ; 32 bit version
29 ;==============================================================================
30 ECHO === 32-BIT ASSEMBLY (ML) ===
31 
32 ; __cdecl
33 ; Argument passing: Right to left
34 ; Stack-maintenance: Calling function pops the stack
35 ; Name-decoration: Underscore character (_) is prefixed to names,
36 ; except when exporting __cdecl functions that use C linkage.
37 ;
38 ; __stdcall
39 ; Argument-passing: Right to left. By value, unless pointer or reference.
40 ; Stack-maintenance: Called function pops the stack.
41 ; Name-decoration: An underscore (_) is prefixed to the name. The name is
42 ; followed by the at sign (@) followed by the number of bytes (in decimal)
43 ; in the argument list. In other words, a function declared as
44 ; int func( int a, double b ); is decorated as: _func@12
45 ;
46 ; __fastcall
47 ; Argument-passing: The first two DWORD or smaller arguments are passed in
48 ; ECX and EDX registers; all other arguments are passed right to left.
49 ; Stack-maintenance: Called function pops the stack.
50 ; Name-decoration: At sign (@) is prefixed to names; an at sign followed by
51 ; the number of bytes (in decimal) in the parameter list is suffixed to names.
52 
53 _TEXT SEGMENT
54 
55 PUBLIC _foo_c
56 ;
57 ; UINT32 __cdecl foo_c( UINT32 bar );
58 ;
59 _foo_c PROC
60  enter 0,0
61  mov eax, [epb+8] ; first argument
62  add eax, eax
63  leave
64  ret ; Caller unstacks the args
65 _foo_c ENDP
66 
67 PUBLIC _foo_s@4
68 ;
69 ; UINT32 __stdcall foo_s( UINT32 bar );
70 ;
71 _foo_s@4 PROC
72  enter 0,0
73  mov eax, [epb+8] ; first argument
74  add eax, eax
75  leave
76  ret 4 ; Unstack the args
77 _foo_s@4 ENDP
78 
79 PUBLIC @foo_f@4
80 ;
81 ; UINT32 __fastcall foo_f( UINT32 bar );
82 ;
83 @foo_f@4 PROC
84  ;enter 0,0
85  mov eax, ecx ; first argument
86  add eax, eax
87  ;leave
88  ret ; For 3 or more args, unstack all except the first two
89 @foo_f@4 ENDP
90 
91 _TEXT ENDS
92 
93 ;==============================================================================
94 ELSE ; 64 bit version
95 ;==============================================================================
96 ECHO === 64-BIT ASSEMBLY (ML64) ===
97 
98 ; Extern C assembly routines does NOT get an added underscore with MSVC + ML64.
99 ; Hence the x64 assembly routines must be named _exactly_as_the_C_prototypes_,
100 ; or, in case of C++ class members, the mangled C++ identifiers.
101 ;
102 ; Fastcall is used regardless of prototype declaration!
103 ; Arguments -> RCX, RDX, R8, R9, then stack.
104 ;
105 ; The four register args are backed by unused stack cells.
106 ; Ergo, after std prologue the fifth argument is at [RBP+48].
107 ;
108 ; Normal fastcall stack cleanup convention (function pop args) is *not used*.
109 ; Functions end with 'ret 0' even if they had stack args.
110 ;
111 ; RAX, RCX, RDX, R8, R9, R10, R11 are considered volatile.
112 ; RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 are nonvolatile
113 ; and must be saved and restored by a function that use them.
114 ;
115 ; frame$ = 10h ; Offset from rbp to first shadow arg after 'enter 0,0'
116 ; x64 fastcall arguments:
117 ; rcx = arg1 (rbp+10h)
118 ; rdx = arg2 (rbp+18h)
119 ; r8 = arg3 (rbp+20h)
120 ; r9 = arg4 (rbp+28h)
121 ; [rbp+30h] = arg5
122 
123 _TEXT SEGMENT
124 
125 PUBLIC foo
126 ;
127 ; UINT64 foo( UINT64 bar );
128 ;
129 foo PROC
130  ;enter 0,0 ;<< not needed if <= 4 args
131  mov rax, rcx ; first argument
132  add rax, rax
133  ;leave ;>> not needed if <= 4 args
134  ret ; Caller balances the stack
135 foo ENDP
136 
137 _TEXT ENDS
138 
139 ENDIF ; _WIN64
140 END