home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR13 / OS2ASM.ZIP / C.ASM < prev    next >
Assembly Source File  |  1991-08-10  |  27KB  |  1,040 lines

  1. ; Copyright (C) 1985-1991 by Walter Bright
  2. ; All rights reserved.
  3. ; Written by Joe Huffman
  4. ; Sandpoint, ID  83864-9445
  5. ; Modified by Joe Huffman September 17, 1990
  6. ; C startup code for SCO UNIX System V/386 version 3.2.0 and Phar Lap
  7. ; DOS extender
  8.  
  9. include macros.asm
  10.  
  11. ifndef M_UNIX
  12. ifdef M_XENIX
  13. M_UNIX    equ    1    ;No differences in this module between XENIX and UNIX.
  14. endif
  15. endif
  16.  
  17. ifdef DOS386
  18. include x386mac.asm
  19.     extrn __dos:word, __8087:dword, __stack:dword
  20.     extrn __DOS386_version:dword,__DOS386_environ:dword
  21.     extrn    _calloc:near, _realloc:near, _malloc:near
  22. endif
  23.  
  24. ifdef X386
  25. includelib zlx.lod        ;stub loader
  26. include x386mac.asm
  27.     extrn    _calloc:near, _realloc:near, _malloc:near, __stack:dword, __psp:dword
  28.     extrn    __osmajor:byte, __osminor:byte,__x386_coproc_init:near
  29.     extrn    __x386_start:near
  30. endif
  31.  
  32. ifdef M_UNIX
  33.     extrn __environ:dword
  34. endif
  35.     extrn    _exit:near, __exit:near
  36.     extrn __argc:dword,__argv:dword,__envptr:dword
  37.     extrn __cinit:near, _main:near
  38.  
  39.     public  __acrtused, __heapbottom, __pastdata, __x386_break
  40.     public  __chkstack, __chkstk, __x386_zero_base_selector
  41.     public    __exe_type
  42.  
  43. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  44. ; Form the start of DGROUP.
  45. ; Modified by Joe Huffman June 19, 1990
  46. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  47.  
  48. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  49. ; Initialized data globals
  50. CR    =    13
  51. LF    =    10
  52.  
  53. ifdef X386  ;Define order of segments
  54. begdata_16
  55. ;16 bit data segment for real mode and priv level 0 activities
  56.         dw      _TEXT           ;first word in extender code, used by loader
  57.         extrn __x386_esp3:dword,__x386_esp0:dword
  58.         extrn __x386_stack_32_des:word
  59. enddata_16
  60.  
  61. begcode_16
  62. __start:
  63.         jmp     __x386_start    ;jump to 16 bit initialization
  64. endcode_16
  65.  
  66. _TEXT    segment para public 'CODE' ;must be paragraph aligned here
  67. endcode
  68.  
  69.     begdata
  70.  
  71. extrn __x386_mk_protected_ptr:dword
  72.  
  73.         db      'Zortech C 3.0b1 library, Copyright (C) 1988-1991 ',CR,LF
  74.         db      'X386',CR,LF
  75.         db      'written by Walter Bright, Joe Huffman and Doug Huffman',0
  76.  
  77. public  __data_bottom,__x386_version
  78.                 ;Used for NULL pointer detection.  No one has any business
  79.                 ;accessing below this point.
  80. __data_bottom   label byte
  81. null_code_ptr           db    CR,LF,'NULL code pointer called',CR,LF,'$'
  82. __x386_disp_base        dw      0               ;storage for _dispbase
  83. __stack_bottom  label byte                      ;for pharlap compatibility
  84. __x386_version          dw      300h            ;extender vesion #
  85.  
  86. DGROUP  group   _TEXT,HUGE_BSS
  87.  
  88.         extrn __x386_data_16_alias:word,__stack:dword
  89.         public __x386_set_ss_lim
  90.         __x386_set_ss_lim       dd      offset no_dpmi_set_ss_lim
  91.  
  92. else    ;X386
  93.  
  94. ifdef DOS386
  95.     begcode_16
  96.     endcode_16
  97. endif ;DOS386
  98.  
  99.     begdata
  100. endif   ;X386
  101.  
  102.     c_extrn errno,dword
  103.  
  104. ifdef DOS386
  105.     db    'Zortech C 3.0r2 DOS386 library, Copyright (C) 1988-1991 ',CR,LF
  106. else
  107.     db    'Zortech C 3.0r2 UNIX library, Copyright (C) 1988-1991 ',LF
  108. endif
  109.     db    'written by Walter Bright and Joe Huffman',0
  110.  
  111.     align    4
  112.  
  113. __pastdata    dd    ?    ;address of 1 past data segment
  114. __heapbottom    dd    ?    ;lowest address in heap (used to detect
  115.                 ;free() errors and stack wrap)
  116.  
  117. __acrtused    equ    1234    ;cause linker to pull in this module.
  118.  
  119. __x386_break    dd    offset DGROUP:__stack_bottom
  120. ;used in alloca()
  121.  
  122. ;Set exe file type
  123. ifdef X386
  124. __exe_type    dw    EXE_DOSX
  125. else
  126. ifdef DOS386
  127. __exe_type    dw    EXE_PHAR386
  128. else
  129. __exe_type    dw    EXE_SCOUNIX
  130. endif
  131. endif
  132.  
  133. __x386_zero_base_selector       dw      34h     ;writable segment, base = 0
  134. ifdef DOS386
  135. public __x386_version
  136. __x386_version                  dw      0       ;zero for pharlap
  137. endif
  138.  
  139. ifndef M_UNIX
  140. ovrflw    db    CR,LF,'Stack Overflow',CR,LF,'$'
  141. nomem    db    CR,LF,'Not enough memory',CR,LF,'$'
  142. badcmd    db    CR,LF,'Max of 128 args allowed',CR,LF,'$'
  143. badstk    db    CR,LF,'Bad stack size parameter',CR,LF,'$'
  144. ARGMAX    =    128    ;max # of command line args
  145. endif
  146.  
  147.     enddata
  148.  
  149. ifdef DOS386
  150.  
  151. STACK_MIN_SIZE    equ    1024
  152. STACK  segment
  153.  
  154.     public    __stack_bottom
  155. __stack_bottom    dd    66BB55AAh    ;Check value.
  156.         db    (STACK_MIN_SIZE-4) dup(?) ;Start up with minimum size.
  157. STACK  ends
  158.  
  159. endif
  160.  
  161. _TEXT    segment para public 'CODE'
  162.     assume DS:DGROUP, ES:DGROUP, CS:_TEXT
  163.  
  164. ifdef X386
  165. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  166. ;This is the very beginning of the 32 bit code segment.
  167. ;It must be paragraph aligned so that the offset of the first instruction
  168. ;will be zero.
  169. ;
  170. ;Exit with an error message if this is ever exectuted.
  171. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  172.     mov    edx,offset DGROUP:null_code_ptr
  173.     jmp    fatmsg
  174. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  175. ;This is the location where 16 bit code transfers control to when 
  176. ;first entering 32 bit code.  SS and ESP are set up when arriving here.  DS 
  177. ;will = ES = __x386_data_32, GS = __x386_seg_env, FS = __x386_seg_psp.  
  178. ;__pastdata and __heapbottom are intialized prior to this code obtaining 
  179. ;control.
  180. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  181.  
  182. public  __x386_init
  183. __x386_init:
  184.     mov    EDI,offset DGROUP:_BSS    ;Initialize BSS to zero. 
  185.     mov    ECX,offset DGROUP:EEND 
  186.     sub    ECX,EDI 
  187.     clr    EAX 
  188.     shr    ECX,2 
  189.     rep    stosd 
  190.  
  191.     mov    __psp,FS
  192.     call    get_stack    ;FS has selector for PSP.
  193.     mov    EAX,ESP        ;Check for enough room for stack.
  194.     sub    EAX,__stack
  195.  
  196.     mov    EDX,offset DGROUP:badstk
  197.     jc    fatmsg        ;Is the stack value too big?
  198.     cmp    EAX,__pastdata
  199.     jl    fatmsg
  200.  
  201.     call    args_setup
  202.     push    GS
  203.     pop    ES
  204.     call    env_malloc    ;ES:0 points to the start of the environment
  205.  
  206.     clr    EAX
  207.     mov    FS,AX        ;Makes switches to/from real mode faster.
  208.     mov    GS,AX
  209.  
  210.     push    ds
  211.     pop    es
  212.  
  213.     mov    AX,3000h
  214.     bdos
  215.     mov    __osmajor,AL
  216.     mov    __osminor,AH
  217.  
  218.     call    __x386_coproc_init
  219. else ;X386
  220.  
  221. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  222. ; Program entry point.  Under UNIX it must be named __start for the
  223. ; linker to make this the entry point.  The end 'label'
  224. ; directive is ignored.  If __start is not found then _main is
  225. ; used.
  226. ; Modified by Joe Huffman January 13, 1991
  227. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  228.  
  229.     public    __start
  230. __start:
  231. endif ;X386
  232.  
  233.     clr    EBP        ;so debuggers can find last stack frame
  234.     push    EBP
  235.     mov    EBP,ESP
  236.  
  237. ifdef DOS386
  238.     call    dos386_setup
  239.     mov    EBP,ESP        ;stack was changed in dos386_set_ds.
  240. endif
  241.  
  242.  
  243. ifdef M_UNIX
  244. if OMF
  245.     mov    ECX,offset DGROUP:EEND
  246. else
  247.     lea    ECX,_end    ;This symbol is defined by the linker.
  248.                 ;Next available address after .bss
  249. endif
  250.     mov    __heapbottom,ECX
  251.     mov    __pastdata,ECX
  252.  
  253. ;;;;;;;;;;;;;;;;;;;;;;;;;
  254. ;Set up __argc and argv
  255. ;;;;;;;;;;;;;;;;;;;;;;;;;
  256.     mov    EAX,4[ebp]    ;argc
  257.     mov    __argc,EAX
  258.     lea    ECX,[EBP + SIZEPTR * EAX + 12]          ;Start of environment.
  259.     mov    __environ,ECX
  260.     push    ECX        ;environ in preparation for calling main().
  261.     mov    ECX,[ECX]
  262.     mov    __envptr,ECX    ;_envptr for comp with DOS.
  263.     lea    ECX,[EBP + 8]    ;argv
  264.     mov    __argv,ECX
  265. endif ;M_UNIX
  266.     call    __cinit        ;perform static constructors
  267.     push    __argv
  268.     push    __argc
  269.     call    _main        ;call C main(__argc,__argv, __environ)
  270.     push    EAX        ;save exit status for exit
  271.     call    _exit        ;return to OS
  272.     hlt            ;Should never reach here.
  273.  
  274. ifdef DOS386
  275.  
  276. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  277. ; Determine if we have and which version of 8087 we have installed.
  278. dos386_setup    proc    near
  279.     push    EBP
  280.     mov    EBP,ESP
  281.  
  282.     sub    ESP,512
  283.     mov    EBX,ESP        ;Pointers to buffer areas.
  284.     sub    ESP,256
  285.     mov    ECX,ESP
  286.  
  287.     mov    EAX,02526h    ;Get configuration information.
  288.     bdos
  289.  
  290.     mov    EAX,20h[ebx]    ;Get coprocesser flag.
  291.  
  292.     sub    EAX,4        ;4 == None, 6 = 287, 7 = 387
  293.     mov    __8087,EAX
  294.     jz    short no_87
  295.     finit            ;initialize 80x87
  296.     fstcw    [ESP]
  297.     fwait
  298.     or    word ptr [ESP],01000h    ;turn on affine infinity bit
  299.     fldcw    [ESP]
  300. no_87:
  301.     mov    ESP,EBP
  302.     mov    EBX,'PHAR'    ;To get Phar Lap version too.
  303.     bdos    30h
  304.     mov    __dos,AX
  305.     mov    __DOS386_version,EBX
  306.     mov    __DOS386_environ,ECX
  307.  
  308.     call    dos386_set_bss
  309.     mov    AX,SEG_PSP
  310.     mov    FS,AX
  311.     call    get_stack    ;Requires FS == PSP selector.
  312.     call    dos386_set_ds
  313.     call    args_setup    ;Requires FG == PSP selector.
  314.  
  315. if ESeqDS
  316.     push    ES
  317. endif
  318.     mov    EAX,SEG_ENV
  319.     mov    ES,AX
  320.     call    env_malloc
  321. if ESeqDS
  322.     pop    ES
  323. endif
  324.     pop    EBP
  325.     ret
  326. dos386_setup    endp
  327.  
  328. ;;;;;;;;;;;;;;;;;;;;;;;;;
  329. ; Set BSS to 0.  Destroys EDI.
  330. ; September 12, 1990
  331. ;;;;;;;;;;;;;;;;;;;;;;;;;
  332. dos386_set_bss    proc    near
  333.     mov    EDI,offset DGROUP:_BSS
  334.     mov    ECX,offset DGROUP:EEND
  335.     sub    ECX,EDI        ;Number of bytes to clear.
  336.     clr    EAX
  337.     shr    ECX,2        ;Number of dwords
  338.     rep    stosd        ;Always on dword boundaries.
  339.     ret
  340. dos386_set_bss    endp
  341.  
  342. ;;;;;;;;;;;;;;;;;;;;;;;;;
  343. ; Shrink the data segment to the minimum required.  Set Stack to proper size.
  344. ; Set up the pointers to the heapbottom and pastdata.
  345. ; September 11, 1990
  346. ;;;;;;;;;;;;;;;;;;;;;;;;;
  347. dos386_set_ds    proc    near
  348.     push    EBP
  349.     mov    EBP,ESP
  350.     mov    eax,STACK_MIN_SIZE
  351.     cmp    eax,__stack
  352.     jge    short set_seg1    ;eax = max(STACK_MIN_SIZE,__stack)
  353.     mov    eax,__stack
  354.  
  355. set_seg1:
  356.     mov    __stack,eax    ;Actual stack size.
  357.     add    eax,offset DGROUP:__stack_bottom + SIZEPTR
  358.     and    eax,NOT 3
  359.     mov    __heapbottom,eax ;Next dword past top of stack.
  360.     push    eax
  361.     call    _brk        ;Sets __pastdata
  362.     add    esp,SIZEPTR
  363.     inc    eax        ;Test eax for -1.
  364.     jz    short alloc_fail
  365.     mov    eax,__heapbottom
  366.     sub    eax,SIZEPTR    ;New top of stack.
  367.  
  368. set_seg2:
  369.     mov    EBX,[EBP]    ;Trace stack frame back to find top of stack.
  370.     tst    EBX        
  371.     jz    set_seg3
  372.     mov    EBP,[EBX]
  373.     jmps    set_seg2
  374.  
  375. set_seg3:
  376.     push    DS
  377.     pop    ES
  378.  
  379.     mov    ECX,EBP        ;Prepare to copy old stack to new stack.
  380.     sub    ECX,ESP
  381.     mov    ESI,ESP
  382.     mov    ESP,EAX        ;Set up new stack top.
  383.     sub    ESP,ECX
  384.     mov    EDI,ESP        ;Point at destination for new stack.
  385.     rep    movsb        ;Move the stack data.
  386.  
  387.     pop    EBP
  388.     ret
  389. dos386_set_ds endp
  390.  
  391. endif    ;DOS386
  392.  
  393. ifndef M_UNIX
  394. alloc_fail:
  395.     mov    EDX,offset DGROUP:nomem
  396. ;    jmp    short fatmsg
  397.  
  398. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  399. ; Print out fatal error message and abort.
  400. ; Input:
  401. ;    DS:EDX -> message
  402. ; Modified by Joe Huffman September 10, 1990
  403.  
  404. fatmsg:
  405.     bdos    9        ;Output the message.
  406.     push    1        ;error exit code
  407.     call    __exit        ;abort
  408.     hlt            ;never reached
  409. endif ;M_UNIX
  410.  
  411.  
  412.  
  413. ifndef M_UNIX
  414. ;;;;;;;;;;;;;;;;;;
  415. ;Stuff common to both the PharLap and X386 code.
  416. ;;;;;;;;;;;;;;;;;;
  417.  
  418. ;;;;;;;;;;;;;;;;;;;;;;;;;
  419. ; Get =XXXX from command line and set __stack.  Rounds it up to the next
  420. ; 4096 boundary.
  421. ; Input: FS == selector for PSP.
  422. ;    
  423. ; Returns:
  424. ;    __stack = value from command line rounded up.
  425. ; Destroys: All general registers.  Saves segment registers.
  426.  
  427. get_stack    proc    near
  428.     mov    EBX,__stack    ;Ignore if __stack == 0
  429.     tst    EBX
  430.     jz    GS10
  431.  
  432.     push    DS
  433.     mov    AX,FS
  434.     mov    DS,AX
  435.     mov    ESI,80h
  436.     lodsb
  437.     mov    EDI,ESI
  438.     movzx    ECX,AL        ;Length of the command line.
  439.  
  440. GS1:    jecxz    GS9
  441.     lodsb
  442.     dec    ECX
  443.  
  444. GS2:    mov    DX,256 * 9 + ' '    ;Search for tabs, spaces,
  445.     _ifs    AL e "'",GS3        ;If found a ' skip past it.
  446.     _ifs    AL e '"',GS3        ;If found a " skip it.
  447.     _ifs    AL e DL,GS1        ;If found a ' ' eat whitespace
  448.     _ifs    AL e DH,GS1        ;If found a '\t' eat white
  449.     _ifs    AL e '=',GS6        ;found =XXXX stack size parameter
  450.     jmps    GS4
  451.  
  452. GS3:    mov    DL,AL        ;Search for this character -- ' or "
  453.     mov    DH,AL
  454.  
  455. GS4:    jecxz    GS9
  456.     lodsb
  457.     dec    ECX
  458.  
  459.     _ifs    AL e DL,GS5    ;Found it, search for another
  460.     _ifs    AL ne DL,GS4
  461.  
  462. GS5:    _ifs    DL e DH,GS1    ;Load next char and continue.
  463.     jmps    GS2        ;Already loaded next char.
  464.  
  465.  
  466. GS6:    clr    EBX        ;accumulate result in EBX
  467.  
  468. GS7:    jecxz    GS9            ;if end of command line
  469.     lodsb                ;get next char of paramter
  470.     dec    ECX
  471.  
  472.     _ifs    AL e ' ', GS9
  473.     _ifs    AL e 9, GS9        ;if end of parameter
  474.     sub    AL,'0'
  475.     js    short GSerr
  476.     movzx    EAX,AL
  477.     _ifs    AL ae 10, GSerr        ;AL is not a digit
  478.     imul    EBX,10
  479.     jc    short GSerr        ;integer overflow
  480.     add    EBX,EAX            ;EBX = EBX * 10 + EAX
  481.     jnc    short GS7        ;no error
  482.  
  483. GSerr:    pop    DS
  484.     mov    EDX,offset DGROUP:badstk
  485.     jmp    fatmsg
  486.  
  487. GS9:    pop    DS
  488.     neg    EBX            ;Round up to nearest 4096 boundary.
  489.     and    BX,0f000h
  490.     neg    EBX
  491.     mov    __stack,EBX        ;store result in __stack
  492. GS10:    ret
  493. get_stack    endp
  494.  
  495. ;;;;;;;;;;;;;;;;;;
  496. ;This expects ES:0 to point to the start of the environment.
  497. ;It malloc's space for the envirnment and copies the environment there.
  498. ;All general registers are trashed.  Segment registers are preserved.
  499. ;argv is expected to be setup with room for argv[0] so that the program
  500. ;name is put there.
  501. ;;;;;;;;;;;;;;;;;;
  502. env_malloc    proc    near
  503.  
  504. ;Need to find the end of the environment.  This is two consecutive 0 bytes.
  505.     clr    EAX        ;Search for a 0.
  506.     mov    EDI,EAX        ;Environment starts at offset 0.
  507.     mov    ECX,EAX
  508.     dec    ECX        ;Allow it to be very long.
  509.  
  510. env_len_loop:
  511.       repne   scasb          ;Find the first 0.
  512.       scasb              ;Is the next a 0 also?
  513.       jz      short env_len_done      ;Jmp if found two 0's in a row.
  514.       loop      env_len_loop
  515.  
  516. env_len_done:
  517.     push    ES        ;Save a copy of ES.
  518. if ESeqDS
  519.     mov    AX,DS
  520.     mov    ES,AX
  521. endif
  522.  
  523.     push    EDI        ;EDI has the length of the entire enviroment.
  524.     call    _malloc
  525.     pop    EBX        ;Clean up the stack.
  526.  
  527.     tst    EAX
  528.     jz    alloc_fail
  529.  
  530.     mov    __envptr,EAX
  531.     mov    ECX,EDI        ;Still has length of the environment.
  532.     mov    EDI,EAX        ;Destination of environment.
  533.     clr    ESI        ;Source offset of environment.
  534.  
  535.     push    DS
  536.     pop    ES        ;Get DGROUP in ES.
  537.     pop    DS        ;Get environment selector in DS.
  538.  
  539.     rep    movsb        ;Environment is copied.
  540.  
  541.     add    ESI,2        ;Get to program name.
  542.     mov    EDI,ESI        ;Place to start scan.
  543.  
  544.     push    ES        ;DGROUP.
  545.     push    DS        ;Environment selector.
  546.     pop    ES        ;Set ES to enviroment sel.
  547.     pop    DS        ;Set DS to DGROUP.
  548.  
  549.     clr    AL
  550.     mov    CL,0FFh        ;Something longer than the real length.
  551.     repne    scasb        ;find the end.
  552.     sub    EDI,ESI        ;Length of program name.
  553.     inc    EDI        ;Leave room for 0.
  554.  
  555.     push    ES        ;Save environment selector.
  556. if ESeqDS
  557.     mov    AX,DS
  558.     mov    ES,AX
  559. endif
  560.     push    EDI        ;Length of program name plus '\0'.
  561.     call    _malloc        ;Get some memory for the program name.
  562.     pop    EBX        ;Clean up the stack.
  563.     tst    EAX
  564.     jz    alloc_fail
  565.  
  566.     mov    EBX,__argv
  567.     mov    [EBX],EAX    ;Set up pointer argv[0].
  568.     mov    ECX,EDI        ;Length of prog name plus a 0.
  569.     mov    EDI,EAX        ;ptr to allocated memory for the program name.
  570.  
  571.     push    DS        ;DGROUP
  572.     pop    ES
  573.     pop    DS        ;Environment selector.
  574.     rep    movsb        ;Copy program name.
  575.  
  576.     push    DS        ;Environment selector.
  577.     push    ES        ;DGROUP
  578.     pop    DS        ;DGROUP
  579.     pop    ES        ;Envirnment selector.
  580.     ret
  581. env_malloc    endp
  582.  
  583. ;;;;;;;;;;;;;;;;;;;;;;;;;
  584. ; Set up argc and argv for DOS386.
  585. ; Because the data is in another segment the data space is malloced and copied
  586. ; to the new area.  On entry FS must be the selector for the PSP.
  587. ; Memory is allocated for argv[].
  588. ; Uses/destroys EAX, EBX, ECX, EDX, ESI, EDI, and ES.
  589. ; January 15, 1991
  590. ;;;;;;;;;;;;;;;;;;;;;;;;;
  591. args_setup    proc    near
  592.     push    1
  593.     push    SIZEPTR * (ARGMAX + 2)    ;+1 for argv[0], +1 for argv[argc]
  594.  
  595. if ESeqDS
  596.     push    DS
  597.     pop    ES
  598. endif
  599.     call    _calloc
  600.     add    ESP,8
  601.     mov    __argv,EAX
  602.     jz    alloc_fail
  603.     tst    EAX
  604.  
  605.     movzx    EBX,byte ptr FS:[80h]      ;Length of the command line.
  606.     tst    EBX
  607.     jz    arg_L7        ;no command line
  608.     inc    EBX        ;Room for terminating 0.
  609.     push    EBX        ;Size allocated.
  610.     dec    EBX        ;Actual length.
  611.     call    _malloc
  612.     add    ESP,4
  613.     tst    EAX
  614.     jz    alloc_fail
  615.  
  616.     mov    EDI,EAX        ;Dest of copy of command line.
  617.     mov    EDX,EAX        ;Save this pointer.  Note that it is
  618. ife ESeqDS            ;eventually 'lost'.  It will never be freed.
  619.     push    DS        ;If it is desired to free this later (like
  620.     pop    ES        ;after the program is run) then this is the
  621. endif                ;place to save a copy away somewhere.
  622.     mov    ECX,EBX        ;Length of the command line
  623.     mov    ESI,081h
  624.  
  625.     push    DS
  626.     push    FS
  627.     pop    DS        ;source is DS:ESI
  628.     rep    movsb        ;Entire command line is now in our data seg.
  629.     clr    AL
  630.     stosb            ;0 terminate the command line
  631.     pop    DS
  632.  
  633.     ;;;;;;;;;;;;;
  634.     ; EDX has pointer to our copy of command line (in DGROUP).
  635.     ; EBX has length (not including terminating 0).
  636.     ; ES == DS == DGROUP
  637.  
  638.     mov    ESI,EDX
  639.     mov    EDI,EDX
  640.     mov    EBX,SIZEPTR    ;&argv[1] - argv
  641.  
  642. arg_loop_top:
  643.     mov    DX,9*256 + ' '        ;DH = tab, DL = space
  644.     lodsb                ;get char from command line
  645.     tst    AL            ;done?
  646.     jz    set_argv_done        ;yes
  647.  
  648.     _ifs    AL ne '=', arg_ignore_eq
  649.     _ifs    __stack e 0,arg_ignore_eq  ;if ignore '=nnnn' command
  650.  
  651. arg_eat__stack:        ;__stack already been taken care of, ignore it now.
  652.     lodsb
  653.     tst    AL
  654.     jz    set_argv_done
  655.     _ifs    AL e DL, arg_loop_top
  656.     _ifs    AL e DH, arg_loop_top    ;eat spaces and tabs
  657.     jmp    arg_eat__stack
  658.  
  659. arg_ignore_eq:
  660.     _ifs    AL e DL, arg_loop_top
  661.     _ifs    AL e DH, arg_loop_top    ;eat spaces and tabs
  662.     _ifs    AL e '"', arg_L1
  663.     _ifs    AL ne "'", arg_L2
  664.  
  665. arg_L1: mov    DL,AL
  666.     mov    DH,AL
  667.     inc    ESI        ;past ' or "
  668.  
  669. arg_L2: _ifs    EBX be ARGMAX*SIZEPTR,arg_L3
  670.     mov    EDX,offset DGROUP:badcmd
  671.     jmp    fatmsg
  672.  
  673. arg_L3: dec    ESI
  674.     mov    EAX,__argv    ;set the pointer to this arg.
  675.     mov    [EAX + EBX],ESI    ;EBX has offset of pointer to this arg.
  676.     mov    EDI,ESI
  677.     add    EBX,SIZEPTR
  678.     xor    AL,AL        ;last char read
  679. arg_L4:    mov    AH,AL        ;remember last char read
  680.     lodsb            ;get next char of parameter
  681.     stosb            ;and store it
  682.     tst    AL        ;done
  683.     jz    short set_argv_done
  684.  
  685.     ;Remove any \ that are immediately followed by "
  686.     _ifs    AX ne <'\'*256 + '"'>, L3a
  687.     dec    EDI        ;remove '\'
  688.     dec    EDI
  689.     stosb
  690.     jmp    arg_L4
  691.  
  692. L3a:    _ifs    AL e  DL,arg_L5 ;end of parameter
  693.     _ifs    AL ne DH,arg_L4 ;not end of parameter
  694. arg_L5: clr    AL
  695.     dec    EDI
  696.     stosb            ;terminate parameter with a 0
  697.     jmp    arg_loop_top    ;look for next parameter
  698.  
  699. arg_L7:    mov    BL,SIZEPTR    ;Length required for _argv.
  700.                 ;argv[0] will be set by dos386_set_envp()
  701. set_argv_done:
  702.     add    EBX,SIZEPTR    ;allow room for terminating NULL
  703.     push    EBX        ;Size of array used for pointers to args.
  704.                 ;Parameter to realloc().
  705.     shr    EBX,2        ;get arg count
  706.     dec    EBX        ;remove terminating NULL
  707.     mov    __argc,EBX
  708.     push    __argv
  709.     call    _realloc    ;shrink argv[] down to actual size
  710.     add    ESP,8
  711.     tst    EAX
  712.     jz    alloc_fail
  713.     mov    __argv,EAX
  714.     ret
  715.  
  716. args_setup    endp
  717.  
  718. endif    ;M_UNIX
  719.  
  720. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  721. ; Check and see if stack overflowed.
  722. ; This can be called at any time by the application code. It was originally
  723. ; useful to place a call to this at selected points when stack overflow
  724. ; checking is turned off.  Obsolete for UNIX because of hardware protection
  725. ; and virtual memory.
  726. ; Returns:
  727. ;    # of bytes left in stack
  728. ; Modified by Joe Huffman September 13, 1990
  729. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  730. __chkstack    proc    near
  731. ifdef DOS386
  732.     mov    EAX,ESP
  733.     _ifs    __stack_bottom ne 66BB55AAh, stack_overflow
  734.     sub    EAX,offset DGROUP: __stack_bottom ;Remaining stack left.
  735.     jbe    stack_overflow
  736. endif
  737. ifdef M_UNIX
  738.     mov    EAX,ESP
  739.     sub    EAX,__pastdata    ;Remaining stack left.
  740. endif
  741. ifdef M_X386
  742.     mov    EAX,__pastdata    ;Round up to the next 4k boundary.
  743.     neg    EAX        ;This is the current segment limit of
  744.     and    AX,0f000h    ;the stack.  This can change if malloc()
  745.     add    EAX,ESP        ;(or siblings) is called -- actually brk() 
  746.                 ;is the critical function...
  747. endif
  748.     ret
  749. __chkstack    endp
  750.  
  751. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  752. ; Stack frame generator.
  753. ; Called at entry to each function when stack overflow checking
  754. ; is turned on.
  755. __chkstk    proc    near
  756.     pop    EDX        ;get offset of return addr
  757.     sub    ESP,EAX        ;create space for local variables
  758. ifdef DOS386
  759.     jbe    short stack_overflow
  760.     _ifs    __stack_bottom ne 66BB55AAh, stack_overflow
  761.     _ifs    ESP be <offset DGROUP:__stack_bottom>,stack_overflow
  762. endif
  763.     jmp    EDX        ;return to caller
  764.  
  765. __chkstk    endp
  766.  
  767. ifndef M_UNIX
  768.  
  769. ifdef DOS386
  770. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  771. ; Stack overflow jumps here.
  772.  
  773. stack_overflow:
  774.     mov    edx,offset DGROUP:ovrflw
  775.     jmp    fatmsg
  776. endif
  777.     endcode
  778.  
  779. ;;;;;;;;;;;;;;;;;;;;;;;;;
  780. ; Items below are things which are different between Phar Lap DOS386 and the
  781. ; X386 memory model so they are put in c.asm to keep the Phar Lap and X386 
  782. ; libraries identical.
  783. ;
  784. ; Copyright Walter Bright
  785. ; Modified by Joe Huffman September 17, 1990
  786. ;;;;;;;;;;;;;;;;;;;;;;;;; 
  787.  
  788.  
  789. ENOMEM    equ    8
  790.  
  791. _TEXT    segment para public 'CODE'
  792.     assume CS:_TEXT
  793.     c_public sbrk, brk
  794.  
  795. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  796. ; Request memory from operating system.
  797. ; Attempt to grow the data segment.
  798. ; Use:
  799. ;    p = sbrk(nbytes);
  800. ; Returns:
  801. ;    pointer to memory allocated
  802. ;    -1 if error
  803. ; Modified by Joe Huffman June 20, 1990
  804. ;
  805. ; NOTE!!! malloc() depends on P[EBP] being the true amount allocated.
  806. ; Don't use it for scratch!
  807. func    sbrk
  808.     push    EBP
  809.     mov    EBP,ESP
  810.     uses    <ECX>
  811.  
  812.     mov    EAX,__pastdata        ;Current setting.
  813.     mov    ECX,P[EBP]        ;Number of bytes to change DS by.
  814.     jecxz    short sbrk_done        ;If zero return current setting.
  815.  
  816.     add    ECX,EAX            ;ECX has new pointer to end of DS,
  817.     jc    short sbrk_err1        ;jump if wrap around
  818.     push    EAX            ;Current end of DS for return value.
  819.     push    ECX            ;Push new pointer to end of DS.
  820.     callm    brk            ;Set the new end of segment.
  821.     add    ESP,4
  822.  
  823.     pop    ECX            ;return value if was successful.
  824.     or    EAX,EAX            ;Returns 0 for success.
  825.     jnz    short sbrk_err2
  826.  
  827. sbrk_done:
  828.     add    EAX,ECX
  829.  
  830.     unuse    <ECX>
  831.     pop    EBP
  832.     ret
  833.  
  834. sbrk_err1:
  835.     mov    errno,ENOMEM
  836.  
  837. sbrk_err2:
  838.     mov    EAX,-1
  839.     unuse    <ECX>
  840.     pop    EBP
  841.     ret
  842. c_endp    sbrk
  843.  
  844. ;;;;;;;;;;;;;;;;;;;;;;;;;
  845. ; Set the end point of DS to a new value.
  846. ; Use:
  847. ;    int brk(char *new_end)
  848. ; Returns:
  849. ;    0 if succesfull
  850. ;      -1 if error.
  851. ; June 20, 1990
  852. ;;;;;;;;;;;;;;;;;;;;;;;;;
  853.  
  854. ifdef X386
  855.  
  856. _brk    proc    near
  857.         mov     eax,4[esp]     ;desired new value for break
  858.         cmp     eax,__x386_break        ;check current location of break
  859.         ja      brk1
  860. ;no need to adjust stack limit, update __pastdata, change nothing else.
  861.         mov     __pastdata,eax
  862. brk2:   xor     eax,eax
  863.         ret
  864. brk1:   push    es
  865.         mov     es,__x386_data_16_alias
  866. assume es:__X386_GROUP_16
  867.         mov     ecx,__x386_esp3         ;top of stack
  868.         sub     ecx,__stack             ;result may not be 4 k aligned
  869.         and     cx,0f000h               ;round down to 4 k boundary
  870.         cmp     eax,ecx
  871. ;preserve min stack size, also catches wrap around error in round up below
  872.         ja      brk_error
  873. ;adjust stack limit and __x386_break
  874.         mov     edx,eax         ;value for __pastdata if cmp eax,esp is okay
  875.         neg     eax
  876.         and     ax,0f000h       ;round up to nearest 4 kbyte boundary
  877.         neg     eax
  878.         mov     al,8            ;allow room for two pushes
  879.         cmp     eax,esp
  880.         ja      brk_error
  881.         xor     al,al           ;take out fudge factor placed in al
  882.         mov     __pastdata,edx  ;brk will not fail so update __pastdata
  883.         mov     ecx,eax
  884.         shr     eax,12          ;adjust for page granular limit
  885.         dec     eax     ;make next address down illegal
  886. comment&
  887.         The variable __x386_set_ss_lim is initialized at run time to point to 
  888.         __x386_dpmi_set_ss_lim if a dpmi host is detected, otherwise, it is 
  889.         initialized to no_dpmi_set_ss_lim.
  890. &
  891.         jmp     __x386_set_ss_lim
  892. no_dpmi_set_ss_lim:
  893.         mov     es:__X386_GROUP_16:__x386_stack_32_des.limit_0,ax 
  894. ;low word of limit is now stored in gdt
  895.         shr     eax,8
  896.         or      ah,0c0h ;mov c into high nibble of ah, set granularity and dbit
  897.         mov     es:__X386_GROUP_16:__x386_stack_32_des.type_limit,ah
  898. limit_updated:
  899. ;Stack limit is now updated
  900.         push    ss
  901.         pop     ss      ;load new limit from gdt
  902.         mov     __x386_break,ecx        ;update break
  903.         pop     es
  904.         jmp     brk2
  905. brk_error:
  906.         mov     _errno,ENOMEM
  907.         xor     eax,eax
  908.         dec     eax             ;return - 1
  909.         pop     es
  910.         ret
  911. public __x386_dpmi_set_ss_lim
  912. __x386_dpmi_set_ss_lim:
  913. comment&
  914.         Execution branches to this point if dpmi was detected during 
  915.         initialization.  At this point, the original es has been pushed on the 
  916.         stack, eax contains the new segment limit shifted right 12 bits.  ecx 
  917.         contains __x386_break and must be preserved for later use.
  918.         &
  919.         push    ecx
  920.         push    ebx
  921.         mov     bx,ss   ;selector for dpmi
  922.         mov     edx,eax
  923.         shl     edx,12          ;restore to 32 bit address
  924.         or      dx,0fffh        ;set low 12 bits for dpmi
  925.         shld    ecx,edx,16      ;cx:dx now has new limit
  926. ;Microsoft windows has serious bugs which can only be avoided by loading a 
  927. ;special stack with esp > 2 GBytes or esp < 64 KBytes.  I chose the second 
  928. ;option.
  929.         push    esi
  930.         push    edi
  931.         push    ebp
  932.         push    ds
  933.         mov     ax,__x386_data_16_alias
  934.         mov     ds,ax
  935. assume ds:__X386_GROUP_16
  936. ;must allocate space on the 16 bit stack in case of a hardware interrupt
  937.         mov     ebp,__x386_esp0
  938.         sub     __x386_esp0,180h
  939.         mov     esi,esp
  940.         mov     edi,ss
  941.         mov     ss,ax
  942.         mov     esp,ebp
  943.         mov     ax,8h
  944.         int     31h             ;call dpmi, set ss limit
  945.         mov     ss,edi
  946.         mov     esp,esi         ;restore 32 bit stack
  947.         add     __x386_esp0,180h
  948. assume ds:DGROUP
  949.         pop     ds
  950.         pop     ebp
  951.         pop     edi
  952.         pop     esi
  953.         pop     ebx
  954.         pop     ecx
  955.         jmp     limit_updated
  956. _brk    endp
  957.  
  958. else ;X386
  959.  
  960. func    brk
  961.     push    EBX
  962.  
  963.     mov    EBX,P[ESP]
  964.     add    EBX,4096 - 1    ;Round up to nearest page size.
  965.     shr    EBX,12        ;Get number of pages.
  966.  
  967. ife ESeqDS
  968.     mov    AX,DS
  969.     mov    ES,AX
  970. endif
  971.  
  972.     bdos    4AH        ;resize the segment.
  973.     unuse    <EBX>
  974.  
  975.     jc    short cerror
  976.  
  977.     mov    EAX,PS[ESP]    ;Get the new break value.
  978.     mov    __pastdata,EAX    ;Save it for future use.
  979.     clr    EAX
  980.     ret
  981.  
  982. cerror:
  983.     mov    _errno,EAX    ;errno = value returned by kernel
  984.     sbb    EAX,EAX        ;return value = -1
  985.  
  986.     ret
  987.  
  988. c_endp    brk
  989.  
  990. endif ;X386
  991.  
  992.  
  993. comment&
  994.         __get_video_selector returns a protected mode selector in ax which 
  995.         points to the video buffer.  The real mode segment value is passed in 
  996.         ax, it is ignored under Pharlap which returns 1ch regardless of the 
  997.         value passed in ax.  In case of X386, a protected mode selector is 
  998.         allocated with base address of X386, if no selectors are available it 
  999.         returns 0 in ax which causes disp to use bios.  If zero was passed in 
  1000.         AX, it returns 0 which tells disp to use bios.
  1001. &
  1002.  
  1003. public __get_video_selector
  1004. __get_video_selector       proc    near
  1005. ifdef DOS386
  1006.         or      AX,AX           ;check for zero
  1007.         jz short vid_sel_ret    ;if zero, return zero
  1008.         mov     AX,1ch          ;hardwired video buffer selector
  1009. vid_sel_ret:
  1010.         ret
  1011. else  ;DOS386
  1012.         or      AX,AX           ;check for zero
  1013.         jz short vid_sel_ret    ;if zero, return zero
  1014.         cmp     __x386_disp_base,0
  1015.         jnz     R1                      ;if not zero, it is already allocated
  1016. get_new_selector:
  1017.         movzx   EAX,AX
  1018.         shl     EAX,4                   ;make absolute address
  1019.         push    EAX
  1020.         call    __x386_mk_protected_ptr ;returns pointer in DX:EAX
  1021.         or      EAX,EAX                 ;zero if successful
  1022.         mov     EAX,EDX                 ;selector
  1023.         pop     EDX                     ;restore stack, EDX is garbage
  1024.         jnz     R1                      ;return zero if failure
  1025.         mov     __x386_disp_base,AX     ;store for future calls
  1026. vid_sel_ret:
  1027.         ret
  1028. R1:
  1029.         mov     AX,__x386_disp_base
  1030.         ret
  1031. endif
  1032. __get_video_selector    endp
  1033.  
  1034. endif   ;M_UNIX
  1035.  
  1036.     endcode
  1037.  
  1038.     end    __start
  1039.  
  1040.