prt0stm.asm 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. ; common startup code for the SMALL, TINY and MEDIUM memory models
  2. %ifdef __MEDIUM__
  3. %define __FAR_CODE__
  4. %else
  5. %define __NEAR_CODE__
  6. %endif
  7. %ifdef __FAR_CODE__
  8. extra_param_offset equ 2
  9. %else
  10. extra_param_offset equ 0
  11. %endif
  12. cpu 8086
  13. segment text use16 class=code
  14. extern PASCALMAIN
  15. extern dos_psp
  16. extern dos_version
  17. extern __Test8086
  18. extern _edata ; defined by WLINK, indicates start of BSS
  19. extern _end ; defined by WLINK, indicates end of BSS
  20. extern __stklen
  21. extern __stktop
  22. extern __stkbottom
  23. extern __nearheap_start
  24. extern __nearheap_end
  25. extern __SaveInt00
  26. extern FPC_HANDLEERROR
  27. %ifdef __TINY__
  28. resb 0100h
  29. %endif
  30. ..start:
  31. %ifdef __TINY__
  32. mov bx, cs
  33. %else
  34. ; init the stack
  35. mov bx, dgroup
  36. mov ss, bx
  37. mov sp, stacktop
  38. %endif
  39. ; zero fill the BSS section
  40. mov es, bx
  41. mov di, _edata wrt dgroup
  42. mov cx, _end wrt dgroup
  43. sub cx, di
  44. xor al, al
  45. cld
  46. rep stosb
  47. ; save the Program Segment Prefix
  48. push ds
  49. ; init DS
  50. mov ds, bx
  51. ; pop the PSP from stack and store it in the pascal variable dos_psp
  52. pop ax
  53. mov word [dos_psp], ax
  54. ; get DOS version and save it in the pascal variable dos_version
  55. mov ax, 3000h
  56. int 21h
  57. xchg al, ah
  58. mov word [dos_version], ax
  59. ; detect CPU
  60. xor bx, bx ; 0=8086/8088/80186/80188/NEC V20/NEC V30
  61. ; on pre-286 processors, bits 12..15 of the FLAGS registers are always set
  62. pushf
  63. pop ax
  64. and ah, 0fh
  65. push ax
  66. popf
  67. pushf
  68. pop ax
  69. and ah, 0f0h
  70. cmp ah, 0f0h
  71. je cpu_detect_done
  72. ; at this point we have a 286 or higher
  73. inc bx
  74. ; on a true 286 in real mode, bits 12..15 are always clear
  75. pushf
  76. pop ax
  77. or ah, 0f0h
  78. push ax
  79. popf
  80. pushf
  81. pop ax
  82. and ah, 0f0h
  83. jz cpu_detect_done
  84. ; we have a 386+
  85. inc bx
  86. cpu_detect_done:
  87. mov [__Test8086], bl
  88. ; allocate max heap
  89. ; TODO: also support user specified heap size
  90. ; try to resize our main DOS memory block until the end of the data segment
  91. %ifdef __TINY__
  92. mov cx, cs
  93. mov dx, 1000h ; 64kb in paragraphs
  94. %else
  95. mov dx, word [dos_psp]
  96. mov cx, dx
  97. sub dx, dgroup
  98. neg dx ; dx = (ds - psp) in paragraphs
  99. add dx, 1000h ; 64kb in paragraphs
  100. %endif
  101. ; get our MCB size in paragraphs
  102. dec cx
  103. mov es, cx
  104. mov bx, word [es:3]
  105. ; is it smaller than the maximum data segment size?
  106. cmp bx, dx
  107. jbe skip_mem_realloc
  108. mov bx, dx
  109. inc cx
  110. mov es, cx
  111. mov ah, 4Ah
  112. int 21h
  113. jc mem_realloc_err
  114. skip_mem_realloc:
  115. ; bx = the new size in paragraphs
  116. %ifndef __TINY__
  117. add bx, word [dos_psp]
  118. sub bx, dgroup
  119. %endif
  120. mov cl, 4
  121. shl bx, cl
  122. sub bx, 2
  123. mov sp, bx
  124. mov word [__stktop], sp
  125. add bx, 2
  126. sub bx, word [__stklen]
  127. and bl, 0FEh
  128. mov word [__stkbottom], bx
  129. cmp bx, _end wrt dgroup
  130. jb not_enough_mem
  131. ; heap is between [ds:_end wrt dgroup] and [ds:__stkbottom - 1]
  132. mov word [__nearheap_start], _end wrt dgroup
  133. mov bx, word [__stkbottom]
  134. dec bx
  135. mov word [__nearheap_end], bx
  136. %ifdef __FAR_CODE__
  137. jmp far PASCALMAIN
  138. %else
  139. jmp PASCALMAIN
  140. %endif
  141. not_enough_mem:
  142. mov dx, not_enough_mem_msg
  143. jmp error_msg
  144. mem_realloc_err:
  145. mov dx, mem_realloc_err_msg
  146. error_msg:
  147. mov ah, 9
  148. int 21h
  149. mov ax, 4CFFh
  150. int 21h
  151. FPC_INT00_HANDLER:
  152. sub sp, 4 ; reserve space on the stack for the retf
  153. push bx
  154. push cx
  155. push ds
  156. ; init ds
  157. %ifdef __TINY__
  158. mov bx, cs
  159. %else
  160. mov bx, dgroup
  161. %endif
  162. mov ds, bx
  163. ; check whether we're running on the same stack
  164. mov cx, ss
  165. cmp bx, cx
  166. jne .call_previous_handler
  167. %ifndef __FAR_CODE__
  168. ; check whether we're coming from the same code segment
  169. mov bx, sp
  170. mov cx, [bx + 3*2 + 6] ; get caller segment
  171. mov bx, cs
  172. cmp bx, cx
  173. jne .call_previous_handler
  174. %endif
  175. ; runerror 200
  176. mov bx, sp
  177. mov cx, [bx + 3*2 + 4] ; get caller offset
  178. %ifdef __FAR_CODE__
  179. mov dx, [bx + 3*2 + 6] ; get caller segment
  180. %endif
  181. add sp, 3*2 + 4 + 6
  182. xor ax, ax
  183. push ax
  184. mov ax, 200
  185. push ax
  186. %ifdef __FAR_CODE__
  187. push dx
  188. %endif
  189. push cx
  190. cld
  191. %ifdef __FAR_CODE__
  192. jmp far FPC_HANDLEERROR
  193. %else
  194. jmp FPC_HANDLEERROR
  195. %endif
  196. .call_previous_handler:
  197. mov bx, sp
  198. mov cx, [__SaveInt00]
  199. mov [ss:bx + 3*2], cx
  200. mov cx, [__SaveInt00+2]
  201. mov [ss:bx + 3*2 + 2], cx
  202. pop ds
  203. pop cx
  204. pop bx
  205. retf ; jumps to the previous handler with all registers and stack intact
  206. global FPC_INSTALL_INTERRUPT_HANDLERS
  207. FPC_INSTALL_INTERRUPT_HANDLERS:
  208. push ds
  209. ; save old int 00 handler
  210. mov ax, 3500h
  211. int 21h
  212. mov [__SaveInt00], bx
  213. mov bx, es
  214. mov [__SaveInt00+2], bx
  215. ; install the new int 00 handler
  216. %ifndef __TINY__
  217. push cs
  218. pop ds
  219. %endif
  220. mov dx, FPC_INT00_HANDLER
  221. mov ax, 2500h
  222. int 21h
  223. pop ds
  224. %ifdef __FAR_CODE__
  225. retf
  226. %else
  227. ret
  228. %endif
  229. global FPC_RESTORE_INTERRUPT_HANDLERS
  230. FPC_RESTORE_INTERRUPT_HANDLERS:
  231. push ds
  232. mov ax, 2500h
  233. lds dx, [__SaveInt00]
  234. int 21h
  235. pop ds
  236. %ifdef __FAR_CODE__
  237. retf
  238. %else
  239. ret
  240. %endif
  241. global FPC_MSDOS_CARRY
  242. FPC_MSDOS_CARRY:
  243. stc
  244. global FPC_MSDOS
  245. FPC_MSDOS:
  246. mov al, 21h ; not ax, because only the low byte is used
  247. pop dx
  248. %ifdef __FAR_CODE__
  249. pop bx
  250. %endif
  251. pop cx
  252. push ax
  253. push cx
  254. %ifdef __FAR_CODE__
  255. push bx
  256. %endif
  257. push dx
  258. global FPC_INTR
  259. FPC_INTR:
  260. push bp
  261. mov bp, sp
  262. mov al, byte [bp + 6 + extra_param_offset]
  263. mov byte [cs:int_number], al
  264. mov si, [bp + 4 + extra_param_offset]
  265. push ds
  266. mov ax, word [si + 16]
  267. mov es, ax
  268. mov ax, word [si + 14] ; ds
  269. push ax
  270. mov ax, word [si]
  271. mov bx, word [si + 2]
  272. mov cx, word [si + 4]
  273. mov dx, word [si + 6]
  274. mov bp, word [si + 8]
  275. mov di, word [si + 12]
  276. mov si, word [si + 10]
  277. pop ds
  278. db 0CDh ; opcode of INT xx
  279. int_number:
  280. db 255
  281. pushf
  282. push ds
  283. push si
  284. push bp
  285. mov bp, sp
  286. mov si, word [bp + 8]
  287. mov ds, si
  288. mov si, word [bp + 14 + extra_param_offset]
  289. mov word [si], ax
  290. mov word [si + 2], bx
  291. mov word [si + 4], cx
  292. mov word [si + 6], dx
  293. mov word [si + 12], di
  294. mov ax, es
  295. mov word [si + 16], ax
  296. pop ax
  297. mov word [si + 8], ax
  298. pop ax
  299. mov word [si + 10], ax
  300. pop ax
  301. mov word [si + 14], ax
  302. pop ax
  303. mov word [si + 18], ax
  304. pop ds
  305. pop bp
  306. %ifdef __FAR_CODE__
  307. retf 4
  308. %else
  309. ret 4
  310. %endif
  311. segment data
  312. mem_realloc_err_msg:
  313. db 'Memory allocation error', 13, 10, '$'
  314. not_enough_mem_msg:
  315. db 'Not enough memory', 13, 10, '$'
  316. segment bss class=bss
  317. %ifndef __TINY__
  318. segment stack stack class=stack
  319. resb 256
  320. stacktop:
  321. %endif
  322. %ifdef __TINY__
  323. group dgroup text data bss
  324. %else
  325. group dgroup data bss stack
  326. %endif