ODSwap.asm 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. ; OpenDoors Online Software Programming Toolkit
  2. ; (C) Copyright 1991 - 1999 by Brian Pirie.
  3. ;
  4. ; This library is free software; you can redistribute it and/or
  5. ; modify it under the terms of the GNU Lesser General Public
  6. ; License as published by the Free Software Foundation; either
  7. ; version 2 of the License, or (at your option) any later version.
  8. ;
  9. ; This library is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ; Lesser General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU Lesser General Public
  15. ; License along with this library; if not, write to the Free Software
  16. ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. ;
  18. ;
  19. ; File: ODSwap.asm
  20. ;
  21. ; Description: Performs EMS/disk swapping and low level spawning
  22. ; activities. This file should only be included when building
  23. ; the MS-DOS version of OpenDoors.
  24. ;
  25. ; Revisions: Date Ver Who Change
  26. ; ---------------------------------------------------------------
  27. ; Oct 13, 1994 6.00 BP New file header format.
  28. ; Feb 19, 1996 6.00 BP Changed version number to 6.00.
  29. ; Mar 03, 1996 6.10 BP Begin version 6.10.
  30. ; If you have increased the file handle table size so that more than 20 files
  31. ; may be open in the parent process, set FHTSZ to the new size.
  32. FHTSZ EQU 20
  33. IFDEF LCODE
  34. ARG_1 EQU 6
  35. ELSE
  36. ARG_1 EQU 4
  37. ENDIF
  38. arena struc ; arena header
  39. sig db 0 ; 'M' or 'Z' if last block
  40. own dw 0 ; PSP of owner or 0 if free
  41. siz dw 0 ; size not including header
  42. arena ends
  43. vector struc
  44. number db 0 ; vector number
  45. flag db 0 ; 0-CURRENT,1-IRET,2-free,3-end
  46. vseg dw 0 ; vector segment
  47. voff dw 0 ; vector offset
  48. vector ends
  49. _TEXT SEGMENT word public 'CODE'
  50. ASSUME cs:_TEXT
  51. ASSUME ds:nothing
  52. ASSUME es:nothing
  53. ASSUME ss:nothing
  54. ; The code between slidetop and slidebot constitutes the spawn kernel. The
  55. ; kernel is copied to the front of the parent process immediately following the
  56. ; parent's PSP. The environment passed to the child is copied to immediately
  57. ; following the kernel.
  58. slidetop:
  59. path db 79 dup (0) ; program to execute
  60. command db 128 dup (0) ; command-line
  61. file db 79 dup (0) ; swap file
  62. parmblk label byte ; parameter block
  63. environ dw 0 ; environment block
  64. cmd dw 0,0 ; command-line tail
  65. fcb1 dw 0,0 ; first file control block
  66. fcb2 dw 0,0 ; second file control block
  67. fcb5c db 10h dup (0) ; first file control block
  68. fcb6c db 10h dup (0) ; second file control block
  69. cntsvl dw 0 ; count save low
  70. cntsvh dw 0 ; count save high
  71. tmpcode dw 0 ; temporary return code
  72. env dw 0 ; environment segment
  73. envlen dw 0 ; environment length
  74. parsz dw 0 ; parent size
  75. ttlsz dw 0 ; total size
  76. oldsz dw 0 ; old size
  77. newsz dw 0 ; new size
  78. emsseg dw 0 ; EMS page frame segment
  79. handle dw 0 ; EMS handle
  80. useems db 0 ; if 0, use EMS
  81. save db 4 dup (0) ; save 4 bytes at DS:[2Eh]
  82. f1add dd 0 ; fnish1 address
  83. last db 0 ; if 0, last block swap
  84. IF FHTSZ - 20
  85. fhtsv db FHTSZ dup (0) ; file handle table save
  86. ENDIF
  87. errmsg db 'spawn error',0Dh,0Ah
  88. msglen EQU $-errmsg
  89. EVEN
  90. lclstk dw 64 dup (0) ; local stack
  91. stktop label word ; stack top
  92. slide1: mov ax,cs ; install local stack
  93. cli
  94. mov ss,ax
  95. mov sp,offset stktop - offset slidetop + 100h
  96. sti
  97. ; copy environment
  98. mov bx,offset slidebot - offset slidetop + 15 + 100h
  99. mov cl,4
  100. shr bx,cl ; convert to paragraphs
  101. add bx,ax ; add CS (actually PSP)
  102. index = offset environ - offset slidetop + 100h
  103. mov cs:[index],bx ; parameter block
  104. mov es,bx
  105. xor di,di
  106. index = offset env - offset slidetop + 100h
  107. mov ds,cs:[index]
  108. xor si,si
  109. index = offset envlen - offset slidetop + 100h
  110. mov cx,cs:[index]
  111. shr cx,1 ; translate to word count
  112. rep movsw ; CF set if one byte left over
  113. adc cx,cx ; CX = 1 or 0, depending CF
  114. rep movsb ; possible final byte
  115. dec ax ; PSP segment
  116. mov es,ax ; program arena header
  117. mov bx,es:[siz]
  118. index = offset oldsz - offset slidetop + 100h
  119. mov cs:[index],bx ; old size
  120. mov byte ptr es:[sig],'M' ; not last
  121. index = offset newsz - offset slidetop + 100h
  122. mov bx,cs:[index] ; new size
  123. mov es:[siz],bx
  124. inc ax ; PSP segment
  125. add ax,bx ; add new size
  126. mov es,ax ; new last arena header
  127. mov byte ptr es:[sig],'Z' ; last
  128. index = offset last - offset slidetop + 100h
  129. cmp byte ptr cs:[index],0
  130. je slide2 ; jump if last block swap
  131. mov byte ptr es:[sig],'M' ; not last
  132. slide2: mov word ptr es:[own],0 ; free
  133. index = offset ttlsz - offset slidetop + 100h
  134. mov ax,cs:[index] ; total size
  135. sub ax,bx ; subtract new size
  136. dec ax ; account for arena header
  137. mov es:[siz],ax
  138. ; save 4 bytes destroyed by DOS 2.0 at DS:2Eh
  139. mov ax,cs ; PSP segment
  140. mov es,ax
  141. mov bx,es:[2Eh]
  142. index = offset save - offset slidetop + 100h
  143. mov cs:[index],bx
  144. mov bx,es:[30h]
  145. index = offset save - offset slidetop + 102h
  146. mov cs:[index],bx
  147. mov bx,offset parmblk - offset slidetop + 100h
  148. mov ds,ax ; PSP segment
  149. mov dx,100h ; offset path
  150. mov ax,4B00h ; load and execute program
  151. int 21h
  152. jnc slide3 ; jump if no error
  153. index = offset tmpcode - offset slidetop + 100h
  154. mov cs:[index],ax ; temporary return code
  155. slide3: mov ax,cs ; install local stack
  156. cli
  157. mov ss,ax
  158. mov sp,offset stktop - offset slidetop + 100h
  159. sti
  160. ; restore 4 bytes destroyed by DOS 2.0 at DS:2Eh
  161. mov es,ax ; PSP segment
  162. index = offset save - offset slidetop + 100h
  163. mov bx,cs:[index]
  164. mov es:[2Eh],bx
  165. index = offset save - offset slidetop + 102h
  166. mov bx,cs:[index]
  167. mov es:[30h],bx
  168. index = offset oldsz - offset slidetop + 100h
  169. mov bx,cs:[index] ; old size
  170. mov ah,4Ah ; resize memory block
  171. int 21h
  172. jnc slide7
  173. index = offset useems - offset slidetop + 100h
  174. slide4: cmp byte ptr cs:[index],0
  175. jne slide6 ; jump if don't use EMS
  176. index = offset handle - offset slidetop + 100h
  177. mov dx,cs:[index] ; EMS handle
  178. slide5: mov ah,45h ; release handle and memory
  179. int 67h
  180. cmp ah,82h ; memory manager busy?
  181. je slide5 ; jump if busy
  182. slide6: jmp slide18 ; exit
  183. index = offset parsz - offset slidetop + 100h
  184. slide7: mov bx,cs:[index] ; parent size
  185. index = offset ttlsz - offset slidetop + 100h
  186. mov ax,cs:[index] ; total size
  187. sub ax,bx ; subtract parent size
  188. or ax,ax
  189. jz slide9
  190. mov dx,cs ; PSP segment
  191. add dx,bx ; add parent size
  192. mov es,dx ; new last arena header
  193. mov byte ptr es:[sig],'Z' ; last
  194. index = offset last - offset slidetop + 100h
  195. cmp byte ptr cs:[index],0
  196. je slide8 ; jump if last block swap
  197. mov byte ptr es:[sig],'M' ; not last
  198. slide8: mov word ptr es:[own],0 ; free
  199. dec ax ; account for arena header
  200. mov es:[siz],ax
  201. slide9: push cs ; PSP segment
  202. index = offset useems - offset slidetop + 100h
  203. cmp byte ptr cs:[index],0
  204. jne slide14 ; jump if don't use EMS
  205. pop es ; PSP segment
  206. mov di,offset slidebot - offset slidetop + 100h
  207. index = offset emsseg - offset slidetop + 100h
  208. mov ds,cs:[index] ; EMS page frame segment
  209. mov si,offset slidebot - offset slidetop
  210. index = offset handle - offset slidetop + 100h
  211. mov dx,cs:[index] ; EMS handle
  212. xor bx,bx ; logical page number
  213. mov cx,16384 - ( offset slidebot - offset slidetop )
  214. jmp short slide13
  215. index = offset cntsvl - offset slidetop + 100h
  216. slide10: sub cs:[index],cx
  217. index = offset cntsvh - offset slidetop + 100h
  218. sbb word ptr cs:[index],0
  219. xor al,al ; physical page number
  220. slide11: mov ah,44h ; map memory
  221. int 67h
  222. or ah,ah
  223. jz slide12
  224. cmp ah,82h ; memory manager busy?
  225. je slide11 ; jump if busy
  226. jmp slide4 ; exit
  227. slide12: shr cx,1 ; translate to word count
  228. rep movsw ; CF set if one byte left over
  229. adc cx,cx ; CX = 1 or 0, depending CF
  230. rep movsb ; possible final byte
  231. xor si,si
  232. mov cx,16384 ; assume copy full block
  233. inc bx ; logical page number
  234. cmp bx,1
  235. je slide13
  236. mov ax,es
  237. add ax,1024 ; 16384 bytes
  238. mov es,ax
  239. mov di,16640 ; 16384 + 100h
  240. index = offset cntsvh - offset slidetop + 100h
  241. slide13: cmp word ptr cs:[index],0
  242. jne slide10 ; jump if more than full block
  243. index = offset cntsvl - offset slidetop + 100h
  244. cmp cs:[index],cx
  245. jae slide10 ; jump if at least full block
  246. mov cx,cs:[index] ; CX = cntsvl
  247. cmp cx,0
  248. jne slide10 ; jump if more left to copy
  249. jmp short slide17
  250. slide14: pop ds ; PSP segment
  251. IF FHTSZ - 20
  252. ; restore the file handle table from the kernel
  253. mov si,offset fhtsv - offset slidetop + 100h
  254. mov es,ds:[36h] ; file handle table segment
  255. mov di,ds:[34h] ; file handle table offset
  256. mov cx,FHTSZ ; file handle table size
  257. rep movsb
  258. ENDIF
  259. mov dx,offset file - offset slidetop + 100h
  260. mov ax,3D00h ; open file read only
  261. int 21h
  262. jc slide18 ; exit if error
  263. mov bx,ax ; handle
  264. xor cx,cx
  265. mov dx,offset slidebot - offset slidetop
  266. mov ax,4200h ; move file pointer
  267. int 21h ; from beginning of file
  268. mov dx,offset slidebot - offset slidetop + 100h
  269. mov cx,65520 ; assume read full block
  270. jmp short slide16
  271. index = offset cntsvl - offset slidetop + 100h
  272. slide15: sub cs:[index],cx
  273. index = offset cntsvh - offset slidetop + 100h
  274. sbb word ptr cs:[index],0
  275. mov ah,3Fh ; read file
  276. int 21h
  277. jc slide18 ; exit if error
  278. cmp ax,cx
  279. jne slide18 ; exit if not all read
  280. mov ax,ds
  281. add ax,4095 ; 65520 bytes
  282. mov ds,ax
  283. index = offset cntsvh - offset slidetop + 100h
  284. slide16: cmp word ptr cs:[index],0
  285. jne slide15 ; jump if more than full block
  286. index = offset cntsvl - offset slidetop + 100h
  287. cmp word ptr cs:[index],65520
  288. jae slide15 ; jump if at least full block
  289. mov cx,cs:[index] ; CX = cntsvl
  290. cmp cx,0
  291. jne slide15 ; jump if more left to read
  292. index = offset tmpcode - offset slidetop + 100h
  293. slide17: mov ax,cs:[index] ; temporary return code
  294. index = offset f1add - offset slidetop + 100h
  295. jmp dword ptr cs:[index]
  296. slide18: push cs ; PSP segment
  297. pop ds
  298. mov dx,offset errmsg - offset slidetop + 100h
  299. mov cx,msglen ; errmsg length
  300. mov bx,2 ; standard error device handle
  301. mov ah,40h ; write error message
  302. int 21h
  303. mov ax,4C01h ; terminate with return code
  304. int 21h
  305. handler: iret ; interrupt handler
  306. slidebot:
  307. cntl dw 0 ; count low
  308. cnth dw 0 ; count high
  309. stks dw 0 ; original SS contents
  310. stkp dw 0 ; original SP contents
  311. psp dw 0 ; PSP segment
  312. s1add dd 0 ; slide1 address
  313. rcode dw 0 ; return code
  314. useems2 db 0 ; if 0, use EMS
  315. vtabseg dw 0 ; vectab1 segment
  316. vtaboff dw 0 ; vectab1 offset
  317. errmsg2 db 'spawn error',0Dh,0Ah
  318. msglen2 EQU $-errmsg2
  319. ;
  320. ; int _xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
  321. ;
  322. PUBLIC __xspawn
  323. IFDEF LCODE
  324. __xspawn PROC far
  325. ELSE
  326. __xspawn PROC near
  327. ENDIF
  328. push bp
  329. mov bp,sp
  330. push di ; preserve register variables
  331. push si
  332. push ds
  333. IFDEF LDATA
  334. lds si,dword ptr [bp+ARG_1]
  335. ELSE
  336. mov si,word ptr [bp+ARG_1]
  337. ENDIF
  338. mov di,offset path
  339. start1: mov al,ds:[si] ; copy path string
  340. mov cs:[di],al ; to code segment
  341. inc si
  342. inc di
  343. or al,al ; null char?
  344. jnz start1 ; no, get next char
  345. IFDEF LDATA
  346. lds si,dword ptr [bp+ARG_1+4]
  347. ELSE
  348. mov si,word ptr [bp+ARG_1+2]
  349. ENDIF
  350. mov bx,si ; preserve si
  351. mov di,offset command
  352. mov cx,2 ; account for count and '\r'
  353. add cl,byte ptr ds:[bx] ; add count byte
  354. start2: mov al,ds:[bx] ; copy command
  355. mov cs:[di],al ; to code segment
  356. inc bx
  357. inc di
  358. loop start2 ; get next char
  359. inc si ; skip count byte
  360. push cs
  361. pop es
  362. mov di,offset fcb5c
  363. mov ax,2901h ; parse filename
  364. int 21h ; skip leading separators
  365. mov di,offset fcb6c
  366. mov al,1 ; parse filename
  367. int 21h ; skip leading separators
  368. IFDEF LDATA
  369. mov ax,word ptr [bp+ARG_1+8]
  370. ELSE
  371. mov ax,word ptr [bp+ARG_1+4]
  372. ENDIF
  373. mov cl,4
  374. shr ax,cl ; convert to paragraphs
  375. IFDEF LDATA
  376. mov bx,word ptr [bp+ARG_1+10]
  377. ELSE
  378. mov bx,ds
  379. ENDIF
  380. add ax,bx
  381. mov cs:[env],ax ; environment segment
  382. IFDEF LDATA
  383. lds bx,dword ptr [bp+ARG_1+12] ; vectab1
  384. ELSE
  385. mov bx,word ptr [bp+ARG_1+6] ; vectab1
  386. ENDIF
  387. mov cs:[vtabseg],ds ; vectab1 segment
  388. mov cs:[vtaboff],bx ; vectab1 offset
  389. mov cs:[stks],ss ; original SS contents
  390. mov cs:[stkp],sp ; original SP contents
  391. mov cs:[rcode],0 ; assume success
  392. IFDEF LDATA
  393. mov ax,word ptr [bp+ARG_1+16]
  394. ELSE
  395. mov ax,word ptr [bp+ARG_1+8]
  396. ENDIF
  397. or ax,ax ; do swap?
  398. jz start3 ; yes, jump
  399. jmp noswap1
  400. IFDEF LDATA
  401. start3: mov ax,word ptr [bp+ARG_1+18]
  402. ELSE
  403. start3: mov ax,word ptr [bp+ARG_1+10]
  404. ENDIF
  405. mov cs:[envlen],ax ; environment length
  406. add ax,offset slidebot - offset slidetop + 30 + 100h
  407. mov cl,4
  408. shr ax,cl ; convert to paragraphs
  409. mov cs:[newsz],ax ; new size
  410. IFDEF LDATA
  411. lds si,dword ptr [bp+ARG_1+20]
  412. ELSE
  413. mov si,word ptr [bp+ARG_1+12]
  414. ENDIF
  415. mov di,offset file
  416. mov cs:[useems2],1 ; assume don't use EMS
  417. cmp byte ptr ds:[si],0
  418. jne start4
  419. mov cs:[useems2],0 ; use EMS
  420. start4: mov al,ds:[si] ; copy file string
  421. mov cs:[di],al ; to code segment
  422. inc si
  423. inc di
  424. or al,al ; null char?
  425. jnz start4 ; no, get next char
  426. ; save fnish1 address
  427. mov word ptr cs:[f1add+2],cs
  428. mov word ptr cs:[f1add],offset fnish1
  429. ; initialize parameter block
  430. mov ax,cs:[psp] ; PSP segment
  431. mov cs:[cmd],offset command - offset slidetop + 100h
  432. mov cs:[cmd+2],ax
  433. mov cs:[fcb1],offset fcb5c - offset slidetop + 100h
  434. mov cs:[fcb1+2],ax
  435. mov cs:[fcb2],offset fcb6c - offset slidetop + 100h
  436. mov cs:[fcb2+2],ax
  437. cld ; left to right direction
  438. mov ds,ax ; PSP segment
  439. IFDEF LDATA
  440. mov dx,word ptr [bp+ARG_1+24]
  441. ELSE
  442. mov dx,word ptr [bp+ARG_1+14]
  443. ENDIF
  444. IF FHTSZ - 20
  445. cmp word ptr ds:[32h],FHTSZ ; file handle table size
  446. je start5 ; jump if OK
  447. mov cs:[rcode],5
  448. jmp short start6
  449. ENDIF
  450. start5: mov ax,cs:[newsz] ; new size
  451. cmp ax,cs:[ttlsz] ; new size < total size?
  452. jb start8 ; yes, jump
  453. mov cs:[rcode],7 ; extremely unlikely
  454. start6: cmp cs:[useems2],0
  455. jne start7 ; jump if don't use EMS
  456. jmp fnish2
  457. start7: mov bx,dx ; file handle
  458. jmp fnish6
  459. start8: cmp cs:[useems2],0
  460. jne start12 ; jump if don't use EMS
  461. mov cs:[useems],0 ; use EMS
  462. mov cs:[handle],dx ; EMS handle
  463. mov es,cs:[emsseg] ; EMS page frame segment
  464. xor bx,bx ; logical page number
  465. jmp short start11
  466. start9: sub cs:[cntl],cx
  467. sbb cs:[cnth],0
  468. call mapems
  469. or ah,ah
  470. jz start10 ; jump if map succeeded
  471. jmp fnish2
  472. start10: mov si,100h
  473. xor di,di
  474. shr cx,1 ; translate to word count
  475. rep movsw ; CF set if one byte left over
  476. adc cx,cx ; CX = 1 or 0, depending CF
  477. rep movsb ; possible final byte
  478. inc bx ; logical page number
  479. mov ax,ds
  480. add ax,1024 ; 16384 bytes
  481. mov ds,ax
  482. start11: mov cx,16384 ; assume copy full block
  483. cmp cs:[cnth],0
  484. jne start9 ; jump if more than full block
  485. cmp cs:[cntl],16384
  486. jae start9 ; jump if at least full block
  487. mov cx,cs:[cntl]
  488. cmp cx,0
  489. jne start9 ; jump if more left to copy
  490. jmp short start17
  491. start12: mov cs:[useems],1 ; don't use EMS
  492. mov bx,dx ; handle
  493. mov dx,100h ; DS:DX segment:offset buffer
  494. mov cx,65520 ; assume write full block
  495. jmp short start16
  496. start13: sub cs:[cntl],cx
  497. sbb cs:[cnth],0
  498. mov ah,40h ; write file
  499. int 21h
  500. jc start14 ; jump if error
  501. cmp ax,cx
  502. je start15 ; jump if all written
  503. start14: mov ah,3Eh ; close file
  504. int 21h
  505. mov cs:[rcode],5
  506. jmp fnish7
  507. start15: mov ax,ds
  508. add ax,4095 ; 65520 bytes
  509. mov ds,ax
  510. start16: cmp cs:[cnth],0
  511. jne start13 ; jump if more than full block
  512. cmp cs:[cntl],65520
  513. jae start13 ; jump if at least full block
  514. mov cx,cs:[cntl]
  515. cmp cx,0
  516. jne start13 ; jump if more left to write
  517. mov ah,3Eh ; close file
  518. int 21h
  519. IF FHTSZ - 20
  520. ; save the file handle table in the kernel
  521. mov es,cs:[psp] ; PSP segment
  522. mov ds,es:[36h] ; file handle table segment
  523. mov si,es:[34h] ; file handle table offset
  524. push cs
  525. pop es
  526. mov di,offset fhtsv ; file handle table save
  527. mov cx,FHTSZ ; file handle table size
  528. rep movsb
  529. ENDIF
  530. start17: mov cx,cs
  531. mov dx,offset handler ; interrupt handler offset
  532. call safevect ; set vectors in vectab1
  533. ; time to copy the kernel
  534. mov es,cs:[psp] ; PSP segment
  535. mov di,100h
  536. mov ds,cx ; DS = CS
  537. mov si,offset slidetop
  538. mov cx,offset slidebot - offset slidetop
  539. shr cx,1 ; translate to word count
  540. rep movsw ; CF set if one byte left over
  541. adc cx,cx ; CX = 1 or 0, depending CF
  542. rep movsb ; possible final byte
  543. mov word ptr cs:[s1add+2],es ; PSP segment
  544. index = offset slide1 - offset slidetop + 100h
  545. mov word ptr cs:[s1add],index ; slide1 offset
  546. mov cx,es ; PSP segment
  547. index = offset handler - offset slidetop + 100h
  548. mov dx,index ; interrupt handler offset
  549. call safevect ; set vectors in vectab1
  550. jmp dword ptr cs:[s1add] ; jump to the kernel
  551. ; If all goes well, this is where we come back to from the kernel.
  552. fnish1: mov cs:[rcode],ax ; return code
  553. cli ; restore original stack
  554. mov ss,cs:[stks]
  555. mov sp,cs:[stkp]
  556. sti
  557. push ds ; maybe EMS page frame segment
  558. push dx ; maybe EMS handle
  559. push bx ; maybe swap file handle
  560. mov cx,cs
  561. mov dx,offset handler ; interrupt handler offset
  562. call safevect ; set vectors in vectab1
  563. pop bx
  564. pop dx
  565. pop ds
  566. cmp cs:[useems2],0
  567. jne fnish4 ; jump if don't use EMS
  568. ; DS = EMS page frame segment
  569. ; DX = EMS handle
  570. mov cx,offset slidebot - offset slidetop
  571. mov es,cs:[psp] ; PSP segment
  572. mov di,100h
  573. xor si,si
  574. xor bx,bx ; logical page number
  575. call mapems
  576. or ah,ah
  577. jnz fnish3 ; jump if map failed
  578. shr cx,1 ; translate to word count
  579. rep movsw ; CF set if one byte left over
  580. adc cx,cx ; CX = 1 or 0, depending CF
  581. rep movsb ; possible final byte
  582. fnish2: mov ah,45h ; release handle and memory
  583. int 67h
  584. cmp ah,82h ; memory manager busy?
  585. je fnish2 ; jump if busy
  586. jmp short fnish7
  587. fnish3: mov ah,45h ; release handle and memory
  588. int 67h
  589. cmp ah,82h ; memory manager busy?
  590. je fnish3 ; jump if busy
  591. jmp short fnish5 ; exit
  592. ; BX = swap file handle
  593. fnish4: xor cx,cx ; offset 0
  594. xor dx,dx ; offset 0
  595. mov ax,4200h ; move file pointer
  596. int 21h ; from beginning of file
  597. mov cx,offset slidebot - offset slidetop
  598. mov ds,cs:[psp] ; PSP segment
  599. mov dx,100h
  600. mov ah,3Fh ; read file
  601. int 21h
  602. jc fnish5 ; exit if error
  603. cmp ax,cx
  604. je fnish6
  605. fnish5: push cs
  606. pop ds
  607. mov dx,offset errmsg2
  608. mov cx,msglen2 ; errmsg2 length
  609. mov bx,2 ; standard error device handle
  610. mov ah,40h ; write error message
  611. int 21h
  612. mov ax,4C01h ; terminate with return code
  613. int 21h
  614. fnish6: mov ah,3Eh ; close file
  615. int 21h
  616. push cs
  617. pop ds
  618. mov dx,offset file
  619. mov ah,41h ; delete file
  620. int 21h
  621. fnish7: pop ds
  622. pop si ; restore register variables
  623. pop di
  624. pop bp
  625. mov ax,cs:[rcode] ; return code
  626. or ax,ax
  627. jz fnish11
  628. push ax
  629. mov ax,3000h ; get DOS version number
  630. int 21h
  631. cmp al,3 ; major version number
  632. pop ax
  633. jb fnish8
  634. cmp al,34 ; unknown error - 3.0
  635. jae fnish9
  636. cmp al,32 ; sharing violation
  637. jb fnish8
  638. mov al,5 ; access denied
  639. jmp short fnish10
  640. fnish8: cmp al,19 ; unknown error - 2.0
  641. jbe fnish10
  642. fnish9: mov al,19 ; unknown error - 2.0
  643. fnish10: xor ah,ah
  644. fnish11: ret
  645. ; If we are not swapping, we jump here.
  646. noswap1: mov ax,cs
  647. ; initialize parameter block
  648. mov bx,cs:[env]
  649. mov cs:[environ],bx
  650. mov cs:[cmd],offset command
  651. mov cs:[cmd+2],ax
  652. mov cs:[fcb1],offset fcb5c
  653. mov cs:[fcb1+2],ax
  654. mov cs:[fcb2],offset fcb6c
  655. mov cs:[fcb2+2],ax
  656. ; save 4 bytes destroyed by DOS 2.0 at DS:2Eh
  657. mov si,cs:[2Eh]
  658. mov word ptr cs:[save],si
  659. mov si,cs:[30h]
  660. mov word ptr cs:[save+2],si
  661. mov cx,cs
  662. mov dx,offset handler ; interrupt handler offset
  663. call safevect ; set vectors in vectab1
  664. mov es,cx ; ES = CS
  665. mov bx,offset parmblk
  666. mov ds,cx ; DS = CS
  667. mov dx,offset path
  668. mov ax,4B00h ; load and execute program
  669. int 21h
  670. jnc noswap2 ; jump if no error
  671. mov cs:[rcode],ax ; return code
  672. noswap2: cli ; restore original stack
  673. mov ss,cs:[stks]
  674. mov sp,cs:[stkp]
  675. sti
  676. ; restore 4 bytes destroyed by DOS 2.0 at DS:2Eh
  677. mov si,word ptr cs:[save]
  678. mov cs:[2Eh],si
  679. mov si,word ptr cs:[save+2]
  680. mov cs:[30h],si
  681. jmp fnish7
  682. __xspawn ENDP
  683. mapems PROC near
  684. ; DX = handle
  685. ; BX = logical page number
  686. xor al,al ; physical page number
  687. map1: mov ah,44h ; map memory
  688. int 67h
  689. cmp ah,82h ; memory manager busy?
  690. je map1 ; jump if busy
  691. ret
  692. mapems ENDP
  693. setvectsub PROC near
  694. ; ES = vector table segment
  695. ; BX = vector table offset
  696. mov ah,25h ; set interrupt vector
  697. setvectsub1: mov al,es:[bx+flag] ; 0-CURRENT,1-IRET,2-free,3-end
  698. cmp al,3 ; is it the end?
  699. je setvectsub3 ; yes, jump
  700. cmp al,2 ; is it free?
  701. je setvectsub2 ; yes, jump
  702. mov al,es:[bx+number] ; vector number
  703. mov ds,es:[bx+vseg] ; vector segment
  704. mov dx,es:[bx+voff] ; vector offset
  705. int 21h ; set interrupt vector
  706. setvectsub2: add bx,6 ; size of vector structure
  707. jmp setvectsub1 ; next
  708. setvectsub3: ret
  709. setvectsub ENDP
  710. safevect PROC near
  711. ; CX = handler segment
  712. ; DX = handler offset
  713. mov es,cs:[vtabseg] ; vectab1 segment
  714. mov bx,cs:[vtaboff] ; vectab1 offset
  715. safevect1: mov al,es:[bx+flag] ; 0-CURRENT,1-IRET,2-free,3-end
  716. cmp al,3 ; is it the end?
  717. je safevect3 ; yes, jump
  718. cmp al,1 ; is it IRET?
  719. jne safevect2 ; no, jump
  720. mov es:[bx+vseg],cx ; handler segment
  721. mov es:[bx+voff],dx ; handler offset
  722. safevect2: add bx,6 ; size of vector structure
  723. jmp safevect1 ; next
  724. safevect3: mov bx,cs:[vtaboff] ; vectab1 offset
  725. call setvectsub
  726. ret
  727. safevect ENDP
  728. ;
  729. ; int _xsize( unsigned int, long *, long * );
  730. ;
  731. PUBLIC __xsize
  732. IFDEF LCODE
  733. __xsize PROC far
  734. ELSE
  735. __xsize PROC near
  736. ENDIF
  737. push bp
  738. mov bp,sp
  739. push di ; preserve register variables
  740. push si
  741. push ds
  742. mov cs:[last],0 ; assume last block swap
  743. mov bx,word ptr [bp+ARG_1] ; PSP segment
  744. mov cs:[psp],bx
  745. mov dx,bx
  746. dec bx ; program arena header
  747. size1: mov es,bx ; current arena header
  748. mov ax,es:[own]
  749. or ax,ax ; is it free?
  750. jz size2 ; yes, count it
  751. cmp ax,dx ; do we own it?
  752. jne size4 ; no, jump
  753. mov cx,bx ; last owned block
  754. size2: inc bx
  755. add bx,es:[siz] ; block size
  756. jc size3 ; carry, arena is trashed
  757. mov al,es:[sig] ; get arena signature
  758. cmp al,'M' ; are we at end of memory?
  759. je size1 ; no, jump
  760. cmp al,'Z'
  761. je size5
  762. size3: mov bx,-1 ; request maximum memory
  763. mov ah,48h ; allocate memory block
  764. int 21h
  765. mov cs:[rcode],7
  766. jmp fnish7
  767. size4: mov cs:[last],1 ; not last block swap
  768. size5: sub bx,dx ; subtract PSP segment
  769. mov ax,cx ; last owned block
  770. mov es,cx
  771. inc ax
  772. add ax,es:[siz] ; block size
  773. sub ax,dx ; subtract PSP segment
  774. mov cs:[parsz],ax ; parent size
  775. sub ax,10h ; subtract PSP size
  776. xor dx,dx ; convert to bytes
  777. mov cx,4
  778. size6: shl ax,1
  779. rcl dx,1
  780. loop size6
  781. IFDEF LDATA
  782. lds si,dword ptr [bp+ARG_1+2]
  783. ELSE
  784. mov si,word ptr [bp+ARG_1+2]
  785. ENDIF
  786. mov ds:[si],ax ; swap size requirement
  787. mov ds:[si+2],dx
  788. mov cs:[cntl],ax ; count low
  789. mov cs:[cnth],dx ; count high
  790. mov cx,offset slidebot - offset slidetop
  791. sub ax,cx
  792. sbb dx,0
  793. mov cs:[cntsvl],ax ; count save low
  794. mov cs:[cntsvh],dx ; count save high
  795. mov cs:[ttlsz],bx ; total size
  796. xor dx,dx ; convert to bytes
  797. mov cx,4
  798. size7: shl bx,1
  799. rcl dx,1
  800. loop size7
  801. IFDEF LDATA
  802. lds si,dword ptr [bp+ARG_1+6]
  803. ELSE
  804. mov si,word ptr [bp+ARG_1+4]
  805. ENDIF
  806. mov ds:[si],bx ; parent and free memory
  807. mov ds:[si+2],dx
  808. pop ds
  809. pop si ; restore register variables
  810. pop di
  811. pop bp
  812. xor ax,ax
  813. ret
  814. __xsize ENDP
  815. ;
  816. ; int _chkems( char *, int * );
  817. ;
  818. PUBLIC __chkems
  819. IFDEF LCODE
  820. __chkems PROC far
  821. ELSE
  822. __chkems PROC near
  823. ENDIF
  824. push bp
  825. mov bp,sp
  826. ; determine whether expanded memory is available
  827. IFDEF LDATA
  828. push ds
  829. lds dx,dword ptr [bp+ARG_1] ; EMM device driver name
  830. ELSE
  831. mov dx,word ptr [bp+ARG_1] ; EMM device driver name
  832. ENDIF
  833. mov ax,3D00h ; open file read only
  834. int 21h
  835. IFDEF LDATA
  836. pop ds
  837. ENDIF
  838. jc check2 ; expanded memory unavailable
  839. ; determine whether we opened the EMM device driver or a file
  840. mov bx,ax ; handle
  841. mov ax,4400h ; IOCTL - get device info
  842. int 21h
  843. jc check1 ; expanded memory unavailable
  844. test dx,80h ; test bit 7
  845. jz check1 ; expanded memory unavailable
  846. mov ax,4407h ; IOCTL - get output status
  847. int 21h
  848. jc check1 ; expanded memory unavailable
  849. or al,al
  850. jz check1 ; expanded memory unavailable
  851. ; close EMM device driver to reclaim handle
  852. mov ah,3Eh ; close file
  853. int 21h
  854. ; determine whether the EMM is functional
  855. mov ah,40h ; get manager status
  856. int 67h
  857. or ah,ah
  858. jnz check2 ; expanded memory unavailable
  859. ; check EMM version
  860. mov ah,46h ; get EMM version
  861. int 67h
  862. or ah,ah
  863. jnz check2 ; expanded memory unavailable
  864. cmp al,32h ; version 3.2
  865. jb check2 ; expanded memory unavailable
  866. ; get page frame segment
  867. mov ah,41h ; get page frame segment
  868. int 67h
  869. or ah,ah
  870. jnz check2 ; expanded memory unavailable
  871. mov cs:[emsseg],bx ; segment
  872. ; get size of page map information
  873. mov ax,4E03h ; get size of page map info
  874. int 67h
  875. or ah,ah
  876. jnz check2 ; expanded memory unavailable
  877. IFDEF LDATA
  878. les bx,dword ptr [bp+ARG_1+4] ; mapsize address
  879. mov es:[bx],ax
  880. ELSE
  881. mov bx,word ptr [bp+ARG_1+2] ; mapsize address
  882. mov ds:[bx],ax
  883. ENDIF
  884. xor ax,ax ; expanded memory available
  885. pop bp
  886. ret
  887. ; close EMM device driver or file to reclaim handle
  888. check1: mov ah,3Eh ; close file
  889. int 21h
  890. check2: mov ax,1 ; expanded memory unavailable
  891. pop bp
  892. ret
  893. __chkems ENDP
  894. ;
  895. ; int _savemap( char * );
  896. ;
  897. PUBLIC __savemap
  898. IFDEF LCODE
  899. __savemap PROC far
  900. ELSE
  901. __savemap PROC near
  902. ENDIF
  903. push bp
  904. mov bp,sp
  905. push di ; preserve register variable
  906. IFDEF LDATA
  907. les di,dword ptr [bp+ARG_1] ; buffer address
  908. ELSE
  909. mov di,word ptr [bp+ARG_1] ; buffer address
  910. push ds
  911. pop es
  912. ENDIF
  913. mov ax,4E00h ; save page map
  914. int 67h
  915. pop di ; restore register variable
  916. pop bp
  917. ret
  918. __savemap ENDP
  919. ;
  920. ; int _restmap( char * );
  921. ;
  922. PUBLIC __restmap
  923. IFDEF LCODE
  924. __restmap PROC far
  925. ELSE
  926. __restmap PROC near
  927. ENDIF
  928. push bp
  929. mov bp,sp
  930. push ds
  931. push si ; preserve register variable
  932. IFDEF LDATA
  933. lds si,dword ptr [bp+ARG_1] ; buffer address
  934. ELSE
  935. mov si,word ptr [bp+ARG_1] ; buffer address
  936. ENDIF
  937. mov ax,4E01h ; restore page map
  938. int 67h
  939. xor al,al
  940. pop si ; restore register variable
  941. pop ds
  942. pop bp
  943. ret
  944. __restmap ENDP
  945. ;
  946. ; int _getems( int, int * );
  947. ;
  948. PUBLIC __getems
  949. IFDEF LCODE
  950. __getems PROC far
  951. ELSE
  952. __getems PROC near
  953. ENDIF
  954. push bp
  955. mov bp,sp
  956. mov bx,word ptr [bp+ARG_1] ; number of pages
  957. mov ah,43h ; get handle and allocate
  958. ; memory
  959. int 67h
  960. IFDEF LDATA
  961. les bx,dword ptr [bp+ARG_1+2] ; handle address
  962. mov es:[bx],dx ; handle
  963. ELSE
  964. mov bx,word ptr [bp+ARG_1+2] ; handle address
  965. mov ds:[bx],dx ; handle
  966. ENDIF
  967. xor al,al
  968. pop bp
  969. ret
  970. __getems ENDP
  971. ;
  972. ; int _dskspace( int, unsigned int *, unsigned int * );
  973. ;
  974. PUBLIC __dskspace
  975. IFDEF LCODE
  976. __dskspace PROC far
  977. ELSE
  978. __dskspace PROC near
  979. ENDIF
  980. push bp
  981. mov bp,sp
  982. push di ; preserve register variable
  983. mov ah,36h ; get free disk space
  984. mov dl,byte ptr [bp+ARG_1] ; drive code (0=default, 1=A)
  985. int 21h
  986. cmp ax,0FFFFh ; was drive invalid?
  987. je space1 ; yes, jump
  988. mul cx ; bytes per sector *
  989. ; sectors per cluster
  990. IFDEF LDATA
  991. les di,dword ptr [bp+ARG_1+2]
  992. mov es:[di],ax ; bytes per cluster
  993. ELSE
  994. mov di,word ptr [bp+ARG_1+2]
  995. mov ds:[di],ax ; bytes per cluster
  996. ENDIF
  997. IFDEF LDATA
  998. les di,dword ptr [bp+ARG_1+6]
  999. mov es:[di],bx ; number of available clusters
  1000. ELSE
  1001. mov di,word ptr [bp+ARG_1+4]
  1002. mov ds:[di],bx ; number of available clusters
  1003. ENDIF
  1004. xor ax,ax
  1005. space1: pop di ; restore register variable
  1006. pop bp
  1007. ret
  1008. __dskspace ENDP
  1009. ;
  1010. ; int _getrc( void );
  1011. ;
  1012. PUBLIC __getrc
  1013. IFDEF LCODE
  1014. __getrc PROC far
  1015. ELSE
  1016. __getrc PROC near
  1017. ENDIF
  1018. mov ah,4Dh ; get child return code
  1019. int 21h
  1020. ret
  1021. __getrc ENDP
  1022. ;
  1023. ; int _create( char *, int * );
  1024. ;
  1025. PUBLIC __create
  1026. IFDEF LCODE
  1027. __create PROC far
  1028. ELSE
  1029. __create PROC near
  1030. ENDIF
  1031. push bp
  1032. mov bp,sp
  1033. IFDEF LDATA
  1034. push ds
  1035. ENDIF
  1036. mov ax,3000h ; get DOS version number
  1037. int 21h
  1038. IFDEF LDATA
  1039. lds dx,dword ptr [bp+ARG_1] ; file
  1040. ELSE
  1041. mov dx,word ptr [bp+ARG_1] ; file
  1042. ENDIF
  1043. xor cx,cx ; normal attribute
  1044. mov ah,5Bh ; create new file
  1045. cmp al,3 ; major version number
  1046. jae create1
  1047. mov ah,3Ch ; create file
  1048. create1: int 21h
  1049. jc create2
  1050. IFDEF LDATA
  1051. lds bx,dword ptr [bp+ARG_1+4] ; handle address
  1052. ELSE
  1053. mov bx,word ptr [bp+ARG_1+2] ; handle address
  1054. ENDIF
  1055. mov ds:[bx],ax
  1056. xor ax,ax
  1057. create2:
  1058. IFDEF LDATA
  1059. pop ds
  1060. ENDIF
  1061. pop bp
  1062. ret
  1063. __create ENDP
  1064. ;
  1065. ; int _getcd( int, char * );
  1066. ;
  1067. PUBLIC __getcd
  1068. IFDEF LCODE
  1069. __getcd PROC far
  1070. ELSE
  1071. __getcd PROC near
  1072. ENDIF
  1073. push bp
  1074. mov bp,sp
  1075. push si ; preserve register variable
  1076. IFDEF LDATA
  1077. push ds
  1078. ENDIF
  1079. mov dl,byte ptr [bp+ARG_1] ; drive code (0=default, 1=A)
  1080. IFDEF LDATA
  1081. lds si,dword ptr [bp+ARG_1+2] ; buffer
  1082. ELSE
  1083. mov si,word ptr [bp+ARG_1+2] ; buffer
  1084. ENDIF
  1085. mov ah,47h ; get current directory
  1086. int 21h
  1087. jc getcd1
  1088. xor ax,ax
  1089. getcd1:
  1090. IFDEF LDATA
  1091. pop ds
  1092. ENDIF
  1093. pop si ; restore register variable
  1094. pop bp
  1095. ret
  1096. __getcd ENDP
  1097. ;
  1098. ; int _getdrv( void );
  1099. ;
  1100. PUBLIC __getdrv
  1101. IFDEF LCODE
  1102. __getdrv PROC far
  1103. ELSE
  1104. __getdrv PROC near
  1105. ENDIF
  1106. mov ah,19h ; get default disk drive
  1107. int 21h
  1108. xor ah,ah
  1109. ; AX = drive (0 = A, 1 = B, etc.)
  1110. ret
  1111. __getdrv ENDP
  1112. ;
  1113. ; void _getvect( int, unsigned int *, unsigned int * );
  1114. ;
  1115. PUBLIC __getvect
  1116. IFDEF LCODE
  1117. __getvect PROC far
  1118. ELSE
  1119. __getvect PROC near
  1120. ENDIF
  1121. push bp
  1122. mov bp,sp
  1123. push ds
  1124. push si ; preserve register variable
  1125. mov ah,35h ; get interrupt vector
  1126. mov al,byte ptr [bp+ARG_1] ; interrupt number
  1127. int 21h
  1128. IFDEF LDATA
  1129. lds si,dword ptr [bp+ARG_1+2]
  1130. ELSE
  1131. mov si,word ptr [bp+ARG_1+2]
  1132. ENDIF
  1133. mov ds:[si],es ; segment
  1134. IFDEF LDATA
  1135. lds si,dword ptr [bp+ARG_1+6]
  1136. ELSE
  1137. mov si,word ptr [bp+ARG_1+4]
  1138. ENDIF
  1139. mov ds:[si],bx ; offset
  1140. pop si ; restore register variable
  1141. pop ds
  1142. pop bp
  1143. ret
  1144. __getvect ENDP
  1145. ;
  1146. ; void _setvect( VECTOR * );
  1147. ;
  1148. PUBLIC __setvect
  1149. IFDEF LCODE
  1150. __setvect PROC far
  1151. ELSE
  1152. __setvect PROC near
  1153. ENDIF
  1154. push bp
  1155. mov bp,sp
  1156. push ds ; modified in setvectsub
  1157. IFDEF LDATA
  1158. les bx,dword ptr [bp+ARG_1] ; vector table
  1159. ELSE
  1160. mov bx,word ptr [bp+ARG_1] ; vector table
  1161. push ds
  1162. pop es
  1163. ENDIF
  1164. call setvectsub
  1165. pop ds
  1166. pop bp
  1167. ret
  1168. __setvect ENDP
  1169. ;
  1170. ; void _setdrvcd(int drive, char * string);
  1171. ;
  1172. PUBLIC __setdrvcd
  1173. IFDEF LCODE
  1174. __setdrvcd PROC far
  1175. ELSE
  1176. __setdrvcd PROC near
  1177. ENDIF
  1178. push bp
  1179. mov bp,sp
  1180. IFDEF LDATA
  1181. push ds
  1182. ENDIF
  1183. mov dl,byte ptr [bp+ARG_1] ; drive code (0=A, 1=B)
  1184. mov ah,0eh
  1185. int 21h
  1186. IFDEF LDATA
  1187. lds dx,dword ptr [bp+ARG_1+2] ; buffer
  1188. ELSE
  1189. mov dx,word ptr [bp+ARG_1+2] ; buffer
  1190. ENDIF
  1191. mov ah,3bh ; set current directory
  1192. int 21h
  1193. IFDEF LDATA
  1194. pop ds
  1195. ENDIF
  1196. pop bp
  1197. ret
  1198. __setdrvcd ENDP
  1199. _TEXT ENDS
  1200. END