prt0comn.asm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. ; common startup code for all the memory models
  2. %ifdef __TINY__
  3. %define __NEAR_CODE__
  4. %define __NEAR_DATA__
  5. %elifdef __SMALL__
  6. %define __NEAR_CODE__
  7. %define __NEAR_DATA__
  8. %elifdef __MEDIUM__
  9. %define __FAR_CODE__
  10. %define __NEAR_DATA__
  11. %elifdef __COMPACT__
  12. %define __NEAR_CODE__
  13. %define __FAR_DATA__
  14. %elifdef __LARGE__
  15. %define __FAR_CODE__
  16. %define __FAR_DATA__
  17. %elifdef __HUGE__
  18. %define __FAR_CODE__
  19. %define __FAR_DATA__
  20. %else
  21. %fatal "Memory model not defined."
  22. %endif
  23. %ifdef __FAR_CODE__
  24. extra_param_offset equ 2
  25. %else
  26. extra_param_offset equ 0
  27. %endif
  28. %ifdef __FAR_DATA__
  29. extra_data_offset equ 2
  30. %else
  31. extra_data_offset equ 0
  32. %endif
  33. cpu 8086
  34. segment text use16 class=code
  35. extern PASCALMAIN
  36. extern dos_psp
  37. extern dos_version
  38. extern __Test8086
  39. extern _edata ; defined by WLINK, indicates start of BSS
  40. extern _end ; defined by WLINK, indicates end of BSS
  41. extern __stklen
  42. extern __stktop
  43. extern __stkbottom
  44. extern __nearheap_start
  45. extern __nearheap_end
  46. extern ___heap
  47. %ifndef __TINY__
  48. %ifdef __FAR_DATA__
  49. extern ___stack
  50. %endif
  51. %ifdef __NEAR_DATA__
  52. extern ___stacktop
  53. %endif
  54. %endif
  55. extern __SaveInt00
  56. extern FPC_HANDLEERROR
  57. %ifdef __TINY__
  58. resb 0100h
  59. %endif
  60. ..start:
  61. %ifdef __TINY__
  62. mov bx, cs
  63. %else
  64. mov bx, dgroup
  65. %ifdef __NEAR_DATA__
  66. ; init the stack
  67. mov ss, bx
  68. mov sp, ___stacktop wrt dgroup
  69. %endif
  70. %endif
  71. ; zero fill the BSS section
  72. mov es, bx
  73. mov di, _edata wrt dgroup
  74. mov cx, _end wrt dgroup
  75. sub cx, di
  76. xor al, al
  77. cld
  78. rep stosb
  79. ; save the Program Segment Prefix
  80. push ds
  81. ; init DS
  82. mov ds, bx
  83. ; pop the PSP from stack and store it in the pascal variable dos_psp
  84. pop ax
  85. mov word [dos_psp], ax
  86. ; get DOS version and save it in the pascal variable dos_version
  87. mov ax, 3000h
  88. int 21h
  89. xchg al, ah
  90. mov word [dos_version], ax
  91. ; detect CPU
  92. xor bx, bx ; 0=8086/8088/80186/80188/NEC V20/NEC V30
  93. ; on pre-286 processors, bits 12..15 of the FLAGS registers are always set
  94. pushf
  95. pop ax
  96. and ah, 0fh
  97. push ax
  98. popf
  99. pushf
  100. pop ax
  101. and ah, 0f0h
  102. cmp ah, 0f0h
  103. je cpu_detect_done
  104. ; at this point we have a 286 or higher
  105. inc bx
  106. ; on a true 286 in real mode, bits 12..15 are always clear
  107. pushf
  108. pop ax
  109. or ah, 0f0h
  110. push ax
  111. popf
  112. pushf
  113. pop ax
  114. and ah, 0f0h
  115. jz cpu_detect_done
  116. ; we have a 386+
  117. inc bx
  118. cpu_detect_done:
  119. mov [__Test8086], bl
  120. %ifdef __NEAR_DATA__
  121. ; ****************************************************************************
  122. ; ** near data memory layout setup **
  123. ; ****************************************************************************
  124. ; allocate max heap
  125. ; TODO: also support user specified heap size
  126. ; try to resize our main DOS memory block until the end of the data segment
  127. mov cx, word [dos_psp]
  128. %ifdef __TINY__
  129. mov dx, cs
  130. %else
  131. mov dx, dgroup
  132. %endif
  133. sub dx, cx ; dx = (ds - psp) in paragraphs
  134. push dx ; save (ds - psp)
  135. add dx, 1000h ; 64kb in paragraphs
  136. ; get our MCB size in paragraphs
  137. dec cx
  138. mov es, cx
  139. mov bx, word [es:3]
  140. ; is it smaller than the maximum data segment size?
  141. cmp bx, dx
  142. jbe skip_mem_realloc
  143. mov bx, dx
  144. inc cx
  145. mov es, cx
  146. mov ah, 4Ah
  147. int 21h
  148. jc mem_realloc_err
  149. skip_mem_realloc:
  150. ; bx = the new size in paragraphs
  151. pop cx ; cx = (ds - psp)
  152. sub bx, cx
  153. mov cl, 4
  154. shl bx, cl
  155. sub bx, 2
  156. mov sp, bx
  157. mov word [__stktop], sp
  158. add bx, 2
  159. sub bx, word [__stklen]
  160. and bl, 0FEh
  161. mov word [__stkbottom], bx
  162. cmp bx, _end wrt dgroup
  163. jb not_enough_mem
  164. ; heap is between [ds:_end wrt dgroup] and [ds:__stkbottom - 1]
  165. mov word [__nearheap_start], _end wrt dgroup
  166. mov bx, word [__stkbottom]
  167. dec bx
  168. mov word [__nearheap_end], bx
  169. ; ****************************************************************************
  170. ; ** near data setup done **
  171. ; ****************************************************************************
  172. %endif
  173. %ifdef __FAR_DATA__
  174. mov word [__stktop], sp
  175. mov word [__stkbottom], 0
  176. mov ax, ss
  177. mov word [__stkbottom + 2], ax
  178. mov word [__stktop + 2], ax
  179. mov dx, sp
  180. add dx, 15
  181. mov cl, 4
  182. shr dx, cl
  183. add ax, dx
  184. mov word [__nearheap_start], 0
  185. mov word [__nearheap_end], 0FFF0h
  186. mov word [__nearheap_start + 2], ax
  187. mov word [__nearheap_end + 2], ax
  188. %endif
  189. %ifdef __FAR_CODE__
  190. jmp far PASCALMAIN
  191. %else
  192. jmp PASCALMAIN
  193. %endif
  194. not_enough_mem:
  195. mov dx, not_enough_mem_msg
  196. jmp error_msg
  197. mem_realloc_err:
  198. ; at this point there's still (ds-psp) pushed on the stack, but we won't
  199. ; bother popping it, because we exit to DOS with an error message here
  200. mov dx, mem_realloc_err_msg
  201. error_msg:
  202. mov ah, 9
  203. int 21h
  204. mov ax, 4CFFh
  205. int 21h
  206. FPC_INT00_HANDLER:
  207. sub sp, 4 ; reserve space on the stack for the retf
  208. push bx
  209. push cx
  210. push ds
  211. ; init ds
  212. %ifdef __TINY__
  213. mov bx, cs
  214. %else
  215. mov bx, dgroup
  216. %endif
  217. mov ds, bx
  218. ; check whether we're running on the same stack
  219. mov cx, ss
  220. cmp bx, cx
  221. jne .call_previous_handler
  222. %ifndef __FAR_CODE__
  223. ; check whether we're coming from the same code segment
  224. mov bx, sp
  225. mov cx, [bx + 3*2 + 6] ; get caller segment
  226. mov bx, cs
  227. cmp bx, cx
  228. jne .call_previous_handler
  229. %endif
  230. ; runerror 200
  231. mov bx, sp
  232. mov cx, [bx + 3*2 + 4] ; get caller offset
  233. %ifdef __FAR_CODE__
  234. mov dx, [bx + 3*2 + 6] ; get caller segment
  235. %endif
  236. add sp, 3*2 + 4 + 6
  237. xor ax, ax
  238. push ax
  239. mov ax, 200
  240. push ax
  241. %ifdef __FAR_CODE__
  242. push dx
  243. %endif
  244. push cx
  245. cld
  246. %ifdef __FAR_CODE__
  247. jmp far FPC_HANDLEERROR
  248. %else
  249. jmp FPC_HANDLEERROR
  250. %endif
  251. .call_previous_handler:
  252. mov bx, sp
  253. mov cx, [__SaveInt00]
  254. mov [ss:bx + 3*2], cx
  255. mov cx, [__SaveInt00+2]
  256. mov [ss:bx + 3*2 + 2], cx
  257. pop ds
  258. pop cx
  259. pop bx
  260. retf ; jumps to the previous handler with all registers and stack intact
  261. global FPC_INSTALL_INTERRUPT_HANDLERS
  262. FPC_INSTALL_INTERRUPT_HANDLERS:
  263. push ds
  264. ; save old int 00 handler
  265. mov ax, 3500h
  266. int 21h
  267. mov [__SaveInt00], bx
  268. mov bx, es
  269. mov [__SaveInt00+2], bx
  270. ; install the new int 00 handler
  271. %ifndef __TINY__
  272. push cs
  273. pop ds
  274. %endif
  275. mov dx, FPC_INT00_HANDLER
  276. mov ax, 2500h
  277. int 21h
  278. pop ds
  279. %ifdef __FAR_CODE__
  280. retf
  281. %else
  282. ret
  283. %endif
  284. global FPC_RESTORE_INTERRUPT_HANDLERS
  285. FPC_RESTORE_INTERRUPT_HANDLERS:
  286. push ds
  287. mov ax, 2500h
  288. lds dx, [__SaveInt00]
  289. int 21h
  290. pop ds
  291. %ifdef __FAR_CODE__
  292. retf
  293. %else
  294. ret
  295. %endif
  296. global FPC_MSDOS_CARRY
  297. FPC_MSDOS_CARRY:
  298. stc
  299. global FPC_MSDOS
  300. FPC_MSDOS:
  301. mov al, 21h ; not ax, because only the low byte is used
  302. pop dx
  303. %ifdef __FAR_CODE__
  304. pop bx
  305. %endif
  306. pop cx
  307. %ifdef __FAR_DATA__
  308. pop si
  309. %endif
  310. push ax
  311. %ifdef __FAR_DATA__
  312. push si
  313. %endif
  314. push cx
  315. %ifdef __FAR_CODE__
  316. push bx
  317. %endif
  318. push dx
  319. global FPC_INTR
  320. FPC_INTR:
  321. push bp
  322. mov bp, sp
  323. mov al, byte [bp + 6 + extra_param_offset + extra_data_offset]
  324. mov byte [cs:int_number], al
  325. mov si, [bp + 4 + extra_param_offset]
  326. push ds
  327. %ifdef __FAR_DATA__
  328. mov ax, [bp + 6 + extra_param_offset]
  329. mov ds, ax
  330. %endif
  331. mov ax, word [si + 16]
  332. mov es, ax
  333. mov ax, word [si + 14] ; ds
  334. push ax
  335. mov ax, word [si]
  336. mov bx, word [si + 2]
  337. mov cx, word [si + 4]
  338. mov dx, word [si + 6]
  339. mov bp, word [si + 8]
  340. mov di, word [si + 12]
  341. mov si, word [si + 10]
  342. pop ds
  343. db 0CDh ; opcode of INT xx
  344. int_number:
  345. db 255
  346. pushf
  347. push ds
  348. push si
  349. push bp
  350. mov bp, sp
  351. %ifdef __FAR_DATA__
  352. mov si, [bp + 16 + extra_param_offset]
  353. %else
  354. mov si, word [bp + 8]
  355. %endif
  356. mov ds, si
  357. mov si, word [bp + 14 + extra_param_offset]
  358. mov word [si], ax
  359. mov word [si + 2], bx
  360. mov word [si + 4], cx
  361. mov word [si + 6], dx
  362. mov word [si + 12], di
  363. mov ax, es
  364. mov word [si + 16], ax
  365. pop ax
  366. mov word [si + 8], ax
  367. pop ax
  368. mov word [si + 10], ax
  369. pop ax
  370. mov word [si + 14], ax
  371. pop ax
  372. mov word [si + 18], ax
  373. pop ds
  374. pop bp
  375. %ifdef __FAR_CODE__
  376. retf 4
  377. %else
  378. ret 4
  379. %endif
  380. %ifndef __TINY__
  381. global FPC_CHECK_NULLAREA
  382. FPC_CHECK_NULLAREA:
  383. push ds
  384. pop es
  385. xor di, di
  386. mov cx, 32
  387. mov al, 1
  388. cld
  389. repe scasb
  390. je .skip
  391. dec ax ; 1 byte shorter than dec al
  392. .skip:
  393. %ifdef __FAR_CODE__
  394. retf
  395. %else
  396. ret
  397. %endif
  398. %endif
  399. segment data class=data
  400. mem_realloc_err_msg:
  401. db 'Memory allocation error', 13, 10, '$'
  402. not_enough_mem_msg:
  403. db 'Not enough memory', 13, 10, '$'
  404. ; add reference to the beginning of the minimal heap, so the object
  405. ; module, containing the heap segment doesn't get smartlinked away
  406. dd ___heap
  407. segment bss class=bss
  408. %ifndef __TINY__
  409. segment _NULL align=16 class=BEGDATA
  410. global __nullarea
  411. __nullarea:
  412. dd 01010101h, 01010101h, 01010101h, 01010101h
  413. dd 01010101h, 01010101h, 01010101h, 01010101h
  414. segment _AFTERNULL align=2 class=BEGDATA
  415. dw 0
  416. %ifdef __NEAR_DATA__
  417. segment stack stack class=stack
  418. %else
  419. segment data
  420. ; add reference to the beginning of stack, so the object module,
  421. ; containing the stack segment doesn't get smartlinked away
  422. dd ___stack
  423. %endif
  424. %endif
  425. %ifdef __TINY__
  426. group dgroup text data bss
  427. %else
  428. %ifdef __NEAR_DATA__
  429. group dgroup _NULL _AFTERNULL data bss stack
  430. %else
  431. group dgroup _NULL _AFTERNULL data bss
  432. %endif
  433. %endif