home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / STRTUP10.ZIP / STARTUP.ZIP / STARTUP / STARTUP1.ASM < prev    next >
Encoding:
Assembly Source File  |  1997-02-28  |  12.4 KB  |  423 lines

  1.     page 60,132
  2.     title Start_Up1 -- Intermediate Start Up Code for .COM/.EXE Programs
  3.     name Start_Up1
  4.  
  5. comment ÷
  6.         Start_Up1                                               V1.06
  7. --------------------------------------------------------------------------
  8. NAME
  9.     startup1    Intermediate start up code for .com and .exe
  10.             programs
  11.  
  12. SYNOPSIS
  13.     extern Start_Up1
  14.     or
  15.     extern Start_Up1S
  16.  
  17.     See Programming Notes below for difference.
  18.  
  19. DESCRIPTION
  20.     This is the startup code for all .exe and .com assembly language
  21.     programs.  Just use the SYNOPSIS above in the main function to
  22.     include this startup code in the .exe file from a .lib.    For .com
  23.     assembly language programs, this source code must be the first
  24.     assembled so that this code is the linked first.
  25.  
  26.     This procedure parses the command line into argc and *argv[] similar
  27.     to C.  Argv[0] is the first command line argument not the program
  28.     name as in C.
  29.     
  30.     This procedure performs the following functions in addition to above
  31.     - Initializes the following global variables:
  32.       -- DGRP, segment address of DGROUP
  33.       -- STACK_BOTTOM, offset to stack bottom in DGROUP
  34.       -- PSP, segment address of PSP
  35.       -- ENVIRON, segment address of passed copy of the ENVIRONMENT
  36.       -- OSMAJOR, integer part of OS system
  37.       -- OSMINOR, decimal part of OS system
  38.     - If DOS version is less than 2.0, aborts with error message
  39.     - Initializes DS and ES segment registers to DGROUP
  40.     - Shrinks memory down to size of program by releasing all memory 
  41.       above program
  42.  
  43. RETURNS
  44.     If main returns to startup code.  The program terminiates with the 
  45.     return code in AL.
  46.  
  47. PROGRAMING NOTES
  48.     Assembled with Microsoft MASM V6.11d with options: /Cp /W3 /Wx
  49.     /memmod={see below}.  Do not use the /NOI switch with linker.
  50.  
  51.     Written to link with any memory model.
  52.     
  53.     Use MEMMOD to specify the memory model.
  54.     /dMEMMOD=TINY|SMALL|COMPACT|MEDIUM|LARGE|HUGE
  55.  
  56.     Written using the FORTRAN/PASCAL/BASIC calling convention so passed
  57.     parameters are pushed in the order of appearance in the proc 
  58.     declaration.
  59.  
  60.     This procedure can pass argc and argv on stack two ways.   The proc
  61.     declaration in the MAIN procedure will differ depending upon the 
  62.     choice.
  63.     
  64.     The default requires the following proc declaration:
  65.     
  66.         MAIN proc ARGC:word, ARGV:ptr
  67.     
  68.     If SIMPLE is defined, an alternate proc declaration is required:
  69.     
  70.         MAIN proc ARGV:ptr, ARGC:word
  71.     
  72.     Here, ARGV is not a pointer to an array of pointers but the location
  73.     of the 1st pointer.
  74.  
  75.     In Huge memory model, the pointers passed in ARGV are long pointer
  76.     vice huge pointers.
  77.  
  78. MEMORY REQUIREMENTS
  79.     (in bytes)     Tiny   Small   Medium   Compact    Large    Huge
  80.     Code:        165    190    192     193     195    195
  81.     Code (SIMPLE):    162    187    189     189     191    191
  82.     _Data:          0     0      0       0       0      0
  83.     Const:          0     0      0       0       0      0
  84.     _BBS:         12    12     12      12      12     12
  85.     Stack:          ?     ?      ?       ?       ?      ?
  86.  
  87.     The first code size is for SIMPLE not defined.    The Code (SIMPLE) is
  88.     for when SIMPLE is defined.
  89.  
  90.     Stack usage is determined by the size of and the number of arguments
  91.     in the command line.
  92.  
  93.     Note:  The 12 bytes in _BSS are from sudata.asm which is used so that
  94.     all startup code can reside in the same .lib file.
  95.  
  96. CAUTION
  97.     Startup1 defines a 512 byte stack.  This should be enough for programs
  98.     who make moderate use of the stack.  If automatic variables are used
  99.     extensively, more stack space should be defined in the main module
  100.     unless using the tiny memory model.  In this case, the startup code
  101.     must be the first souce file in the build, change the size of the
  102.     STACK_SIZE define.
  103.     
  104.     Linker option, NO IGNORE CASE, is not used so that the linker will
  105.     handle __end properly.
  106.     
  107. EXTERNAL LIBRARIES
  108.     sudata        alib?
  109.  
  110. EXTERNAL PROCEDURES
  111.     main        user defined
  112.  
  113. INTERUPTS CALLED
  114.     Int 21h 30h - Get Version Number
  115.     Int 21h 4ah - Set Memory Block Size
  116.     Int 21h 4ch - Terminate program with return code
  117.  
  118. GLOBAL NAMES
  119.     Startup_1 or Startup_1S
  120.  
  121. AUTHOR
  122.     Raymond Moon - 7 Sep 87
  123.  
  124.         Copyright (c) 1987, 1988, 1994, 1995, 1996 - MoonWare
  125.     ALL RIGHTS RESERVED
  126.  
  127. VERSION
  128.     Version    - Date        - Remarks
  129.     1.00    -  7 Sep 87    - Original
  130.         1.01    - 13 Feb 88     - Updated program to parse command line
  131.                 - This created Startup1 from Startup0
  132.     1.02    -  4 Jul 88    - Converted to MASM V5.1
  133.     1.03    -  9 Oct 88    - Added Stack_Bottom & ZZ_PRGM_TOP segment
  134.                   to determine end of data.
  135.     1.04    - 30 Oct 94    - Moved ZZ_PRGM_TOP segment position in file.
  136.                 - Removed increment in program size in paras
  137.                     as ZZ_PRGM_TOP is aligned on a para.
  138.     1.05    -  5 Mar 95    - Added TINY Model capability
  139.                 - Converted to .dosseg using __end vice
  140.                   ZZ_PRGM_TOP for end of data
  141.                 - Removed checking for DOS Ver 1.0 and
  142.                                   terminating with error message.
  143.         1.06    - 29 Dec 96     - Optimized the .com coding
  144. ==========================================================================
  145.     ÷  Commend End
  146.  
  147. ;-----------------------------
  148. ; A      Make the small memory model the default
  149.  
  150. ifndef    memmod
  151. memmod    equ    <small>
  152. endif
  153.  
  154. ;-----------------------------
  155. ; B    Include the processor, memory model, associate ES register with
  156. ;    DGROUP, and specify DOS segment order.
  157.  
  158.     include procesor.inc
  159. %    .MODEL    memmod,FORTRAN
  160.     assume    es:DGROUP
  161.     .dosseg
  162.  
  163. ;----------------------------
  164. ; C     Required includes
  165.  
  166.     include startup.inc
  167.  
  168. ;----------------------------
  169. ; D     Define any required equates
  170.  
  171. STACK_SIZE    equ    512
  172.  
  173. ;=========================================================================
  174. ;    DATA
  175. ;=========================================================================
  176. ; E     Define storage for the various global and system variables.
  177.  
  178. if    @Model    NE  1
  179.     .STACK    STACK_SIZE    ; Define a nominal stack
  180. endif
  181.  
  182. ;----------------------------
  183. ; F     Define __end which is defined when using .dosseg
  184.  
  185. externdef    __end:byte
  186.  
  187. ;----------------------------
  188. ; G     Define segment for addressing information in the PSP
  189.  
  190. PSP_SEG    segment at 00h
  191.     
  192.     org    2h
  193. NEXTPARA_PTR    dw    ?        ; Segment address of next memory para
  194.  
  195.     org    2ch
  196. ENVIRON_PTR    dw    ?        ; Segment address of Environment
  197.  
  198.     org     80h
  199. PARM_LEN     db    ?        ; Number of bytes in Command Line tail
  200. PARMS       db    127 dup(?)    ; Start of Command Line tail
  201. PSP_SEG    ends
  202.  
  203. ;=========================================================================
  204. ;    CODE
  205. ;=========================================================================
  206. ; H     Put the called main procedure in the proper relationship to the
  207. ;    startup code.
  208.  
  209. if @CodeSize
  210. extrn    Main:far
  211. .CODE
  212. else
  213. .CODE
  214. extrn    Main:near
  215. endif
  216.  
  217. ;-----------------------------
  218. ; I     Include org statement if tiny model
  219.  
  220. if    @Model    EQ 1
  221.  
  222.     org    100h
  223. endif
  224.  
  225. ;-----------------------------
  226. ; J     Start the Start_Up1 code.  Make it a far procedure so error return
  227. ;    will work.  If SIMPLE is defined, redefined Start_Up1 as Start_Up1S.
  228.  
  229. ifdef SIMPLE
  230. Start_Up1    equ    <Start_Up1S>
  231. endif
  232.  
  233. % Start_Up1    proc    far
  234.  
  235. ;-----------------------------
  236. ; K     First, initialize global variables.  Set DS to DGROUP.
  237. ;    Skip DGROUP code for .com(Tiny) memory models
  238.  
  239. if    @Model    NE 1
  240.  
  241.     mov    ax, DGROUP        ; Get seg address of DGROUP
  242.     mov    ds, ax            ; Initialize DS segment register
  243.     mov    DGRP, ax        ; Initialize DGRP
  244. assume    es:PSP_SEG
  245. else
  246.     mov    DGRP, ds        ; Initialize DGRP
  247. endif
  248.     mov    PSP, es            ; Initialize PSP
  249. if    @Model    eq 1
  250. assume    ds:PSP_SEG
  251. endif
  252.     mov    bx, ENVIRON_PTR     ; Get segment address of environment
  253.     mov    cx, NEXTPARA_PTR    ; Get segment address of next memory
  254. if    @Model    eq 1
  255. assume    ds:DGROUP
  256. endif
  257.     mov    ENVIRON, bx        ; Initialize ENVIRON
  258.     mov    NEXTPARA, cx        ; Initialize NEXTPARA
  259.     mov    ah, 30h            ; Get DOS version number
  260.     int    21h            ; Call DOS
  261.     mov    OSMAJOR, al        ; Save major version number
  262.     mov    OSMINOR, ah        ; Save minor version number
  263.  
  264. ;----------------------------
  265. ; L     Combine the stack into DGROUP so that it is addressable from DGROUP.
  266. ;    Initialize STACK_BOTTOM.
  267.  
  268.     lea    bx, __end        ; Get pointer to end of data
  269.  
  270. if    @Model    eq    1        ; Ensure that Stack bottom at paragraph
  271.         add     bx, 15                  ; Add to ensure next para if necessary
  272.         and     bx, 0fff0h              ; Truncate to a paragraph boundary
  273. endif
  274.  
  275.     mov    STACK_BOTTOM, bx    ; Save it
  276.  
  277. if    @Model    eq    1        ; Get stack size
  278.     add    bx, STACK_SIZE        ; DI = stack size
  279. else
  280.     add    bx, sp            ; DI = stack size
  281. endif
  282.  
  283.     mov    dx, ds            ; Get DGROUP segment address
  284.     mov    ss, dx            ; Reset SS
  285.     mov    sp, bx            ; Reset SP
  286.  
  287. ;----------------------------
  288. ; M     Release all memory above program.  Calculate the size of the program
  289. ;    in paragraphs (16 bits).  BX starts with Stack Top
  290.  
  291.     mov    cl, 4            ; Convert to #para by dividing by 16
  292.     shr    bx, cl            ; Do division by bit shifting
  293.  
  294. if    @Model    ne    1        ; Needed in non-Tiny memory models
  295.     mov    ax, ds            ; AX => DGROUP
  296.     sub    ax, PSP            ; AX = # para for code
  297.     add    bx, ax            ; BX = # para in program
  298. endif
  299.  
  300.     mov    ah, 4ah            ; Request DOS set block
  301.     int    21h            ; Call DOS
  302.  
  303. ;----------------------------
  304. ; N     See if there are any command line arguments.  If not, all command
  305. ;    line processing is skipped.  The pushed null on the stack will be
  306. ;    argc, and a null pointer is also pushed onto the stack so argv[0]
  307. ;    is a null pointer.
  308.  
  309.     xor    dx, dx            ; Ensure DX is null
  310.     push    dx            ; Ensure null on top of stack
  311.     mov    bp, sp            ; BP = top of stack
  312. if @Model NE 1
  313.     cmp    es:PARM_LEN, 0        ; Are there any Command Line arguments
  314. else
  315. assume    ds:PSP_SEG
  316.     cmp    PARM_LEN, 0        ; Are there any Command Line arguments
  317. assume    ds:DGROUP
  318. endif
  319.     jne    SU1            ; No, go process what is on the stack
  320.     push    dx            ; Push null pointer
  321. if @DataSize
  322.     push    dx            ; Make a doubleword null pointer
  323. endif
  324. if @Model NE 1
  325.     mov    es, DGRP        ; Initialize ES for all except tiny
  326. endif
  327.     jmp    short SU7        ; Go call MAIN
  328.  
  329. ;----------------------------
  330. ; O     There are command line arguments.  Parse them onto the stack and 
  331. ;    build ARGC and ARGV.  Start this by transferring the entire command
  332. ;    line tail onto the stack.  Make room for them by moving SP.
  333.  
  334. SU1:
  335. if @Model NE 1
  336.     mov    ds, PSP            ; DS => PSP
  337. endif
  338. assume ds:PSP_SEG
  339.     mov    cl, PARM_LEN        ; Get # of bytes in Command Line
  340.     inc    cx            ; increase by one
  341.     and    cx, 0feh        ; Force an even count
  342.     mov    ax, sp            ; Get SP
  343.     sub    ax, cx            ; Subtract PARM_LEN
  344.     mov    sp, ax            ; Reset SP, room on Stack
  345.     lea    si, PARMS        ; Load source addr in SI
  346.     mov    di, sp            ; Load destin addr in DI
  347. if @Model NE 1
  348.     mov    es, DGRP        ; ES => DGROUP
  349. endif
  350. assume    es:DGROUP
  351.     rep    movsb            ; Move Command Line onto the Stack
  352. if @Model NE 1
  353.     mov    ds, es:DGRP        ; Restore DS
  354. endif
  355. assume    ds:DGROUP
  356.     
  357. ;-----------------------------
  358. ; P     Convert all blanks, not within double quotes, in the Command Line
  359. ;    to Nul.  CX is IN_LITERAL_FLAG.  Build argv[] at the same time.
  360.  
  361.     xor    di, di            ; DI set to zero, DI = arg count
  362.     mov    bx, bp            ; BX points to last byte in stack
  363.     mov    bp, sp            ; BP is the stop point
  364.     xor    cx, cx            ; Clear IN_LITERAL_FLAG
  365. SU2:    mov    al, [bx]        ; Get byte
  366.     cmp    al, '"'            ; Is it a literal?
  367.     jne    SU3            ; No, go to next test
  368.     inc    cx            ; Set IN_LITERAL_FLAG
  369.     and    cx, 1            ; Ensure only 0, & 1 valid
  370.     jmp    short SU4        ; Continue, and blank '"'
  371. SU3:    cmp    al, ' '            ; Is it a blank?
  372.     ja    SU6            ; No, go set up to get another
  373.     or    cx, cx            ; Is IN_LITERAL_FLAG clear?
  374.     jne    SU6            ; No, do not null blank
  375. SU4:    mov    byte ptr [bx], 0    ; Store Nul in [BX]
  376. SU5:    or    byte ptr [bx + 1], 0    ; Was the previous char null?
  377.     jz    SU6            ; Yes, do not push pointer
  378. if @datasize
  379.     push    ss            ; Push segment address
  380. endif
  381.     mov    ax, bx            ; AX => Null
  382.     inc    ax            ; AX => 1st char
  383.     push    ax            ; Push the offset
  384.     xor    cx, cx            ; Clear in literal flag
  385.     inc    di            ; Account for another arg
  386. SU6:    dec    bx            ; BX point to next byte
  387.     cmp    bx, bp            ; Are we through yet?
  388.     jnb    SU2            ; No, go one mo' 'gin
  389.  
  390. ;-----------------------------
  391. ; Q     Have finished building *argv[]. SP => argv[], and DI = argc.
  392. ;    Create argc and argv on the stack using the FORTRAN calling
  393. ;    convention.  If SIMPLE is defined, push only argc.  See documentation
  394. ;    above for structure of proc declaration in MAIN procedure
  395.  
  396. ifndef SIMPLE
  397.     mov    bx, sp            ; BX = **argv[]
  398.     push    di            ; Push argc
  399. if @DataSize
  400.     push    ss            ; Long pointer
  401. endif
  402.     push    bx            ; Push **argv[]
  403. else
  404.     push    di            ; Push argc
  405. endif
  406.     
  407. ;-----------------------------
  408. ; R     call MAIN
  409.  
  410. SU7:    call    Main            ; Call MAIN procedure
  411.  
  412. ;----------------------------
  413. ; S     If main returns, the program is to terminate with the return code
  414. ;    returned in AL
  415.  
  416.     mov    ah, 4ch            ; End process
  417.     int    21h            ; Call DOS
  418.  
  419. % Start_Up1    endp
  420.  
  421. %    end    Start_Up1        ; Indicate that Start_Up1 is the start
  422.                     ; of the program
  423.