     1                                  
     2                                  %if 0
     3                                  
     4                                  lDOS COMLOADER - load embedded programs
     5                                   by E. C. Masloch, 2018--2025
     6                                  
     7                                  Usage of the works is permitted provided that this
     8                                  instrument is retained with the works, so that any entity
     9                                  that uses the works is notified of this instrument.
    10                                  
    11                                  DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    12                                  
    13                                  Parts copied from msdos4/src/CMD/DEBUG/DEBCOM2.ASM and
    14                                  msdos4/src/CMD/DEBCOM3.ASM (under MIT license).
    15                                  
    16                                  %endif
    17                                  
    18                                  	cpu 8086
    19                                  
    20                                  %include "lmacros3.mac"
     1                              <1> [list -]
    14                              <2> [list -]
    14                              <1> [list -]
    21                                  %include "lstruct.mac"
     1                              <1> [list -]
    13                              <1> [list -]
    22                                  %include "mzheader.mac"
     1                              <1> 
     2                              <1> %if 0
     3                              <1> 
     4                              <1> lDebug MZ .EXE header macros
     5                              <1> 
     6                              <1> Copyright (C) 1995-2003 Paul Vojta
     7                              <1> Copyright (C) 2008-2023 E. C. Masloch
     8                              <1> 
     9                              <1> Usage of the works is permitted provided that this
    10                              <1> instrument is retained with the works, so that any entity
    11                              <1> that uses the works is notified of this instrument.
    12                              <1> 
    13                              <1> DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    14                              <1> 
    15                              <1> %endif
    16                              <1> 
    17                              <1> 
    18                              <1> 	struc EXEHEADER
    19 00000000 ????                <1> exact_struc_at 00h, exeSignature:	resw 1
    20 00000002 ????                <1> exact_struc_at 02h, exeExtraBytes:	resw 1	; bytes in last page
    21 00000004 ????                <1> exact_struc_at 04h, exePages:		resw 1	; number of 512-byte pages. includes the header!
    22 00000006 ????                <1> exact_struc_at 06h, exeRelocItems:	resw 1	; number of relocation items
    23 00000008 ????                <1> exact_struc_at 08h, exeHeaderSize:	resw 1	; header size in 16-byte paragraphs
    24 0000000A ????                <1> exact_struc_at 0Ah, exeMinAlloc:	resw 1	; minimum (bss) allocation in paragraphs
    25 0000000C ????                <1> exact_struc_at 0Ch, exeMaxAlloc:	resw 1	; maximum (bss) allocation in paragraphs
    26 0000000E ????                <1> exact_struc_at 0Eh, exeInitSS:		resw 1	; init ss (is relocated)
    27 00000010 ????                <1> exact_struc_at 10h, exeInitSP:		resw 1	; init sp
    28 00000012 ????                <1> exact_struc_at 12h, exeChecksum:	resw 1
    29                              <1> exact_struc_at 14h, exeInitCSIP:
    30 00000014 ????                <1> exact_struc_at 14h, exeInitIP:		resw 1	; init ip
    31 00000016 ????                <1> exact_struc_at 16h, exeInitCS:		resw 1	; init cs (is relocated)
    32 00000018 ????                <1> exact_struc_at 18h, exeRelocTable:	resw 1	; byte offset of relocation table
    33                              <1> 		; Each relocation item is a word offset and a word segment.
    34                              <1> 		;  The segment of the item itself is relocated as well.
    35 0000001A ????                <1> exact_struc_at 1Ah, exeOverlayNum:	resw 1
    36                              <1> exact_struc_at 1Ch
    37                              <1> 	endstruc
    23                                  
    24                                  
    25                                  	numdef MCP, 0
    26                                  	numdef MZEXESUPPORT, 1
    27                                  
    28                                  %define FOLLOWS ENTRY
    29                                  %define ENDS none
    30                                  %define ADDRESS 0
    31                                  %define COMMAND_LIST none, "", ""
    32                                  	%imacro nextcomprogram 2-4+.nolist "",vstart=256
    33                                  	align 16, db 26h
    34                                  %[ENDS]_end:
    35                                  addsection %1, follows=%[FOLLOWS] %4
    36                                  %1_start:
    37                                  %1_position equ ADDRESS
    38                                   %define FOLLOWS %1
    39                                   %define ENDS %1
    40                                   %xdefine ADDRESS (ADDRESS + (%1_end - %1_start))
    41                                   %xdefine COMMAND_LIST COMMAND_LIST, %1, %2, %3
    42                                  	%endmacro
    43                                  
    44                                  	struc COMPROGRAMLIST_ENTRY
    45 00000000 ????                    cplPositionSeg:	resw 1
    46                                  cplLength:
    47                                  %if _MZEXESUPPORT
    48 00000002 ????                    cplLengthParas:	resw 1
    49                                  %else
    50                                  cplLengthWords:	resw 1
    51                                  %endif
    52 00000004 ????                    cplNameString:	resw 1
    53 00000006 ????                    cplHelpString:	resw 1
    54                                  	endstruc
    55                                  
    56                                  	%imacro comprogramlist 0-*
    57                                  %if (%0 % 3) != 0 || %0 < 6
    58                                   %error Expected number of parameters a multiple of 3 and at least 6
    59                                  %endif
    60                                  %rep (%0 - 6) / 3
    61                                  %rotate 3
    62                                  %1_list_entry:
    63                                  	istruc COMPROGRAMLIST_ENTRY
    64                                  at cplPositionSeg,	dw %1_position >> 4
    65                                  %if _MZEXESUPPORT
    66                                  at cplLengthParas,	dw (%1_end - %1_start) >> 4
    67                                  %else
    68                                  at cplLengthWords,	dw (%1_end - %1_start) >> 1
    69                                  %endif
    70                                  at cplNameString,	dw msg_name.%1 - ..@base
    71                                  at cplHelpString,	dw msg_help.%1 - ..@base
    72                                  	iend
    73                                  %endrep
    74                                  	%endmacro
    75                                  
    76                                  	%imacro comprogrammessages 0-*
    77                                  %if (%0 % 3) != 0 || %0 < 6
    78                                   %error Expected number of parameters a multiple of 3 and at least 6
    79                                  %endif
    80                                  %rep (%0 - 6) / 3
    81                                  %rotate 3
    82                                  msg_name.%1:	asciz %2
    83                                  msg_help.%1:	asciz %3
    84                                  %endrep
    85                                  	%endmacro
    86                                  
    87                                  addsection ENTRY, vstart=256 start=0 align=16
    88                                  startentry:
    89 00000000 8CC9                    	mov cx, cs
    90 00000002 81C1B608                	add cx, paras(COMLOADER_position) + paras(startentry_size) + 16
    91 00000006 51                      	push cx
    92 00000007 31C9                    	xor cx, cx
    93 00000009 51                      	push cx
    94 0000000A CB                      	retf
    95                                  
    96 0000000B 26<rep 5h>              	align 16, db 38
    97                                  	endarea startentry
    98                                  
    99                                  nextcomprogram COMINT3, "INT3", "program that breaks to a debugger"
   100 00000000 BA[0D00]                	mov dx, .msg
   101 00000003 B409                    	mov ah, 09h
   102 00000005 CD21                    	int 21h
   103 00000007 CC                      	int3
   104 00000008 B8004C                  	mov ax, 4C00h
   105 0000000B CD21                    	int 21h
   106                                  
   107 0000000D 456D62656464656420-     .msg:	db "Embedded executable test loaded.",13,10,36
   107 00000016 65786563757461626C-
   107 0000001F 652074657374206C6F-
   107 00000028 616465642E0D0A24   
   108                                  
   109                                  
   110                                  nextcomprogram COMEMPTY, "EMPTY", "empty program for testing"
   111 00000000 B8004C                  	mov ax, 4C00h
   112 00000003 CD21                    	int 21h
   113                                  
   114                                  
   115 00000005 26<rep Bh>              nextcomprogram COMLIST, "LIST", "lists all available programs"
   116 00000000 BA[7400]                	mov dx, .msg
   117 00000003 B409                    	mov ah, 09h
   118 00000005 CD21                    	int 21h
   119                                  
   120 00000007 8ED9                    	mov ds, cx		; ds:bx -> command program name table
   121 00000009 8EC1                    	mov es, cx
   122                                  
   123 0000000B 89DF                    	mov di, bx		; es:di = ds:di -> table
   124                                  .loop:
   125                                  %if _MCP
   126                                  	cmp word [di + cplLength], -1
   127                                  %else
   128 0000000D 837D0200                	cmp word [di + cplLength], 0
   129                                  %endif
   130 00000011 745C                    	je .end
   131 00000013 8B5504                  	mov dx, word [di + cplNameString]
   132 00000016 01DA                    	add dx, bx
   133 00000018 57                      	 push di
   134 00000019 89D7                    	mov di, dx
   135 0000001B B000                    	mov al, 0
   136 0000001D B9FFFF                  	mov cx, -1
   137 00000020 F2AE                    	repne scasb
   138 00000022 F7D9                    	neg cx
   139 00000024 49                      	dec cx
   140 00000025 49                      	dec cx
   141 00000026 B440                    	mov ah, 40h
   142 00000028 53                      	push bx
   143 00000029 BB0100                  	mov bx, 1
   144 0000002C CD21                    	int 21h
   145 0000002E 5B                      	pop bx
   146                                  
   147 0000002F 83F908                  	cmp cx, 8
   148 00000032 B90100                  	mov cx, 1
   149 00000035 7301                    	jae @F
   150 00000037 41                      	inc cx
   151                                  @@:
   152 00000038 B402                    	mov ah, 02h
   153 0000003A B209                    	mov dl, 9
   154 0000003C CD21                    	int 21h
   155 0000003E E2F8                    	loop @B
   156                                  
   157 00000040 5F                      	 pop di
   158 00000041 8B5506                  	 mov dx, word [di + cplHelpString]
   159 00000044 01DA                    	 add dx, bx
   160 00000046 57                      	 push di
   161                                  
   162 00000047 89D7                    	mov di, dx
   163 00000049 B000                    	mov al, 0
   164 0000004B B9FFFF                  	mov cx, -1
   165 0000004E F2AE                    	repne scasb
   166 00000050 F7D9                    	neg cx
   167 00000052 49                      	dec cx
   168 00000053 49                      	dec cx
   169 00000054 B440                    	mov ah, 40h
   170 00000056 53                      	push bx
   171 00000057 BB0100                  	mov bx, 1
   172 0000005A CD21                    	int 21h
   173 0000005C 5B                      	pop bx
   174                                  
   175 0000005D B402                    	mov ah, 02h
   176 0000005F B20D                    	mov dl, 13
   177 00000061 CD21                    	int 21h
   178 00000063 B402                    	mov ah, 02h
   179 00000065 B20A                    	mov dl, 10
   180 00000067 CD21                    	int 21h
   181                                  
   182 00000069 5F                      	 pop di
   183 0000006A 83C708                  	add di, COMPROGRAMLIST_ENTRY_size
   184 0000006D EB9E                    	jmp .loop
   185                                  
   186                                  .end:
   187 0000006F B8004C                  	mov ax, 4C00h
   188 00000072 CD21                    	int 21h
   189                                  
   190                                  .msg:
   191 00000074 436F6D6D616E642070-     	db "Command program names:",13,10,36
   191 0000007D 726F6772616D206E61-
   191 00000086 6D65733A0D0A24     
   192                                  
   193                                  
   194                                  	numdef COMPRESSEDCOMLOADER, 1
   195                                  
   196 0000008D 26<rep 3h>              nextcomprogram COMINSTSECT, "INSTSECT", "installs boot sectors to drives"
   197                                  %if _COMPRESSEDCOMLOADER
   198 00000000 <bin 344Ch>             	incbin "bin/instsect.exe"
   199                                  %else
   200                                  	incbin "bin/instsect.com"
   201                                  %endif
   202                                  
   203                                  
   204 0000344C 26<rep 4h>              nextcomprogram COMPATLDOS, "PATLDOS", "patches ldos.com kernel file (lCFG block)"
   205                                  %if _COMPRESSEDCOMLOADER
   206 00000000 <bin 54DCh>             	incbin "bin/patldos.exe"
   207                                  %else
   208                                  	incbin "bin/patldos.com"
   209                                  %endif
   210                                  
   211                                  
   212 000054DC 26<rep 4h>              nextcomprogram COMVERSION, "VERSION", "lists the version of this kernel file"
   213 00000000 <bin 48h>               	incbin "tmp/version.com"
   214                                  
   215                                  
   216                                  %if _MCP
   217                                  nextcomprogram COMDEBUG, "DEBUG", "lDebug 86-DOS debugger"
   218                                  %endif
   219                                  
   220                                  
   221 00000048 26<rep 8h>              nextcomprogram COMLOADER, "", "", vstart=0
   222                                  		; INP:	ds = es = PSP
   223                                  		;	cs:ip = COMLOADER segment : 0
   224                                  		;	ss:sp -> stack behind COMLOADER
   225 00000000 CC                      	int3
   226                                  %if _MZEXESUPPORT
   227 00000001 EB0A                    	jmp @F
   228                                  relocatecomloader: equ $
   229 00000003 F3A5                    	rep movsw		; move downwards
   230 00000005 06                      	push es
   231 00000006 E80300                  	call .retf		; relocate
   232 00000009 E99D01                  	jmp donerelocatedcomloader
   233                                  				; continue at relocated comloader
   234                                  .retf:
   235 0000000C CB                      	retf
   236                                  
   237                                  %if ($ - relocatecomloader) > 16
   238                                   %error Relocate comloader is too large
   239                                  %endif
   240                                  
   241                                  
   242                                  @@:
   243                                  %endif
   244 0000000D 06                      	push es
   245 0000000E 1F                      	pop ds
   246 0000000F BE8100                  	mov si, 81h		; PSP command line
   247                                  @@:
   248 00000012 AC                      	lodsb
   249 00000013 3C09                    	cmp al, 9
   250 00000015 74FB                    	je @B
   251 00000017 3C20                    	cmp al, 32
   252 00000019 74F7                    	je @B			; skip leading spaces -->
   253 0000001B 7242                    	jb .no_name_given	; end of line ? -->
   254                                  
   255 0000001D 89F7                    	mov di, si
   256 0000001F 4F                      	dec di			; -> name
   257                                  
   258 00000020 A8                      	db __TEST_IMM8
   259                                  @@:
   260 00000021 AC                      	lodsb
   261 00000022 3C61                    	cmp al, 'a'
   262 00000024 7209                    	jb @F
   263 00000026 3C7A                    	cmp al, 'z'
   264 00000028 7705                    	ja @F
   265 0000002A 2C20                    	sub al, 'a' - 'A'
   266 0000002C 8844FF                  	mov byte [si - 1], al
   267                                  @@:
   268 0000002F 3C20                    	cmp al, 32
   269 00000031 77EE                    	ja @BB
   270 00000033 C644FF00                	mov byte [si - 1], 0	; ! al preserved here until after .got_it
   271                                  
   272 00000037 89F1                    	mov cx, si
   273 00000039 29F9                    	sub cx, di
   274                                  
   275 0000003B 0E                      	push cs
   276 0000003C 1F                      	pop ds
   277 0000003D BE[3004]                	mov si, programstable
   278                                  
   279                                  .loop:
   280                                  %if _MCP
   281                                  	cmp word [si + cplLength], -1
   282                                  %else
   283 00000040 837C0200                	cmp word [si + cplLength], 0		; empty payload ?
   284                                  %endif
   285 00000044 7503E9F901              	je .error_unknown_name_given		; yes, end of table -->
   286                                  
   287 00000049 51                      	push cx
   288 0000004A 56                      	push si
   289 0000004B 57                      	push di
   290 0000004C 8B7404                  	mov si, word [si + cplNameString]
   291 0000004F 81C6[3004]              	add si, programstable
   292 00000053 F3A6                    	repe cmpsb		; this command ?
   293 00000055 5F                      	pop di
   294 00000056 5E                      	pop si
   295 00000057 59                      	pop cx
   296 00000058 7416                    	je .got_it
   297                                  
   298 0000005A 83C608                  	add si, COMPROGRAMLIST_ENTRY_size
   299 0000005D EBE1                    	jmp .loop
   300                                  
   301                                  .no_name_given:
   302 0000005F 0E                      	push cs
   303 00000060 1F                      	pop ds
   304                                  %if _MCP
   305                                  	mov si, COMDEBUG_list_entry
   306                                  
   307                                  	push cs
   308                                  	pop ds
   309                                  	mov dx, msg.intro	; -> .msg
   310                                  	mov ah, 09h
   311                                  	int 21h			; display
   312                                  
   313                                  	mov dx, msg.loading_before
   314                                  	mov ah, 09h
   315                                  	int 21h
   316                                  
   317                                  	mov dx, word [si + cplNameString]
   318                                  	add dx, programstable
   319                                  	xor cx, cx
   320                                  	mov bx, dx
   321                                  	mov ax, 4000h
   322                                  	dw __TEST_IMM16		; skip two inc
   323                                  @@:
   324                                  	inc bx
   325                                  	inc cx
   326                                  	cmp al, [bx]
   327                                  	jne @B
   328                                  	mov bx, 1
   329                                  	int 21h
   330                                  
   331                                  	mov dx, msg.loading_after
   332                                  	mov ah, 09h
   333                                  	int 21h
   334                                  %else
   335 00000061 BE[5804]                	mov si, COMVERSION_list_entry
   336 00000064 8B1C                    	mov bx, word [si + cplPositionSeg]
   337                                  				; address (paragraphs from after INIT3 end MCB)
   338                                  %endif
   339 00000066 FF7402                  	push word [si + cplLength]
   340                                  				; number of words/paras
   341                                  
   342 00000069 06                      	push es
   343 0000006A 1F                      	pop ds			; => PSP
   344                                  
   345 0000006B BE8100                  	mov si, 81h
   346 0000006E EB3D                    	jmp .common
   347                                  
   348                                  .got_it:
   349 00000070 8B1C                    	mov bx, word [si + cplPositionSeg]
   350                                  				; address (paragraphs from after INIT3 end MCB)
   351 00000072 FF7402                  	push word [si + cplLength]
   352                                  				; number of words/paras
   353                                  
   354 00000075 49                      	dec cx
   355 00000076 50                      	 push ax
   356 00000077 53                      	 push bx
   357 00000078 81FE[5804]              	cmp si, COMVERSION_list_entry
   358 0000007C 7427                    	je @F
   359 0000007E 0E                      	push cs
   360 0000007F 1F                      	pop ds
   361 00000080 BA[3203]                	mov dx, msg.intro	; -> .msg
   362 00000083 B409                    	mov ah, 09h
   363 00000085 CD21                    	int 21h			; display
   364                                  
   365 00000087 BA[4103]                	mov dx, msg.loading_before
   366 0000008A B409                    	mov ah, 09h
   367 0000008C CD21                    	int 21h
   368                                  
   369 0000008E 8B5404                  	mov dx, word [si + cplNameString]
   370 00000091 81C2[3004]              	add dx, programstable
   371 00000095 B440                    	mov ah, 40h
   372 00000097 BB0100                  	mov bx, 1
   373 0000009A CD21                    	int 21h
   374                                  
   375 0000009C BA[5D03]                	mov dx, msg.loading_after
   376 0000009F B409                    	mov ah, 09h
   377 000000A1 CD21                    	int 21h
   378                                  
   379 000000A3 06                      	push es
   380 000000A4 1F                      	pop ds			; => PSP
   381                                  
   382                                  @@:
   383 000000A5 01CF                    	add di, cx
   384 000000A7 89FE                    	mov si, di
   385 000000A9 5B                      	 pop bx
   386 000000AA 58                      	 pop ax
   387 000000AB 8804                    	mov byte [si], al	; ! preserved from before .loop
   388                                  
   389                                  .common:
   390 000000AD BF8100                  	mov di, 81h
   391 000000B0 B97F00                  	mov cx, 7Fh
   392 000000B3 F3A4                    	rep movsb		; move down the command line trail
   393                                  
   394 000000B5 BF8100                  	mov di, 81h
   395 000000B8 B97F00                  	mov cx, 7Fh
   396 000000BB B00D                    	mov al, 13
   397 000000BD F2AE                    	repne scasb
   398                                  ; COUNTER ->13, cx=7Fh, di=81h
   399                                  ; scasb
   400                                  ; COUNTER 13 ->, ZR, cx=7Eh, di=82h
   401 000000BF F7D9                    	neg cx
   402                                  ; cx=-7Eh
   403 000000C1 83C17E                  	add cx, 7Eh
   404                                  ; cx=0
   405                                  
   406                                  ; COUNTER ->32, 13, cx=7Fh, di=81h
   407                                  ; scasb
   408                                  ; COUNTER 32 ->13, NZ, cx=7Eh, di=82h
   409                                  ; scasb
   410                                  ; COUNTER 32 13 ->, ZR, cx=7Dh, di=83h
   411                                  	; neg cx
   412                                  ; cx=-7Dh
   413                                  	; add cx, 7Eh
   414                                  ; cx=1
   415 000000C4 880E8000                	mov byte [80h], cl	; update command line trail length
   416                                  
   417                                  %ifn _MZEXESUPPORT
   418                                  	mov di, 256
   419                                  %endif
   420 000000C8 59                      	pop cx			; number of words/paras (cplLength)
   421 000000C9 8CC8                    	mov ax, cs
   422 000000CB 2DA508                  	sub ax, (COMLOADER_position >> 4)
   423 000000CE 01D8                    	add ax, bx		; address => source
   424                                  
   425 000000D0 50                      	push ax
   426 000000D1 BE8100                  	mov si, 81h		; -> edited command line tail
   427 000000D4 E83902                  	call parse_dssi_cmdline_to_es_fcbs
   428                                  				; es = ds => PSP, fill FCBs
   429 000000D7 58                      	pop ax
   430 000000D8 53                      	push bx			; push bx = drive validity flags
   431                                  
   432                                  %if _MZEXESUPPORT
   433 000000D9 8CC2                    	mov dx, es
   434 000000DB 83C210                  	add dx, 10h		; => behind PSP
   435 000000DE E87801                  	call movp
   436                                  
   437 000000E1 8EDA                    	mov ds, dx		; => at MZ exe header if any
   438 000000E3 31DB                    	xor bx, bx		; -> at header
   439 000000E5 813F4D5A                	cmp word [bx + exeSignature], "MZ"
   440 000000E9 7409                    	je .load_exe
   441 000000EB 813F5A4D                	cmp word [bx + exeSignature], "ZM"
   442 000000EF 7403E9FC00              	jne .load_com
   443                                  .load_exe:
   444 000000F4 06                      	push es
   445 000000F5 8B4F06                  	mov cx, word [bx + exeRelocItems]
   446 000000F8 1E                      	push ds
   447 000000F9 E327                    	jcxz .donereloc
   448 000000FB 8B7718                  	mov si, word [bx + exeRelocTable]
   449                                  				; ds:si -> reloc table
   450                                  				;  (may overflow 64 KiB but starts within first)
   451 000000FE 89D5                    	mov bp, dx
   452 00000100 036F08                  	add bp, word [bx + exeHeaderSize]
   453                                  				; bp => exe image (after header)
   454                                  .loopreloc:
   455 00000103 89F0                    	mov ax, si		; preserve upper 12 bits
   456 00000105 83E60F                  	and si, 15		; isolate low 4 bits
   457 00000108 D1E8                    	shr ax, 1
   458 0000010A D1E8                    	shr ax, 1
   459 0000010C D1E8                    	shr ax, 1
   460 0000010E D1E8                    	shr ax, 1		; divide by 16
   461 00000110 8CDF                    	mov di, ds
   462 00000112 01C7                    	add di, ax		; => normalised relocation table entry
   463 00000114 8EDF                    	mov ds, di
   464 00000116 AD                      	lodsw			; load offset
   465 00000117 97                      	xchg di, ax		; di = offset
   466 00000118 AD                      	lodsw			; load segment
   467 00000119 01E8                    	add ax, bp		; => relocation entry in exe image (after header)
   468 0000011B 8EC0                    	mov es, ax		; es:di -> relocation entry
   469 0000011D 260115                  	add word [es:di], dx	; relocate (with dx => behind PSP)
   470 00000120 E2E1                    	loop .loopreloc		; loop for all relocations
   471                                  .donereloc:
   472 00000122 1F                      	pop ds			; => exe header
   473 00000123 8B6F04                  	mov bp, word [bx + exePages]
   474 00000126 B105                    	mov cl, 5
   475 00000128 D3E5                    	shl bp, cl		; = how many paragraphs in header + image
   476 0000012A 8B4708                  	mov ax, word [bx + exeHeaderSize]
   477 0000012D 29C5                    	sub bp, ax		; = how many paragraphs in image
   478 0000012F 7703E9D900              	jbe error_format
   479                                  		; lMS-DOS doesn't ever use exeExtraBytes.
   480                                  		;  we can ignore it likewise.
   481 00000134 89E9                    	mov cx, bp
   482 00000136 01D0                    	add ax, dx		; => exe image
   483 00000138 7303E9D000              	jc error_format
   484 0000013D 07                      	pop es			; => PSP
   485 0000013E 015716                  	add word [bx + exeInitCS], dx
   486 00000141 01570E                  	add word [bx + exeInitSS], dx
   487                                  		; on stack: original ax
   488 00000144 FF7716                  	push word [bx + exeInitCS]
   489 00000147 FF7714                  	push word [bx + exeInitIP]
   490 0000014A FF770E                  	push word [bx + exeInitSS]
   491 0000014D FF7710                  	push word [bx + exeInitSP]
   492 00000150 FF770A                  	push word [bx + exeMinAlloc]
   493 00000153 FF770C                  	push word [bx + exeMaxAlloc]
   494 00000156 E80001                  	call movp
   495                                  
   496 00000159 01CA                    	add dx, cx		; => behind exe image at destination
   497 0000015B 7303E9AD00              	jc error_format
   498 00000160 5B                      	pop bx			; max alloc
   499 00000161 58                      	pop ax			; min alloc
   500 00000162 39D8                    	cmp ax, bx		; minimum > maximum ?
   501 00000164 7603E9A400              	ja error_format
   502 00000169 85DB                    	test bx, bx		; maximum == 0 ?
   503 0000016B 7503E99D00              	jz error_format		; not supported -->
   504 00000170 01CB                    	add bx, cx		; bx = maximum allocation size (maxalloc + image)
   505 00000172 7205                    	jc .unlimited
   506 00000174 83C310                  	add bx, 10h		; account for PSP
   507 00000177 7303                    	jnc @F
   508                                  .unlimited:
   509 00000179 BBFFFF                  	mov bx, -1		; if maximum requested, pass along bx = 0FFFFh
   510                                  @@:
   511 0000017C 01C2                    	add dx, ax		; dx => behind minimum allocation
   512 0000017E 7303E98A00              	jc error_format
   513                                  
   514 00000183 06                      	push es			; preserve => PSP
   515 00000184 8CC8                    	mov ax, cs
   516 00000186 39D0                    	cmp ax, dx
   517 00000188 7320                    	jae .noreloc
   518 0000018A 8CD1                    	mov cx, ss
   519 0000018C 83E956                  	sub cx, paras(COMLOADER_end - COMLOADER_start)
   520 0000018F 39C8                    	cmp ax, cx
   521 00000191 7375                    	jae error_memory
   522 00000193 39D1                    	cmp cx, dx
   523 00000195 7276                    	jb error_format
   524 00000197 8EC1                    	mov es, cx		; => comloader destination
   525 00000199 0E                      	push cs
   526 0000019A 1F                      	pop ds			; => comloader source
   527 0000019B B9B002                  	mov cx, words(COMLOADER_end - COMLOADER_start)
   528 0000019E 89CE                    	mov si, cx		; = amount words
   529 000001A0 01F6                    	add si, si		; = amount bytes
   530 000001A2 89F7                    	mov di, si		; -> after last byte to move
   531 000001A4 FD                      	std
   532 000001A5 A7                      	cmpsw			; -> at last word to move
   533 000001A6 E95AFE                  	jmp relocatecomloader	; do rep movsw and far branch to relocated
   534                                  
   535                                  donerelocatedcomloader: equ $	; returns control flow here from relocator
   536 000001A9 FC                      	cld			; UP !
   537                                  .noreloc:
   538 000001AA 58                      	pop ax			; ax => PSP
   539                                  				; bx = requested maximum allocation size
   540                                  
   541 000001AB 5F                      	pop di
   542 000001AC 5D                      	pop bp			; bp:di = stack
   543                                  
   544 000001AD 0E                      	push cs
   545 000001AE 1F                      	pop ds
   546 000001AF BE[DC01]                	mov si, .enterstub	; -> stub source
   547 000001B2 8F4402                  	pop word [si + .enterstub_ip]
   548 000001B5 8F4404                  	pop word [si + .enterstub_cs]
   549                                  				; set cs:ip
   550 000001B8 8F04                    	pop word [si + .enterstub_ax]
   551                                  				; set ax (from our entrypoint)
   552                                  
   553 000001BA 8EC5                    	mov es, bp		; => stack destination
   554 000001BC B91400                  	mov cx, .enterstub_size_w * 2
   555 000001BF 29CF                    	sub di, cx		; -> space for stub
   556 000001C1 D1E9                    	shr cx, 1		; = amount words
   557 000001C3 57                      	 push di
   558 000001C4 F3A5                    	rep movsw		; place stub
   559 000001C6 5F                      	 pop di			; bp:di -> stub
   560 000001C7 8EC0                    	mov es, ax		; es => PSP
   561 000001C9 8ED8                    	mov ds, ax		; ds => PSP
   562 000001CB FA                      	cli
   563 000001CC 8ED5                    	mov ss, bp
   564 000001CE 89FC                    	mov sp, di		; relocate stack
   565 000001D0 FB                      	sti
   566 000001D1 8D4506                  	lea ax, [di + .enterstub_entry]	; ss:ax -> stub entry
   567 000001D4 16                      	push ss
   568 000001D5 50                      	push ax			; -> stub's entry on stack
   569 000001D6 BF0200                  	mov di, 2		; es:di -> PSP word at [2]
   570 000001D9 B44A                    	mov ah, 4Ah		; ah = 4Ah
   571 000001DB CB                      	retf			; branch to there
   572                                  
   573                                  	align 2, nop
   574                                  .enterstub:
   575                                  .enterstub_ax: equ $ - .enterstub
   576 000001DC 0000                    	dw 0
   577                                  .enterstub_ip: equ $ - .enterstub
   578 000001DE 0000                    	dw 0
   579                                  .enterstub_cs: equ $ - .enterstub
   580 000001E0 0000                    	dw 0
   581                                  
   582                                  		; INP:	es = ds => PSP
   583                                  		;	bx = maximum allocation size
   584                                  		;	MCB already >= minimum allocation size
   585                                  		;	ah = 4Ah
   586                                  		;	di = 2
   587                                  		;	ss:sp -> stack with ax, ip, cs, stub
   588                                  .enterstub_entry: equ $ - .enterstub
   589 000001E2 CC                      		int3
   590 000001E3 CD21                    	int 21h
   591 000001E5 8CC0                    	mov ax, es		; => PSP
   592 000001E7 01D8                    	add ax, bx		; => behind allocation
   593 000001E9 AB                      	stosw			; store in word [PSP:2]
   594 000001EA 58                      	pop ax			; pass through ax
   595 000001EB CA0E00                  	retf .enterstub_size - 6; branch to entry and pop off the enterstub
   596 000001EE 90                      	nop	; Better cure for https://github.com/dosemu2/dosemu2/issues/2575
   597 000001EF 90                      	align 2, nop
   598                                  	endarea .enterstub
   599                                  
   600                                  .load_com:
   601                                  %if _MCP
   602                                  	jcxz mcp_debug_transfer
   603                                  %endif
   604                                  
   605                                  %else
   606                                  %if _MCP
   607                                  	jcxz mcp_debug_transfer
   608                                  %endif
   609                                  
   610                                  	mov ds, ax
   611                                  	xor si, si		; ds:si -> source
   612                                  
   613                                  %if 01
   614                                  	cmp word [si + exeSignature], "MZ"
   615                                  	je error_mz_exe_not_supported
   616                                  	cmp word [si + exeSignature], "ZM"
   617                                  	je error_mz_exe_not_supported
   618                                  %endif
   619                                  
   620                                  	push di
   621                                  	rep movsw		; move to behind PSP
   622                                  %endif
   623                                  
   624 000001F0 BB[3004]                	mov bx, programstable	; cx:bx -> command program name table
   625                                  				; (used by the associated COMLIST program)
   626                                  
   627 000001F3 8CC7                    	mov di, es
   628 000001F5 81C70010                	add di, 1000h		; => behind area to be used by stack
   629 000001F9 8CC8                    	mov ax, cs		; => COMLOADER segment
   630 000001FB 39F8                    	cmp ax, di		; COMLOADER starts above-or-equal stack end ?
   631 000001FD 7313                    	jae @F
   632                                  
   633 000001FF 8CD0                    	mov ax, ss
   634 00000201 83E815                  	sub ax, .to_reloc_size_p + programstable_size_p
   635 00000204 39F8                    	cmp ax, di
   636 00000206 731E                    	jae .reloc
   637                                  
   638                                  error_memory: equ $
   639 00000208 BA[B503]                	mov dx, msg.internal_error_memory
   640 0000020B EB41                    	jmp .error_exit
   641                                  
   642                                  %if _MZEXESUPPORT
   643                                  error_format: equ $
   644 0000020D BA[F003]                	mov dx, msg.internal_error_format
   645 00000210 EB3C                    	jmp .error_exit
   646                                  %elif 01
   647                                  error_mz_exe_not_supported: equ $
   648                                  	mov dx, msg.internal_error_mz
   649                                  	jmp .error_exit
   650                                  %endif
   651                                  
   652                                  @@:
   653                                  .to_reloc:
   654                                  %if _MZEXESUPPORT
   655 00000212 BF0001                  	mov di, 100h
   656                                  %else
   657                                  	pop di
   658                                  %endif
   659 00000215 58                      	pop ax			; preserve original ax
   660                                  
   661 00000216 06                      	push es
   662 00000217 FA                      	cli
   663 00000218 17                      	pop ss
   664 00000219 31E4                    	xor sp, sp		; full 64 KiB's stack
   665 0000021B FB                      	sti
   666 0000021C 31F6                    	xor si, si		; si = 0
   667 0000021E 56                      	push si			; 0 word on stack
   668                                  
   669 0000021F 06                      	 push es
   670 00000220 1F                      	 pop ds			; ds = es = ss = cs = PSP
   671                                  
   672 00000221 8CC9                    	mov cx, cs		; => name table
   673                                  
   674 00000223 06                      	push es
   675 00000224 57                      	push di			; -> PSP : 256
   676 00000225 CB                      	retf
   677                                  	endarea .to_reloc
   678                                  
   679                                  
   680                                  .reloc:
   681 00000226 06                      	push es
   682 00000227 8EC0                    	mov es, ax
   683 00000229 31FF                    	xor di, di
   684 0000022B B91000                  	mov cx, words(fromparas(.to_reloc_size_p))
   685 0000022E 0E                      	push cs
   686 0000022F 1F                      	pop ds
   687 00000230 BE[1202]                	mov si, .to_reloc
   688 00000233 F3A5                    	rep movsw
   689 00000235 89DE                    	mov si, bx
   690 00000237 89FB                    	mov bx, di
   691 00000239 B99800                  	mov cx, words(fromparas(programstable_size_p))
   692 0000023C F3A5                    	rep movsw
   693 0000023E 07                      	pop es
   694 0000023F 50                      	push ax
   695 00000240 51                      	push cx
   696 00000241 CB                      	retf
   697                                  
   698                                  
   699                                  .error_unknown_name_given:
   700 00000242 0E                      	push cs
   701 00000243 1F                      	pop ds
   702 00000244 BA[3203]                	mov dx, msg.intro	; -> .msg
   703 00000247 B409                    	mov ah, 09h
   704 00000249 CD21                    	int 21h			; display
   705 0000024B BA[8703]                	mov dx, msg.unknown_name_given
   706                                  
   707                                  .error_exit:
   708 0000024E 0E                      	push cs
   709 0000024F 1F                      	pop ds
   710 00000250 B409                    	mov ah, 09h
   711 00000252 CD21                    	int 21h
   712 00000254 B8014C                  	mov ax, 4C01h
   713 00000257 CD21                    	int 21h
   714                                  
   715                                  
   716                                  %if _MCP
   717                                  mcp_debug_transfer:
   718                                  	pop ax			; drive validity flag
   719                                  	push es
   720                                  	pop ds
   721                                  	push es
   722                                  	mov bx, 256+64
   723                                  	push bx
   724                                  	retf
   725                                  %endif
   726                                  
   727                                  
   728                                  %if _MZEXESUPPORT
   729                                  		; Move paragraphs
   730                                  		;
   731                                  		; INP:	ax:0-> source
   732                                  		;	dx:0-> destination
   733                                  		;	cx = number of paragraphs
   734                                  		; CHG:	-
   735                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
   736                                  		;	Do not provide a wrapped/HMA source or destination!
   737                                  movp:
   738 00000259 51                      	push cx
   739 0000025A 1E                      	push ds
   740 0000025B 56                      	push si
   741 0000025C 06                      	push es
   742 0000025D 57                      	push di
   743                                  
   744 0000025E 39D0                    	cmp ax, dx		; source above destination ?
   745 00000260 770A                    	ja .up			; yes, move up (forwards) -->
   746 00000262 747B                    	je .return		; same, no need to move -->
   747 00000264 50                      	push ax
   748 00000265 01C8                    	add ax, cx		; (expected not to carry)
   749 00000267 39D0                    	cmp ax, dx		; end of source is above destination ?
   750 00000269 58                      	pop ax
   751 0000026A 7730                    	ja .down		; yes, move from top down -->
   752                                  	; Here, the end of source is below-or-equal the destination,
   753                                  	;  so they do not overlap. In this case we prefer moving up.
   754                                  
   755                                  .up:
   756 0000026C 50                      	push ax
   757 0000026D 52                      	push dx
   758                                  .uploop:
   759 0000026E 8ED8                    	mov ds, ax
   760 00000270 8EC2                    	mov es, dx
   761 00000272 31FF                    	xor di, di
   762 00000274 31F6                    	xor si, si		; -> start of segment
   763 00000276 81E90010                	sub cx, 1000h		; 64 KiB left ?
   764 0000027A 7610                    	jbe .uplast		; no -->
   765 0000027C 51                      	push cx
   766 0000027D B90080                  	mov cx, 10000h /2
   767 00000280 F3A5                    	rep movsw		; move 64 KiB
   768 00000282 59                      	pop cx
   769 00000283 050010                  	add ax, 1000h
   770 00000286 81C20010                	add dx, 1000h		; -> next segment
   771 0000028A EBE2                    	jmp short .uploop	; proceed for more -->
   772                                  .uplast:
   773 0000028C 81C10010                	add cx, 1000h		; restore counter
   774 00000290 D1E1                    	shl cx, 1
   775 00000292 D1E1                    	shl cx, 1
   776 00000294 D1E1                    	shl cx, 1		; *8, paragraphs to words
   777 00000296 F3A5                    	rep movsw		; move last part
   778 00000298 5A                      	pop dx
   779 00000299 58                      	pop ax
   780 0000029A EB43                    	jmp short .return
   781                                  
   782                                  .down:
   783 0000029C FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   784                                  .dnloop:
   785 0000029D 81E90010                	sub cx, 1000h		; 64 KiB left ?
   786 000002A1 761A                    	jbe .dnlast		; no -->
   787 000002A3 50                      	push ax
   788 000002A4 52                      	push dx
   789 000002A5 01C8                    	add ax, cx
   790 000002A7 01CA                    	add dx, cx
   791 000002A9 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   792 000002AB 8EC2                    	mov es, dx
   793 000002AD 5A                      	pop dx
   794 000002AE 58                      	pop ax
   795 000002AF BFFEFF                  	mov di, -2
   796 000002B2 89FE                    	mov si, di		; moved from last word down
   797 000002B4 51                      	push cx
   798 000002B5 B90080                  	mov cx, 10000h /2
   799 000002B8 F3A5                    	rep movsw		; move 64 KiB
   800 000002BA 59                      	pop cx
   801 000002BB EBE0                    	jmp short .dnloop	; proceed for more -->
   802                                  .dnlast:
   803 000002BD 81C10010                	add cx, 1000h		; restore counter
   804 000002C1 D1E1                    	shl cx, 1
   805 000002C3 D1E1                    	shl cx, 1
   806 000002C5 D1E1                    	shl cx, 1		; *8, paragraphs to words
   807 000002C7 89CF                    	mov di, cx
   808 000002C9 4F                      	dec di
   809 000002CA D1E7                    	shl di, 1		; words to offset, -> last word
   810 000002CC 89FE                    	mov si, di
   811 000002CE 8ED8                    	mov ds, ax
   812 000002D0 8EC2                    	mov es, dx		; first segment correct
   813                                  
   814                                  
   815                                  	numdef AMD_ERRATUM_109_WORKAROUND, 1
   816                                  		; Refer to comment in init.asm init_movp.
   817                                  
   818                                  %if _AMD_ERRATUM_109_WORKAROUND
   819 000002D2 E308                    	jcxz @FF
   820 000002D4 83F914                  	cmp cx, 20
   821 000002D7 7703                    	ja @FF
   822                                  @@:
   823 000002D9 A5                      	movsw
   824 000002DA E2FD                    	loop @B
   825                                  @@:
   826                                  %endif
   827 000002DC F3A5                    	rep movsw		; move first part
   828 000002DE FC                      	cld
   829                                  .return:
   830 000002DF 5F                      	pop di
   831 000002E0 07                      	pop es
   832 000002E1 5E                      	pop si
   833 000002E2 1F                      	pop ds
   834 000002E3 59                      	pop cx
   835 000002E4 C3                      	retn
   836                                  %endif
   837                                  
   838                                  
   839                                  DELIM1:
   840 000002E5 3C20                    	CMP	AL, 32		; SKIP THESE GUYS
   841 000002E7 7415                    	je @F
   842 000002E9 3C3A                    	CMP	AL, ':'
   843 000002EB 7411                    	je @F
   844 000002ED 3C3D                    	CMP	AL, '='
   845 000002EF 740D                    	je @F
   846 000002F1 3C09                    	CMP	AL, 9
   847 000002F3 7409                    	je @F
   848 000002F5 3C2C                    	CMP	AL, ','
   849 000002F7 C3                      	retn
   850                                  DELIM2:
   851 000002F8 38D0                    	CMP	AL, dl		; STOP ON THESE GUYS
   852 000002FA 7402                    	je @F
   853 000002FC 3C0D                    	CMP	AL, 13
   854                                  @@:
   855 000002FE C3                      	retn
   856                                  
   857                                  SKIP_FILE:
   858 000002FF B437                    	MOV	AH, 37h
   859 00000301 CD21                    	INT	21H			; dl = GET THE CURRENT SWITCH CHARACTER
   860                                  FIND_DELIM:
   861 00000303 AC                      	LODSB
   862 00000304 E8DEFF                  	CALL	DELIM1
   863 00000307 7405                    	JZ	GOTDELIM
   864 00000309 E8ECFF                  	CALL	DELIM2
   865 0000030C 75F5                    	JNZ	FIND_DELIM
   866                                  GOTDELIM:
   867 0000030E 4E                      	DEC	SI
   868 0000030F C3                      	retn
   869                                  
   870                                  		; INP:	ds:si -> command line tail
   871                                  		;	es => PSP
   872                                  		;	es:5Ch -> first FCB to fill
   873                                  		;	es:6Ch -> second FCB to fill
   874                                  		; OUT:	bx = drive validity flags
   875                                  		; CHG:	di, si, ax, dx
   876                                  parse_dssi_cmdline_to_es_fcbs:
   877 00000310 BF5C00                  	MOV	DI, 5Ch
   878 00000313 B80129                  	MOV	AX, 2901h
   879 00000316 CD21                    	INT	21H
   880 00000318 3C01                    	cmp al, 1
   881 0000031A 7501                    	jne @F
   882 0000031C 48                      	dec ax				; al = 0
   883                                  @@:
   884 0000031D 88C3                    	mov bl, al			; Indicate analysis of first parm
   885 0000031F E8DDFF                  	CALL	SKIP_FILE
   886                                  
   887 00000322 BF6C00                  	MOV	DI, 6Ch
   888 00000325 B80129                  	MOV	AX, 2901h
   889 00000328 CD21                    	INT	21H
   890 0000032A 3C01                    	cmp al, 1
   891 0000032C 7501                    	jne @F
   892 0000032E 48                      	dec ax				; al = 0
   893                                  @@:
   894 0000032F 88C7                    	mov bh, al			; Indicate analysis of second parm
   895 00000331 C3                      	retn
   896                                  
   897                                  
   898                                  msg:
   899 00000332 6C444F5320434F4D4C-     .intro:	db "lDOS COMLOADER",36
   899 0000033B 4F4144455224       
   900                                  .loading_before:
   901 00000341 202D206C6F6164696E-     	db " - loading command program ",36
   901 0000034A 6720636F6D6D616E64-
   901 00000353 2070726F6772616D20-
   901 0000035C 24                 
   902                                  .loading_after:
   903 0000035D 0D0A24                  	db 13,10,36
   904                                  .no_name_given:
   905 00000360 0D0A4E6F20636F6D6D-     	db 13,10,"No command program name specified!",13,10,36
   905 00000369 616E642070726F6772-
   905 00000372 616D206E616D652073-
   905 0000037B 706563696669656421-
   905 00000384 0D0A24             
   906                                  .unknown_name_given:
   907 00000387 0D0A53706563696669-     	db 13,10,"Specified command program name not found!",13,10,36
   907 00000390 656420636F6D6D616E-
   907 00000399 642070726F6772616D-
   907 000003A2 206E616D65206E6F74-
   907 000003AB 20666F756E64210D0A-
   907 000003B4 24                 
   908                                  .internal_error_memory:
   909 000003B5 0D0A496E7465726E61-     	db 13,10,"Internal error, lacking memory for nonrelocated stack."
   909 000003BE 6C206572726F722C20-
   909 000003C7 6C61636B696E67206D-
   909 000003D0 656D6F727920666F72-
   909 000003D9 206E6F6E72656C6F63-
   909 000003E2 617465642073746163-
   909 000003EB 6B2E               
   910 000003ED 0D0A24                  	db 13,10,36
   911                                  %if _MZEXESUPPORT
   912                                  .internal_error_format:
   913 000003F0 0D0A496E7465726E61-     	db 13,10,"Internal error, MZ exe has invalid header or too large."
   913 000003F9 6C206572726F722C20-
   913 00000402 4D5A20657865206861-
   913 0000040B 7320696E76616C6964-
   913 00000414 20686561646572206F-
   913 0000041D 7220746F6F206C6172-
   913 00000426 67652E             
   914 00000429 0D0A24                  	db 13,10,36
   915                                  %elif 01
   916                                  .internal_error_mz:
   917                                  	db 13,10,"Internal error, MZ exe not supported."
   918                                  	db 13,10,36
   919                                  %endif
   920                                  
   921 0000042C 90<rep 4h>              	align 8
   922                                  programstable:
   923                                  ..@base:
   924                                  	comprogramlist COMMAND_LIST
    57                              <1> %if (%0 % 3) != 0 || %0 < 6
    58                              <1>  %error Expected number of parameters a multiple of 3 and at least 6
    59                              <1> %endif
    60                              <1> %rep (%0 - 6) / 3
    61                              <1> %rotate 3
    62                              <1> %1_list_entry:
    63                              <1>  istruc COMPROGRAMLIST_ENTRY
    64                              <1> at cplPositionSeg, dw %1_position >> 4
    65                              <1> %if _MZEXESUPPORT
    66                              <1> at cplLengthParas, dw (%1_end - %1_start) >> 4
    67                              <1> %else
    68                              <1> at cplLengthWords, dw (%1_end - %1_start) >> 1
    69                              <1> %endif
    70                              <1> at cplNameString, dw msg_name.%1 - ..@base
    71                              <1> at cplHelpString, dw msg_help.%1 - ..@base
    72                              <1>  iend
    73                              <1> %endrep
    61                              <2> %rotate 3
    62                              <2> %1_list_entry:
    63                              <2>  istruc COMPROGRAMLIST_ENTRY
    64 00000430 0000                <2> at cplPositionSeg, dw %1_position >> 4
    65                              <2> %if _MZEXESUPPORT
    66 00000432 0300                <2> at cplLengthParas, dw (%1_end - %1_start) >> 4
    67                              <2> %else
    68                              <2> at cplLengthWords, dw (%1_end - %1_start) >> 1
    69                              <2> %endif
    70 00000434 3400                <2> at cplNameString, dw msg_name.%1 - ..@base
    71 00000436 3900                <2> at cplHelpString, dw msg_help.%1 - ..@base
    72                              <2>  iend
    61                              <2> %rotate 3
    62                              <2> %1_list_entry:
    63                              <2>  istruc COMPROGRAMLIST_ENTRY
    64 00000438 0300                <2> at cplPositionSeg, dw %1_position >> 4
    65                              <2> %if _MZEXESUPPORT
    66 0000043A 0100                <2> at cplLengthParas, dw (%1_end - %1_start) >> 4
    67                              <2> %else
    68                              <2> at cplLengthWords, dw (%1_end - %1_start) >> 1
    69                              <2> %endif
    70 0000043C 5B00                <2> at cplNameString, dw msg_name.%1 - ..@base
    71 0000043E 6100                <2> at cplHelpString, dw msg_help.%1 - ..@base
    72                              <2>  iend
    61                              <2> %rotate 3
    62                              <2> %1_list_entry:
    63                              <2>  istruc COMPROGRAMLIST_ENTRY
    64 00000440 0400                <2> at cplPositionSeg, dw %1_position >> 4
    65                              <2> %if _MZEXESUPPORT
    66 00000442 0900                <2> at cplLengthParas, dw (%1_end - %1_start) >> 4
    67                              <2> %else
    68                              <2> at cplLengthWords, dw (%1_end - %1_start) >> 1
    69                              <2> %endif
    70 00000444 7B00                <2> at cplNameString, dw msg_name.%1 - ..@base
    71 00000446 8000                <2> at cplHelpString, dw msg_help.%1 - ..@base
    72                              <2>  iend
    61                              <2> %rotate 3
    62                              <2> %1_list_entry:
    63                              <2>  istruc COMPROGRAMLIST_ENTRY
    64 00000448 0D00                <2> at cplPositionSeg, dw %1_position >> 4
    65                              <2> %if _MZEXESUPPORT
    66 0000044A 4503                <2> at cplLengthParas, dw (%1_end - %1_start) >> 4
    67                              <2> %else
    68                              <2> at cplLengthWords, dw (%1_end - %1_start) >> 1
    69                              <2> %endif
    70 0000044C 9D00                <2> at cplNameString, dw msg_name.%1 - ..@base
    71 0000044E A600                <2> at cplHelpString, dw msg_help.%1 - ..@base
    72                              <2>  iend
    61                              <2> %rotate 3
    62                              <2> %1_list_entry:
    63                              <2>  istruc COMPROGRAMLIST_ENTRY
    64 00000450 5203                <2> at cplPositionSeg, dw %1_position >> 4
    65                              <2> %if _MZEXESUPPORT
    66 00000452 4E05                <2> at cplLengthParas, dw (%1_end - %1_start) >> 4
    67                              <2> %else
    68                              <2> at cplLengthWords, dw (%1_end - %1_start) >> 1
    69                              <2> %endif
    70 00000454 C600                <2> at cplNameString, dw msg_name.%1 - ..@base
    71 00000456 CE00                <2> at cplHelpString, dw msg_help.%1 - ..@base
    72                              <2>  iend
    61                              <2> %rotate 3
    62                              <2> %1_list_entry:
    63                              <2>  istruc COMPROGRAMLIST_ENTRY
    64 00000458 A008                <2> at cplPositionSeg, dw %1_position >> 4
    65                              <2> %if _MZEXESUPPORT
    66 0000045A 0500                <2> at cplLengthParas, dw (%1_end - %1_start) >> 4
    67                              <2> %else
    68                              <2> at cplLengthWords, dw (%1_end - %1_start) >> 1
    69                              <2> %endif
    70 0000045C F800                <2> at cplNameString, dw msg_name.%1 - ..@base
    71 0000045E 0001                <2> at cplHelpString, dw msg_help.%1 - ..@base
    72                              <2>  iend
   925                                  %if _MCP
   926                                  	dw -1, -1
   927                                  %else
   928 00000460 00000000                	dw 0, 0
   929                                  %endif
   930                                  
   931                                  	comprogrammessages COMMAND_LIST
    77                              <1> %if (%0 % 3) != 0 || %0 < 6
    78                              <1>  %error Expected number of parameters a multiple of 3 and at least 6
    79                              <1> %endif
    80                              <1> %rep (%0 - 6) / 3
    81                              <1> %rotate 3
    82                              <1> msg_name.%1: asciz %2
    83                              <1> msg_help.%1: asciz %3
    84                              <1> %endrep
    81                              <2> %rotate 3
    82 00000464 494E543300          <2> msg_name.%1: asciz %2
    83 00000469 70726F6772616D2074- <2> msg_help.%1: asciz %3
    83 00000472 68617420627265616B- <2>
    83 0000047B 7320746F2061206465- <2>
    83 00000484 62756767657200      <2>
    81                              <2> %rotate 3
    82 0000048B 454D50545900        <2> msg_name.%1: asciz %2
    83 00000491 656D7074792070726F- <2> msg_help.%1: asciz %3
    83 0000049A 6772616D20666F7220- <2>
    83 000004A3 74657374696E6700    <2>
    81                              <2> %rotate 3
    82 000004AB 4C49535400          <2> msg_name.%1: asciz %2
    83 000004B0 6C6973747320616C6C- <2> msg_help.%1: asciz %3
    83 000004B9 20617661696C61626C- <2>
    83 000004C2 652070726F6772616D- <2>
    83 000004CB 7300                <2>
    81                              <2> %rotate 3
    82 000004CD 494E53545345435400  <2> msg_name.%1: asciz %2
    83 000004D6 696E7374616C6C7320- <2> msg_help.%1: asciz %3
    83 000004DF 626F6F742073656374- <2>
    83 000004E8 6F727320746F206472- <2>
    83 000004F1 6976657300          <2>
    81                              <2> %rotate 3
    82 000004F6 5041544C444F5300    <2> msg_name.%1: asciz %2
    83 000004FE 70617463686573206C- <2> msg_help.%1: asciz %3
    83 00000507 646F732E636F6D206B- <2>
    83 00000510 65726E656C2066696C- <2>
    83 00000519 6520286C4346472062- <2>
    83 00000522 6C6F636B2900        <2>
    81                              <2> %rotate 3
    82 00000528 56455253494F4E00    <2> msg_name.%1: asciz %2
    83 00000530 6C6973747320746865- <2> msg_help.%1: asciz %3
    83 00000539 2076657273696F6E20- <2>
    83 00000542 6F662074686973206B- <2>
    83 0000054B 65726E656C2066696C- <2>
    83 00000554 6500                <2>
   932                                  	endarea programstable
   933                                  
   934                                  
   935 00000556 26<rep Ah>              nextcomprogram COMNONE, "", ""
   936                                  
   937                                  %assign COMLOADERSIZE (COMLOADER_end - COMLOADER_start)
   938                                  %warning comloadersize=%[COMLOADERSIZE]
   938          ******************       warning: comloadersize=1376 [-w+user]
