prt0comn.asm 12 KB

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