proc32.ash 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. ;--------=========xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=========--------
  2. ;
  3. ; Copyright (C) 1999 by Andrew Zabolotny
  4. ; Miscelaneous NASM macros that makes use of new preprocessor features
  5. ;
  6. ; This library is free software; you can redistribute it and/or
  7. ; modify it under the terms of the GNU Library General Public
  8. ; License as published by the Free Software Foundation; either
  9. ; version 2 of the License, or (at your option) any later version.
  10. ;
  11. ; This library is distributed in the hope that it will be useful,
  12. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ; Library General Public License for more details.
  15. ;
  16. ; You should have received a copy of the GNU Library General Public
  17. ; License along with this library; if not, write to the Free
  18. ; Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ;
  20. ;--------=========xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=========--------
  21. ; The macros in this file provides support for writing 32-bit C-callable
  22. ; NASM routines. For a short description of every macros see the
  23. ; corresponding comment before every one. Simple usage example:
  24. ;
  25. ; proc sin,1
  26. ; targ %$angle
  27. ; fld %$angle
  28. ; fsin
  29. ; endproc sin
  30. %ifndef __PROC32_ASH__
  31. %define __PROC32_ASH__
  32. [WARNING -macro-selfref]
  33. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  34. ; Summary:
  35. ; Mangle a name to be compatible with the C compiler
  36. ; Arguments:
  37. ; The name
  38. ; Example:
  39. ; cname (my_func)
  40. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  41. %ifdef EXTERNC_UNDERSCORE
  42. %define cname(x) _ %+ x
  43. %else
  44. %define cname(x) x
  45. %endif
  46. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  47. ; Summary:
  48. ; Import an external C procedure definition
  49. ; Arguments:
  50. ; The name of external C procedure
  51. ; Example:
  52. ; cextern printf
  53. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  54. %macro cextern 1
  55. %xdefine %1 cname(%1)
  56. %ifidni __OUTPUT_FORMAT__,obj
  57. extern %1:wrt FLAT
  58. %else
  59. extern %1
  60. %endif
  61. %endmacro
  62. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  63. ; Summary:
  64. ; Export an C procedure definition
  65. ; Arguments:
  66. ; The name of C procedure
  67. ; Example:
  68. ; cglobal my_printf
  69. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  70. %macro cglobal 1
  71. %xdefine %1 cname(%1)
  72. global %1
  73. %endmacro
  74. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  75. ; Summary:
  76. ; Misc macros to deal with PIC shared libraries
  77. ; Comment:
  78. ; Note that we have a different syntax for working with and without
  79. ; PIC shared libraries. In a PIC environment we should load first
  80. ; the address of the variable into a register and then work through
  81. ; that address, i.e: mov eax,myvar; mov [eax],1
  82. ; In a non-PIC environment we should directly write: mov myvar,1
  83. ; Example:
  84. ; extvar myvar
  85. ; GetGOT
  86. ; %ifdef PIC
  87. ; mov ebx,myvar ; get offset of myvar into ebx
  88. ; %else
  89. ; lea ebx,myvar
  90. ; %endif
  91. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  92. %ifdef PIC
  93. cextern _GLOBAL_OFFSET_TABLE_
  94. %macro GetGOT 0
  95. %ifdef .$proc.stkofs
  96. %assign .$proc.stkofs .$proc.stkofs+4
  97. %endif
  98. call %$Get_GOT
  99. %$Get_GOT:
  100. pop ebx
  101. add ebx,_GLOBAL_OFFSET_TABLE_ + $$ - %$Get_GOT wrt ..gotpc
  102. %endmacro
  103. %macro extvar 1
  104. cextern %1
  105. %xdefine %1 [ebx+%1 wrt ..got]
  106. %endmacro
  107. %else
  108. %define GetGOT
  109. %macro extvar 1
  110. cextern %1
  111. %endmacro
  112. %endif
  113. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  114. ; Summary:
  115. ; Begin a procedure definition
  116. ; For performance reasons we don't use stack frame pointer EBP,
  117. ; instead we're using the [esp+xx] addressing. Because of this
  118. ; you should be careful when you work with stack pointer.
  119. ; The push/pop instructions are macros that are defined to
  120. ; deal correctly with these issues.
  121. ; Arguments:
  122. ; First argument - the procedure name
  123. ; Second optional argument - the number of bytes for local variables
  124. ; The following arguments could specify the registers that should be
  125. ; pushed at beginning of procedure and popped before exiting
  126. ; Example:
  127. ; proc MyTestProc
  128. ; proc MyTestProc,4,ebx,esi,edi
  129. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  130. %macro proc 1-3+ 0
  131. cglobal %1
  132. %push %1
  133. align 16
  134. %1:
  135. %xdefine %$proc.name %1
  136. ; total size of local arguments
  137. %assign %$proc.locsize (%2+3) & 0xFFFC
  138. ; offset from esp to argument
  139. %assign %$proc.argofs 4+%$proc.locsize
  140. ; additional offset to args (tracks push/pops)
  141. %assign .$proc.stkofs 0
  142. ; offset from esp to local arguments
  143. %assign %$proc.locofs 0
  144. ; Now push the registers that we should save
  145. %define %$proc.save %3
  146. %if %$proc.locsize != 0
  147. sub esp,%$proc.locsize
  148. %endif
  149. push %$proc.save
  150. %endmacro
  151. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  152. ; Summary:
  153. ; Declare an argument passed on stack
  154. ; This macro defines two additional macros:
  155. ; first (with the name given by first argument) - [esp+xx]
  156. ; second (with a underscore appended to first argument) - esp+xx
  157. ; Arguments:
  158. ; First argument defines the procedure argument name
  159. ; Second optional parameter defines the size of the argument
  160. ; Default value is 4 (a double word)
  161. ; Example:
  162. ; arg .my_float
  163. ; arg .my_double,8
  164. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  165. %macro arg 1-2 4
  166. %ifndef %$proc.argofs
  167. %error "`arg' not in a proc context"
  168. %else
  169. ; Trick: temporary undefine .$proc.stkofs so that it won't be expanded
  170. %assign %%. .$proc.stkofs
  171. %undef .$proc.stkofs
  172. %xdefine %{1}_ esp+%$proc.argofs+.$proc.stkofs
  173. %xdefine %1 [esp+%$proc.argofs+.$proc.stkofs]
  174. %assign .$proc.stkofs %%.
  175. %assign %$proc.argofs %2+%$proc.argofs
  176. %endif
  177. %endmacro
  178. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  179. ; Summary:
  180. ; Declare an local variable
  181. ; first (with the name given by first argument) - [esp+xx]
  182. ; second (with a slash prefixing the first argument) - esp+xx
  183. ; Arguments:
  184. ; First argument defines the procedure argument name
  185. ; Second optional parameter defines the size of the argument
  186. ; Default value is 4 (a double word)
  187. ; Example:
  188. ; loc .int_value
  189. ; loc .double_value,8
  190. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  191. %macro loc 1-2 4
  192. %ifndef %$proc.locofs
  193. %error "`loc' not in a proc context"
  194. %elif %$proc.locofs + %2 > %$proc.locsize
  195. %error "local stack space exceeded"
  196. %else
  197. %assign %%. .$proc.stkofs
  198. %undef .$proc.stkofs
  199. %xdefine %{1}_ esp+%$proc.locofs+.$proc.stkofs
  200. %xdefine %1 [esp+%$proc.locofs+.$proc.stkofs]
  201. %assign .$proc.stkofs %%.
  202. %assign %$proc.locofs %$proc.locofs+%2
  203. %endif
  204. %endmacro
  205. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  206. ; Summary:
  207. ; Get the type of given size into context-local variable %$type
  208. ; Arguments:
  209. ; Size of type we want (1,2,4,8 or 10)
  210. ; Example:
  211. ; type 4 ; gives "dword"
  212. ; type 10 ; gives "tword"
  213. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  214. %macro type 1
  215. %if %1 = 1
  216. %define %$type byte
  217. %elif %1 = 2
  218. %define %$type word
  219. %elif %1 = 4
  220. %define %$type dword
  221. %elif %1 = 8
  222. %define %$type qword
  223. %elif %1 = 10
  224. %define %$type tword
  225. %else
  226. %define %$. %1
  227. %error "unknown type for argument size %$."
  228. %endif
  229. %endmacro
  230. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  231. ; Summary:
  232. ; Same as `arg' but prepends "word", "dword" etc (typed arg)
  233. ; first (with the name given by first argument) - dword [esp+xx]
  234. ; second (with a slash prefixing the first argument) - esp+xx
  235. ; Arguments:
  236. ; Same as for `arg'
  237. ; Example:
  238. ; targ .my_float ; .my_float is now "dword [esp+xxx]"
  239. ; targ .my_double,8 ; .my_double is now "qword [esp+xxx]"
  240. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  241. %macro targ 1-2 4
  242. %ifndef %$proc.argofs
  243. %error "`targ' not in a proc context"
  244. %else
  245. arg %1,%2
  246. type %2
  247. %assign %%. .$proc.stkofs
  248. %undef .$proc.stkofs
  249. %xdefine %1 %$type %1
  250. %assign .$proc.stkofs %%.
  251. %endif
  252. %endmacro
  253. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  254. ; Summary:
  255. ; Same as `loc' but prepends "word", "dword" etc (typed loc)
  256. ; first (with the name given by first argument) - dword [esp+xx]
  257. ; second (with a slash prefixing the first argument) - esp+xx
  258. ; Arguments:
  259. ; Same as for `loc'
  260. ; Example:
  261. ; tloc int_value
  262. ; tloc double_value,8
  263. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  264. %macro tloc 1-2 4
  265. %ifndef %$proc.locofs
  266. %error "`tloc' not in a proc context"
  267. %else
  268. loc %1,%2
  269. type %2
  270. %assign %%. .$proc.stkofs
  271. %undef .$proc.stkofs
  272. %xdefine %1 %$type %1
  273. %assign .$proc.stkofs %%.
  274. %endif
  275. %endmacro
  276. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  277. ; Summary:
  278. ; Finish a procedure
  279. ; Gives an error if proc/endproc pairs mismatch
  280. ; Defines an label called __end_(procedure name)
  281. ; which is useful for calculating function size
  282. ; Arguments:
  283. ; (optional) The name of procedure
  284. ; Example:
  285. ; endproc MyTestProc
  286. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  287. %push tmp ; trick: define a dummy context to avoid error in next line
  288. %macro endproc 0-1 %$proc.name
  289. %ifndef %$proc.argofs
  290. %error "`endproc' not in a proc context"
  291. %elifnidn %$proc.name,%1
  292. %define %$. %1
  293. %error "endproc names mismatch: expected `%$proc.name'"
  294. %error "but got `%$.' instead"
  295. %elif %$proc.locofs < %$proc.locsize
  296. %error "unused local space declared (used %$proc.locofs, requested %$proc.locsize)"
  297. %else
  298. %$exit:
  299. ; Now pop the registers that we should restore on exit
  300. pop %$proc.save
  301. %if %$proc.locsize != 0
  302. add esp,%$proc.locsize
  303. %endif
  304. ret
  305. __end_%1:
  306. %pop
  307. %endif
  308. %endmacro
  309. %pop
  310. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  311. ; Summary:
  312. ; A replacement for "push" for use within procedures
  313. ; Arguments:
  314. ; any number of registers which will be push'ed successively
  315. ; Example:
  316. ; push eax,ebx,ecx,edx
  317. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  318. %macro push 0-*
  319. ; dummy comment to avoid problems with "push" on the same line with a label
  320. %rep %0
  321. push %1
  322. %rotate 1
  323. %assign .$proc.stkofs .$proc.stkofs+4
  324. %endrep
  325. %endmacro
  326. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  327. ; Summary:
  328. ; A replacement for "pop" for use within procedures
  329. ; Arguments:
  330. ; any number of registers which will be pop'ed in reverse order
  331. ; Example:
  332. ; pop eax,ebx,ecx,edx
  333. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  334. %macro pop 0-*
  335. ; dummy comment to avoid problems with "pop" on the same line with a label
  336. %rep %0
  337. %rotate -1
  338. pop %1
  339. %assign .$proc.stkofs .$proc.stkofs-4
  340. %endrep
  341. %endmacro
  342. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  343. ; Summary:
  344. ; Replacements for "pushfd" and "popfd" that takes care of esp
  345. ; Example:
  346. ; pushfd
  347. ; popfd
  348. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  349. %macro pushfd 0
  350. pushfd
  351. %assign .$proc.stkofs .$proc.stkofs+4
  352. %endmacro
  353. %macro popfd 0
  354. popfd
  355. %assign .$proc.stkofs .$proc.stkofs-4
  356. %endmacro
  357. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  358. ; Summary:
  359. ; Exit from current procedure (optionally on given condition)
  360. ; Arguments:
  361. ; Either none or a condition code
  362. ; Example:
  363. ; exit
  364. ; exit nz
  365. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  366. %macro exit 0-1 mp
  367. j%1 near %$exit
  368. %endmacro
  369. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  370. ; Summary:
  371. ; start an conditional branch
  372. ; Arguments:
  373. ; A condition code
  374. ; second (optional) argument - "short" (by default - "near")
  375. ; Example:
  376. ; if nz
  377. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  378. %macro if 1-2 near
  379. ; dummy comment to avoid problems with "if" on the same line with a label
  380. %push if
  381. j%-1 %2 %$elseif
  382. %endmacro
  383. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  384. ; Summary:
  385. ; define the "else" branch of a conditional statement
  386. ; Arguments:
  387. ; optionaly: "short" if jmp to endif is less than 128 bytes away
  388. ; Example:
  389. ; else
  390. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  391. %macro else 0-1
  392. %ifnctx if
  393. %error "`else' without matching `if'"
  394. %else
  395. jmp %1 %$endif
  396. %$elseif:
  397. %define %$elseif_defined
  398. %endif
  399. %endmacro
  400. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  401. ; Summary:
  402. ; Finish am conditional statement
  403. ; Arguments:
  404. ; none
  405. ; Example:
  406. ; endif
  407. ;-----======xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx======-----
  408. %macro endif 0
  409. %ifnctx if
  410. %error "`endif' without matching `if'"
  411. %else
  412. %ifndef %$elseif_defined
  413. %$elseif:
  414. %endif
  415. %$endif:
  416. %pop
  417. %endif
  418. %endmacro
  419. %endif ; __PROC32_ASH__