prt0stm.asm 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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 __stkbottom
  22. extern __nearheap_start
  23. extern __nearheap_end
  24. %ifdef __TINY__
  25. resb 0100h
  26. %endif
  27. ..start:
  28. %ifdef __TINY__
  29. mov bx, cs
  30. %else
  31. ; init the stack
  32. mov bx, dgroup
  33. mov ss, bx
  34. mov sp, stacktop
  35. %endif
  36. ; zero fill the BSS section
  37. mov es, bx
  38. mov di, _edata wrt dgroup
  39. mov cx, _end wrt dgroup
  40. sub cx, di
  41. jz no_bss
  42. xor al, al
  43. rep stosb
  44. no_bss:
  45. ; save the Program Segment Prefix
  46. push ds
  47. ; init DS
  48. mov ds, bx
  49. ; pop the PSP from stack and store it in the pascal variable dos_psp
  50. pop ax
  51. mov word [dos_psp], ax
  52. ; get DOS version and save it in the pascal variable dos_version
  53. mov ax, 3000h
  54. int 21h
  55. xchg al, ah
  56. mov word [dos_version], ax
  57. ; detect CPU
  58. xor bx, bx ; 0=8086/8088/80186/80188/NEC V20/NEC V30
  59. ; on pre-286 processors, bits 12..15 of the FLAGS registers are always set
  60. pushf
  61. pop ax
  62. and ah, 0fh
  63. push ax
  64. popf
  65. pushf
  66. pop ax
  67. and ah, 0f0h
  68. cmp ah, 0f0h
  69. je cpu_detect_done
  70. ; at this point we have a 286 or higher
  71. inc bx
  72. ; on a true 286 in real mode, bits 12..15 are always clear
  73. pushf
  74. pop ax
  75. or ah, 0f0h
  76. push ax
  77. popf
  78. pushf
  79. pop ax
  80. and ah, 0f0h
  81. jz cpu_detect_done
  82. ; we have a 386+
  83. inc bx
  84. cpu_detect_done:
  85. mov [__Test8086], bl
  86. ; allocate max heap
  87. ; TODO: also support user specified heap size
  88. ; try to resize our main DOS memory block until the end of the data segment
  89. %ifdef __TINY__
  90. mov cx, cs
  91. mov dx, 1000h ; 64kb in paragraphs
  92. %else
  93. mov dx, word [dos_psp]
  94. mov cx, dx
  95. sub dx, dgroup
  96. neg dx ; dx = (ds - psp) in paragraphs
  97. add dx, 1000h ; 64kb in paragraphs
  98. %endif
  99. ; get our MCB size in paragraphs
  100. dec cx
  101. mov es, cx
  102. mov bx, word [es:3]
  103. ; is it smaller than the maximum data segment size?
  104. cmp bx, dx
  105. jbe skip_mem_realloc
  106. mov bx, dx
  107. inc cx
  108. mov es, cx
  109. mov ah, 4Ah
  110. int 21h
  111. jc mem_realloc_err
  112. skip_mem_realloc:
  113. ; bx = the new size in paragraphs
  114. %ifndef __TINY__
  115. add bx, word [dos_psp]
  116. sub bx, dgroup
  117. %endif
  118. mov cl, 4
  119. shl bx, cl
  120. sub bx, 2
  121. mov sp, bx
  122. add bx, 2
  123. sub bx, word [__stklen]
  124. and bl, 0FEh
  125. mov word [__stkbottom], bx
  126. cmp bx, _end wrt dgroup
  127. jb not_enough_mem
  128. ; heap is between [ds:_end wrt dgroup] and [ds:__stkbottom - 1]
  129. mov word [__nearheap_start], _end wrt dgroup
  130. mov bx, word [__stkbottom]
  131. dec bx
  132. mov word [__nearheap_end], bx
  133. %ifdef __FAR_CODE__
  134. jmp far PASCALMAIN
  135. %else
  136. jmp PASCALMAIN
  137. %endif
  138. not_enough_mem:
  139. mov dx, not_enough_mem_msg
  140. jmp error_msg
  141. mem_realloc_err:
  142. mov dx, mem_realloc_err_msg
  143. error_msg:
  144. mov ah, 9
  145. int 21h
  146. mov ax, 4CFFh
  147. int 21h
  148. global FPC_MSDOS_CARRY
  149. FPC_MSDOS_CARRY:
  150. stc
  151. global FPC_MSDOS
  152. FPC_MSDOS:
  153. mov al, 21h ; not ax, because only the low byte is used
  154. pop dx
  155. %ifdef __FAR_CODE__
  156. pop bx
  157. %endif
  158. pop cx
  159. push ax
  160. push cx
  161. %ifdef __FAR_CODE__
  162. push bx
  163. %endif
  164. push dx
  165. global FPC_INTR
  166. FPC_INTR:
  167. push bp
  168. mov bp, sp
  169. mov al, byte [ss:bp + 6 + extra_param_offset]
  170. mov byte [cs:int_number], al
  171. mov si, [ss:bp + 4 + extra_param_offset]
  172. push ds
  173. mov ax, word [si + 16]
  174. mov es, ax
  175. mov ax, word [si + 14] ; ds
  176. push ax
  177. mov ax, word [si]
  178. mov bx, word [si + 2]
  179. mov cx, word [si + 4]
  180. mov dx, word [si + 6]
  181. mov bp, word [si + 8]
  182. mov di, word [si + 12]
  183. mov si, word [si + 10]
  184. pop ds
  185. db 0CDh ; opcode of INT xx
  186. int_number:
  187. db 255
  188. pushf
  189. push ds
  190. push si
  191. push bp
  192. mov bp, sp
  193. mov si, word [ss:bp + 8]
  194. mov ds, si
  195. mov si, word [ss:bp + 14 + extra_param_offset]
  196. mov word [si], ax
  197. mov word [si + 2], bx
  198. mov word [si + 4], cx
  199. mov word [si + 6], dx
  200. mov word [si + 12], di
  201. mov ax, es
  202. mov word [si + 16], ax
  203. pop ax
  204. mov word [si + 8], ax
  205. pop ax
  206. mov word [si + 10], ax
  207. pop ax
  208. mov word [si + 14], ax
  209. pop ax
  210. mov word [si + 18], ax
  211. pop ds
  212. pop bp
  213. %ifdef __FAR_CODE__
  214. retf 4
  215. %else
  216. ret 4
  217. %endif
  218. segment data
  219. mem_realloc_err_msg:
  220. db 'Memory allocation error', 13, 10, '$'
  221. not_enough_mem_msg:
  222. db 'Not enough memory', 13, 10, '$'
  223. segment bss class=bss
  224. %ifndef __TINY__
  225. segment stack stack class=stack
  226. resb 256
  227. stacktop:
  228. %endif
  229. %ifdef __TINY__
  230. group dgroup text data bss
  231. %else
  232. group dgroup data bss stack
  233. %endif