prt0comn.asm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  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. %ifdef __TINY__
  128. mov cx, cs
  129. mov dx, 1000h ; 64kb in paragraphs
  130. %else
  131. mov dx, word [dos_psp]
  132. mov cx, dx
  133. sub dx, dgroup
  134. neg dx ; dx = (ds - psp) in paragraphs
  135. add dx, 1000h ; 64kb in paragraphs
  136. %endif
  137. ; get our MCB size in paragraphs
  138. dec cx
  139. mov es, cx
  140. mov bx, word [es:3]
  141. ; is it smaller than the maximum data segment size?
  142. cmp bx, dx
  143. jbe skip_mem_realloc
  144. mov bx, dx
  145. inc cx
  146. mov es, cx
  147. mov ah, 4Ah
  148. int 21h
  149. jc mem_realloc_err
  150. skip_mem_realloc:
  151. ; bx = the new size in paragraphs
  152. %ifndef __TINY__
  153. add bx, word [dos_psp]
  154. sub bx, dgroup
  155. %endif
  156. mov cl, 4
  157. shl bx, cl
  158. sub bx, 2
  159. mov sp, bx
  160. mov word [__stktop], sp
  161. add bx, 2
  162. sub bx, word [__stklen]
  163. and bl, 0FEh
  164. mov word [__stkbottom], bx
  165. cmp bx, _end wrt dgroup
  166. jb not_enough_mem
  167. ; heap is between [ds:_end wrt dgroup] and [ds:__stkbottom - 1]
  168. mov word [__nearheap_start], _end wrt dgroup
  169. mov bx, word [__stkbottom]
  170. dec bx
  171. mov word [__nearheap_end], bx
  172. ; ****************************************************************************
  173. ; ** near data setup done **
  174. ; ****************************************************************************
  175. %endif
  176. %ifdef __FAR_DATA__
  177. mov word [__stktop], sp
  178. mov word [__stkbottom], 0
  179. mov ax, ss
  180. mov word [__stkbottom + 2], ax
  181. mov word [__stktop + 2], ax
  182. mov dx, sp
  183. add dx, 15
  184. mov cl, 4
  185. shr dx, cl
  186. add ax, dx
  187. mov word [__nearheap_start], 0
  188. mov word [__nearheap_end], 0FFF0h
  189. mov word [__nearheap_start + 2], ax
  190. mov word [__nearheap_end + 2], ax
  191. %endif
  192. %ifdef __FAR_CODE__
  193. jmp far PASCALMAIN
  194. %else
  195. jmp PASCALMAIN
  196. %endif
  197. not_enough_mem:
  198. mov dx, not_enough_mem_msg
  199. jmp error_msg
  200. mem_realloc_err:
  201. mov dx, mem_realloc_err_msg
  202. error_msg:
  203. mov ah, 9
  204. int 21h
  205. mov ax, 4CFFh
  206. int 21h
  207. FPC_INT00_HANDLER:
  208. sub sp, 4 ; reserve space on the stack for the retf
  209. push bx
  210. push cx
  211. push ds
  212. ; init ds
  213. %ifdef __TINY__
  214. mov bx, cs
  215. %else
  216. mov bx, dgroup
  217. %endif
  218. mov ds, bx
  219. ; check whether we're running on the same stack
  220. mov cx, ss
  221. cmp bx, cx
  222. jne .call_previous_handler
  223. %ifndef __FAR_CODE__
  224. ; check whether we're coming from the same code segment
  225. mov bx, sp
  226. mov cx, [bx + 3*2 + 6] ; get caller segment
  227. mov bx, cs
  228. cmp bx, cx
  229. jne .call_previous_handler
  230. %endif
  231. ; runerror 200
  232. mov bx, sp
  233. mov cx, [bx + 3*2 + 4] ; get caller offset
  234. %ifdef __FAR_CODE__
  235. mov dx, [bx + 3*2 + 6] ; get caller segment
  236. %endif
  237. add sp, 3*2 + 4 + 6
  238. xor ax, ax
  239. push ax
  240. mov ax, 200
  241. push ax
  242. %ifdef __FAR_CODE__
  243. push dx
  244. %endif
  245. push cx
  246. cld
  247. %ifdef __FAR_CODE__
  248. jmp far FPC_HANDLEERROR
  249. %else
  250. jmp FPC_HANDLEERROR
  251. %endif
  252. .call_previous_handler:
  253. mov bx, sp
  254. mov cx, [__SaveInt00]
  255. mov [ss:bx + 3*2], cx
  256. mov cx, [__SaveInt00+2]
  257. mov [ss:bx + 3*2 + 2], cx
  258. pop ds
  259. pop cx
  260. pop bx
  261. retf ; jumps to the previous handler with all registers and stack intact
  262. global FPC_INSTALL_INTERRUPT_HANDLERS
  263. FPC_INSTALL_INTERRUPT_HANDLERS:
  264. push ds
  265. ; save old int 00 handler
  266. mov ax, 3500h
  267. int 21h
  268. mov [__SaveInt00], bx
  269. mov bx, es
  270. mov [__SaveInt00+2], bx
  271. ; install the new int 00 handler
  272. %ifndef __TINY__
  273. push cs
  274. pop ds
  275. %endif
  276. mov dx, FPC_INT00_HANDLER
  277. mov ax, 2500h
  278. int 21h
  279. pop ds
  280. %ifdef __FAR_CODE__
  281. retf
  282. %else
  283. ret
  284. %endif
  285. global FPC_RESTORE_INTERRUPT_HANDLERS
  286. FPC_RESTORE_INTERRUPT_HANDLERS:
  287. push ds
  288. mov ax, 2500h
  289. lds dx, [__SaveInt00]
  290. int 21h
  291. pop ds
  292. %ifdef __FAR_CODE__
  293. retf
  294. %else
  295. ret
  296. %endif
  297. global FPC_MSDOS_CARRY
  298. FPC_MSDOS_CARRY:
  299. stc
  300. global FPC_MSDOS
  301. FPC_MSDOS:
  302. mov al, 21h ; not ax, because only the low byte is used
  303. pop dx
  304. %ifdef __FAR_CODE__
  305. pop bx
  306. %endif
  307. pop cx
  308. %ifdef __FAR_DATA__
  309. pop si
  310. %endif
  311. push ax
  312. %ifdef __FAR_DATA__
  313. push si
  314. %endif
  315. push cx
  316. %ifdef __FAR_CODE__
  317. push bx
  318. %endif
  319. push dx
  320. global FPC_INTR
  321. FPC_INTR:
  322. push bp
  323. mov bp, sp
  324. mov al, byte [bp + 6 + extra_param_offset + extra_data_offset]
  325. mov byte [cs:int_number], al
  326. mov si, [bp + 4 + extra_param_offset]
  327. push ds
  328. %ifdef __FAR_DATA__
  329. mov ax, [bp + 6 + extra_param_offset]
  330. mov ds, ax
  331. %endif
  332. mov ax, word [si + 16]
  333. mov es, ax
  334. mov ax, word [si + 14] ; ds
  335. push ax
  336. mov ax, word [si]
  337. mov bx, word [si + 2]
  338. mov cx, word [si + 4]
  339. mov dx, word [si + 6]
  340. mov bp, word [si + 8]
  341. mov di, word [si + 12]
  342. mov si, word [si + 10]
  343. pop ds
  344. db 0CDh ; opcode of INT xx
  345. int_number:
  346. db 255
  347. pushf
  348. push ds
  349. push si
  350. push bp
  351. mov bp, sp
  352. %ifdef __FAR_DATA__
  353. mov si, [bp + 16 + extra_param_offset]
  354. %else
  355. mov si, word [bp + 8]
  356. %endif
  357. mov ds, si
  358. mov si, word [bp + 14 + extra_param_offset]
  359. mov word [si], ax
  360. mov word [si + 2], bx
  361. mov word [si + 4], cx
  362. mov word [si + 6], dx
  363. mov word [si + 12], di
  364. mov ax, es
  365. mov word [si + 16], ax
  366. pop ax
  367. mov word [si + 8], ax
  368. pop ax
  369. mov word [si + 10], ax
  370. pop ax
  371. mov word [si + 14], ax
  372. pop ax
  373. mov word [si + 18], ax
  374. pop ds
  375. pop bp
  376. %ifdef __FAR_CODE__
  377. retf 4
  378. %else
  379. ret 4
  380. %endif
  381. global FPC_CHECK_NULLAREA
  382. FPC_CHECK_NULLAREA:
  383. %ifdef __TINY__
  384. ; tiny model has no nil pointer assignment checking; always return true.
  385. mov al, 1
  386. %else
  387. push ds
  388. pop es
  389. xor di, di
  390. mov cx, 32
  391. mov al, 1
  392. cld
  393. repe scasb
  394. je .skip
  395. dec ax ; 1 byte shorter than dec al
  396. .skip:
  397. %endif
  398. %ifdef __FAR_CODE__
  399. retf
  400. %else
  401. ret
  402. %endif
  403. segment data class=data
  404. mem_realloc_err_msg:
  405. db 'Memory allocation error', 13, 10, '$'
  406. not_enough_mem_msg:
  407. db 'Not enough memory', 13, 10, '$'
  408. ; add reference to the beginning of the minimal heap, so the object
  409. ; module, containing the heap segment doesn't get smartlinked away
  410. dd ___heap
  411. segment bss class=bss
  412. %ifndef __TINY__
  413. segment _NULL align=16 class=BEGDATA
  414. global __nullarea
  415. __nullarea:
  416. dd 01010101h, 01010101h, 01010101h, 01010101h
  417. dd 01010101h, 01010101h, 01010101h, 01010101h
  418. segment _AFTERNULL align=2 class=BEGDATA
  419. dw 0
  420. %ifdef __NEAR_DATA__
  421. segment stack stack class=stack
  422. %else
  423. segment data
  424. ; add reference to the beginning of stack, so the object module,
  425. ; containing the stack segment doesn't get smartlinked away
  426. dd ___stack
  427. %endif
  428. %endif
  429. %ifdef __TINY__
  430. group dgroup text data bss
  431. %else
  432. %ifdef __NEAR_DATA__
  433. group dgroup _NULL _AFTERNULL data bss stack
  434. %else
  435. group dgroup _NULL _AFTERNULL data bss
  436. %endif
  437. %endif