1 2 %if 0 3 4 lDOS iniload packed payload 5 by E. C. Masloch, 2018-2020 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 14 Includes one of several depackers, some of which are under 15 separate usage conditions. Refer to the individual depacker 16 source files for the applicable usage conditions. 17 18 %endif 19 20 %include "lmacros3.mac" 1 <1> [list -] 14 <2> [list -] 14 <1> [list -] 21 22 struc LOADSTACKVARS, -10h 23 FFFFFFF0 ???????? lsvFirstCluster: resd 1 24 FFFFFFF4 ???????? lsvFATSector: resd 1 25 FFFFFFF8 ???? lsvFATSeg: resw 1 26 FFFFFFFA ???? lsvLoadSeg: resw 1 27 FFFFFFFC ???????? lsvDataStart: resd 1 28 endstruc 29 30 struc LOADDATA, LOADSTACKVARS - 10h 31 FFFFFFE0 ???? ldMemoryTop: resw 1 32 FFFFFFE2 ???? ldLoadTop: resw 1 33 FFFFFFE4 ???? ldSectorSeg: resw 1 34 FFFFFFE6 ?? ldFATType: resb 1 35 FFFFFFE7 ?? ldHasLBA: resb 1 36 FFFFFFE8 ???? ldClusterSize: resw 1 37 FFFFFFEA ???? ldParaPerSector:resw 1 38 FFFFFFEC ???? ldLoadingSeg: resw 1 39 FFFFFFEE ???? ldLoadUntilSeg: resw 1 40 endstruc 41 42 43 %ifndef _MAP 44 %elifempty _MAP 45 %else ; defined non-empty, str or non-str 46 [map all _MAP] 47 %endif 48 49 defaulting 50 51 numdef DEBUG0 ; use errordata to generate an error code 52 numdef DEBUG1 ; dump_stack_frame after an error occurred 53 numdef DEBUG2 ; dump_stack_frame before blz_depack_safe call 54 numdef DEBUG3 ; dump_stack_frame at start of blz_depack_safe 55 56 numdef OPTIMISE_INPUT_SMALL, 0 57 numdef OPTIMISE_OUYPUT_SMALL, 0 58 numdef ALLOW_OVERLAPPING, 1 ; allow overlapping src and dst 59 numdef TEST_PROGRAM, 0 60 numdef TEST_PROGRAM_DECOMPRESSED_SIZE, 0,0 61 %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE 62 %error Test program has to learn of decompressed size. 63 %endif 64 numdef TEST_PROGRESS, 0 65 66 numdef INCLUDE_UNCOMPRESSED 67 numdef INCLUDE_UNCOMPRESSED_IN_IMAGE, 1 68 numdef WRITE_WRONG_FILE 69 numdef RELOAD_XMS, 0 70 numdef RELOAD_FILE, 0 71 72 numdef EXEC_OFFSET, 0 73 numdef EXEC_SEGMENT, 0 74 numdef IMAGE_EXE, 0 75 %if ! _IMAGE_EXE && _TEST_PROGRAM 76 %error Test program can only be used as EXE. 77 %endif 78 numdef IMAGE_EXE_CS, -16 ; relative-segment for CS 79 numdef IMAGE_EXE_IP, 256 +64 ; value for IP 80 ; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0. 81 numdef IMAGE_EXE_SS, -16 ; relative-segment for SS 82 numdef IMAGE_EXE_SP, 0FFFEh ; value for SP (0 underflows) 83 numdef IMAGE_EXE_AUTO_STACK, 0, 2048 ; use stack behind image 84 ; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of 85 ; the same name. This one is only used as a flag; if non-zero, 86 ; keep the stack given to us by iniload; if zero, set up the 87 ; stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP. 88 numdef IMAGE_EXE_GET_COM_STACK, 0 89 ; set up stack for flat .COM style entry 90 numdef DEVICE, 0 91 gendef DEVICE_NAME, "" 92 numdef DEVICE_ATTRIBUTE, 8000h 93 numdef DEVICE_ZERO_ENTRYPOINT, 0 94 numdef BOOTLDR, 1 ; support boot loaded entrypoint 95 96 numdef BRIEFLZ, 0 97 numdef LZ4, 0 98 numdef SNAPPY, 0 99 numdef EXODECR, 0 100 numdef X, 0 101 numdef HEATSHRINK, 0 102 numdef LZD, 0 103 numdef LZO, 0 104 numdef LZSA2, 0 105 numdef APL, 0 106 numdef BZP, 0 107 numdef ZEROCOMP, 0 108 numdef MVCOMP, 0 109 numdef LZEXEDAT, 0 110 %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK + !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP + !!_ZEROCOMP + !!_MVCOMP + !!_LZEXEDAT) != 1 113 %fatal Exactly one compression method must be selected. 114 %endif 115 %assign ADDITIONAL_MEMORY 0 116 %if _BRIEFLZ 117 strdef PAYLOAD_FILE, "lDOSLOAD.BLZ" 118 %elif _LZ4 119 strdef PAYLOAD_FILE, "lDOSLOAD.LZ4" 120 %elif _SNAPPY 121 strdef PAYLOAD_FILE, "lDOSLOAD.SZ" 122 %elif _EXODECR 123 strdef PAYLOAD_FILE, "lDOSLOAD.EXO" 124 %elif _X 125 strdef PAYLOAD_FILE, "lDOSLOAD.X" 126 %elif _HEATSHRINK 127 strdef PAYLOAD_FILE, "lDOSLOAD.HS" 128 %elif _LZD 129 strdef PAYLOAD_FILE, "lDOSLOAD.LZ" 130 %elif _LZO 131 strdef PAYLOAD_FILE, "lDOSLOAD.LZO" 132 %elif _LZSA2 133 strdef PAYLOAD_FILE, "lDOSLOAD.SA2" 134 %elif _APL 135 strdef PAYLOAD_FILE, "lDOSLOAD.APL" 136 %elif _BZP 137 strdef PAYLOAD_FILE, "lDOSLOAD.BZP" 138 %elif _ZEROCOMP 139 strdef PAYLOAD_FILE, "lDOSLOAD.ZER" 140 %elif _MVCOMP 141 strdef PAYLOAD_FILE, "lDOSLOAD.MV" 142 %elif _LZEXEDAT 143 strdef PAYLOAD_FILE, "lDOSLOAD.LZE" 144 %endif 145 numdef PAYLOAD_KERNEL_MAX_PARAS, 0, 0 146 %if _PAYLOAD_KERNEL_MAX_PARAS && ! (_IMAGE_EXE || _DEVICE) 147 %error Kernel mode max paras requires building dual-mode or triple-mode executable 148 %endif 149 numdef COUNTER, 0, 32 150 %if (_COUNTER - 1) & _COUNTER 151 %error COUNTER must be a power of two 152 %endif 153 numdef PROGRESS, 0, 1 154 numdef PROGRESSAMOUNT, 0, 0 155 numdef PROGRESSMULTI, 1 156 numdef PROGRESSVAR, 1 157 numdef PROGRESSVARNAME, "" 158 numdef PROGRESSDEFAULT, 0 159 numdef PROGRESSDEFAULTAPP, _PROGRESSDEFAULT 160 numdef PROGRESSDEFAULTDEVICE, _PROGRESSDEFAULT 161 numdef PROGRESSDEFAULTBOOT,1 162 numdef PASSLCFG, 0 163 numdef LCFG, (_PROGRESS && _PROGRESSMULTI) || _PASSLCFG 164 165 166 %define MODULE inicomp 167 strdef INILOAD_CFG, "" 168 %ifnidn _INILOAD_CFG, "" 169 %include _INILOAD_CFG 1 <1> ; File auto-generated, do not edit. 2 <1> strdef INILOAD_SIGNATURE, "FD" 3 <1> %assign _DEVICE 0 4 <1> %ifidni MODULE, fdkernpl 5 <1> %define _PAYLOAD_FILE "kernel.sys" 6 <1> %endif 7 <1> %ifn _TEST_PROGRAM 8 <1> numdef IMAGE_EXE, 0 9 <1> numdef SECOND_PAYLOAD_EXE, 0 10 <1> %endif 170 %endif 171 strdef LCFG_CFG, "" 172 173 %if _DEVICE 174 %ifidn _DEVICE_NAME, "" 175 %error Device name must be set 176 %endif 177 %endif 178 179 struc XMSM 180 00000000 ???????? .size_: resd 1 181 00000004 ???? .srchdl: resw 1 182 00000006 ???????? .srcadr: resd 1 183 0000000A ???? .dsthdl: resw 1 184 0000000C ???????? .dstadr: resd 1 185 endstruc 186 187 188 cpu 8086 189 addsection INIT0, start=0 vstart=0 190 init0_start: 191 %if _DEVICE 192 ; The device header is of a fixed format. 193 ; For our purposes, the 4-byte code for 194 ; each the strategy entry and the 195 ; interrupt entry is part of this format. 196 ; (DOS may read the attributes or entrypoint 197 ; offsets before calling either, so in the inicomp 198 ; stage we need to recreate in the entrypoints part 199 ; exactly what the application has here.) 200 ; _PASSLCFG: The lCFG block is passed in the dword 201 ; behind the interrupt entry. 202 device_header: 203 .next: 204 %if _DEVICE_ZERO_ENTRYPOINT 205 fill 2, -1, jmp strict short j_zero_entrypoint 206 dw -1 207 %else 208 dd -1 ; link to next device 209 %endif 210 .attributes: 211 dw _DEVICE_ATTRIBUTE ; attributes 212 .strategy: 213 dw .strategy_entry ; -> strategy entry 214 .interrupt: 215 dw .interrupt_entry ; -> interrupt entry 216 .name: 217 fill 8, 32, db _DEVICE_NAME ; character device name, 218 ; or block device number of units 219 ; + optional name 220 .strategy_entry: 221 fill 4, 90h, jmp device_entrypoint 222 .interrupt_entry: 223 fill 4, 90h, retf 224 .pass_lcfg: 225 %endif 226 227 228 %if _IMAGE_EXE || _DEVICE 229 00000000 90 nop 230 00000001 90 align 32, nop 231 init0_kernel_entry: 232 ; cs:ip = load seg : 32 here 233 %if ($ - $$) != 32 234 %error Wrong kernel mode entrypoint 235 %endif 236 %if _TEST_PROGRAM 237 @@: 238 00000020 CC int3 239 00000021 FB sti 240 00000022 F4 hlt 241 00000023 EBFB jmp @B 242 %endif 243 %if _BOOTLDR 244 %if ! _IMAGE_EXE 245 j_zero_entrypoint: 246 %endif 247 00000025 31DB xor bx, bx ; 0 = kernel mode 248 00000027 50 push ax 249 00000028 8CC8 mov ax, cs 250 0000002A 83C040 add ax, (init0_end - init0_start) >> 4 251 0000002D 8B56E2 mov dx, word [ bp + ldLoadTop ] ; => after end of available space 252 00000030 BE6000 mov si, 60h ; => destination 253 00000033 EB7E jmp init0_common 254 %endif 255 256 %if _IMAGE_EXE 257 00000035 90 align 64, nop 258 j_zero_entrypoint: 259 init0_exe_entry: 260 ; NOTE: This part is called with ip = 256 + 64, cs = PSP. 261 %if ($ - $$) != 64 262 %error Wrong EXE mode entrypoint 263 %endif 264 %if _IMAGE_EXE_GET_COM_STACK 265 mov bx, ds ; => PSP 266 dec bx ; => MCB 267 mov ds, bx 268 add bx, word [3] ; add size of memory block 269 sub bx, -1 + paras(512) ; add one, then subtract enough paragraphs 270 cli 271 mov ss, bx 272 mov sp, 512 ; -> new stack 273 sti 274 %endif 275 00000040 BB0100 mov bx, 1 ; EXE mode 276 00000043 50 push ax 277 %if _TEST_PROGRAM 278 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 279 push ds 280 mov ax, word [2Ch] ; => environment 281 test ax, ax 282 jnz @F 283 .errorfile: 284 jmp init0_error_file 285 @@: 286 mov ds, ax 287 mov cx, 8000h 288 xor si, si ; -> environment 289 @@: 290 lodsb 291 test al, al 292 loopnz @B ; si -> past one NUL 293 jcxz .errorfile 294 cmp byte [si], 0 ; -> another NUL ? 295 loopne @B ; no, skip next variable --> 296 jcxz .errorfile 297 inc si ; skip double NUL 298 lodsw ; load amount strings after environment 299 cmp ax, 1 ; 1 ? 300 jne .errorfile ; no --> 301 mov dx, si ; ds:dx -> executable pathname 302 mov ax, 3D00h + 0_010_0_000b ; deny write, read only 303 int 21h ; open 304 jc .errorfile 305 pop ds ; restore => PSP 306 push ax ; push into ?handle 307 %endif 308 309 00000044 BE8100 mov si, 81h 310 00000047 31D2 xor dx, dx 311 00000049 31C0 xor ax, ax 312 cmdline: 313 .: 314 0000004B AC lodsb 315 0000004C 3C09 cmp al, 9 316 0000004E 74FB je . 317 00000050 3C20 cmp al, 32 318 00000052 74F7 je . 319 00000054 3C0D cmp al, 13 320 00000056 744E je .end 321 00000058 3C30 cmp al, '0' 322 0000005A 721E jb .notdigit 323 0000005C 3C39 cmp al, '9' 324 0000005E 771A ja .notdigit 325 .digit: 326 00000060 2C30 sub al, '0' 327 00000062 89D1 mov cx, dx ; times 1 328 00000064 01D2 add dx, dx 329 00000066 722A jc .invalid 330 00000068 01D2 add dx, dx ; times 4 331 0000006A 7226 jc .invalid 332 0000006C 01CA add dx, cx ; times 5 333 0000006E 7222 jc .invalid 334 00000070 01D2 add dx, dx ; times 10 335 00000072 721E jc .invalid 336 00000074 01C2 add dx, ax ; add in low digit 337 00000076 721A jc .invalid 338 00000078 EBD1 jmp . 339 340 .notdigit: 341 0000007A 3C41 cmp al, 'A' 342 0000007C 7419 je .a 343 0000007E 3C61 cmp al, 'a' 344 00000080 7415 je .a 345 00000082 3C42 cmp al, 'B' 346 00000084 7416 je .b 347 00000086 3C62 cmp al, 'b' 348 00000088 7412 je .b 349 0000008A 3C43 cmp al, 'C' 350 0000008C 7413 je .c 351 0000008E 3C63 cmp al, 'c' 352 00000090 740F je .c 353 .invalid: 354 00000092 BAFFFF mov dx, -1 ; invalid 355 00000095 EB0F jmp .end 356 357 .a: 358 00000097 80E77F and bh, ~ 80h ; A mode. determine min alloc size 359 0000009A EBAF jmp . 360 361 .b: 362 0000009C 80CF80 or bh, 80h ; B mode. repeat depack, counter in command line 363 0000009F EBAA jmp . 364 365 .c: 366 000000A1 80CF40 or bh, 40h ; C mode. how often would the counter be called 367 000000A4 EBA5 jmp . 368 369 .end: 370 ; bx for ?whichtest 371 000000A6 52 push dx ; for ?repetitions 372 %endif 373 000000A7 8CD2 mov dx, ss ; => after end of available space 374 000000A9 8CC8 mov ax, cs 375 000000AB 83C050 add ax, (256 + (init0_end - init0_start)) >> 4 ; => source 376 000000AE 8CCE mov si, cs 377 000000B0 83C610 add si, 256 >> 4 ; => destination 378 %endif 379 380 init0_common: 381 ; REM: This part must be position-independent, as it is 382 ; called either with ip = init0_common (kernel mode 383 ; or device mode) 384 ; or ip = init0_common + 256 (application mode). 385 ; INP: si => depack destination 386 ; ax => source of payload + INIT1 387 ; dx => behind available memory 388 ; OUT: cs:ip -> init1_start: 389 ; ax => INIT1 390 ; dx => payload source 391 ; si => depack destination 392 ; bx = mode 393 000000B3 FC cld 394 %if _TEST_PROGRAM 395 %ifn _RELOAD_XMS || _RELOAD_FILE 396 000000B4 81EA110F sub dx, ( (payload_end - payload) ) >> 4 397 000000B8 721A jc .error 398 %endif 399 000000BA B9AD23 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) + (init2_end - init2_start) ) >> 4 405 000000BD 29CA sub dx, cx 406 000000BF 7213 jc .error 407 000000C1 39C2 cmp dx, ax 408 000000C3 720F jb .error 409 %else 410 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 415 ; cx = amount paragraphs in INIT0B + payload + INIT1 416 sub dx, cx ; => destination for INIT0B + payload + INIT1 417 ; (highest possible spot in available memory) 418 %endif 419 000000C5 56 push si ; preserve destination 420 000000C6 E86700 call init0_movp ; move up payload + INIT1 421 000000C9 5E pop si 422 %else 423 cld 424 mov ax, cs 425 add ax, (init0_end - init0_start) >> 4 426 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 431 mov dx, word [ bp + ldLoadTop ] 432 sub dx, cx 433 call init0_movp 434 %endif 435 436 %if _LCFG && ! _TEST_PROGRAM 437 push cs 438 call @F ; position-independent far pointer 439 @@: 440 pop ax 441 add ax, lcfg - @B ; -> lCFG block 442 push ax 443 %endif 444 445 000000CA 89D0 mov ax, dx ; => INIT0B 446 ; (same as => payload if INIT0B is empty) 447 %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM 448 add dx, ( + (init0b_end - init0b_start) ) >> 4 ; => payload 451 %else 452 %if _TEST_PROGRAM 453 000000CC 05740F add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 ; => INIT2 458 %else 459 add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) ) >> 4 ; => INIT1 463 %endif 464 %endif 465 000000CF 31C9 xor cx, cx 466 000000D1 50 push ax 467 000000D2 51 push cx 468 000000D3 CB retf ; jump to relocated 469 ; INIT0B:init0b_start 470 ; or INIT1:init1_start 471 ; or INIT2:init2_start 472 473 474 %if _TEST_PROGRAM 475 .error: 476 000000D4 89DF mov di, bx ; whichtest 477 478 000000D6 0E push cs 479 000000D7 1F pop ds 480 000000D8 BA[B202] mov dx, init0_msg.error_stderr + 256 481 000000DB B92500 mov cx, init0_msg.error_stderr.length 482 000000DE BB0200 mov bx, 2 483 000000E1 B440 mov ah, 40h 484 000000E3 CD21 int 21h 485 486 000000E5 F7C70040 test di, 4000h ; whichtest 487 000000E9 7408 jz @F 488 000000EB BA[D702] mov dx, init0_msg.error_c_stdout + 256 489 000000EE B90300 mov cx, init0_msg.error_c_stdout.length 490 000000F1 EB0A jmp @FF 491 @@: 492 000000F3 85FF test di, di ; whichtest 493 000000F5 780D js @FF 494 000000F7 BA[D702] mov dx, init0_msg.error_stdout + 256 495 000000FA B90300 mov cx, init0_msg.error_stdout.length 496 @@: 497 000000FD BB0100 mov bx, 1 498 00000100 B440 mov ah, 40h 499 00000102 CD21 int 21h 500 @@: 501 00000104 B8FF4C mov ax, 4CFFh 502 00000107 CD21 int 21h 503 504 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 505 init0_error_file: 506 mov dx, init0_msg.error_stderr_file + 256 507 mov cx, init0_msg.error_stderr_file.length 508 push cs 509 pop ds 510 mov bx, 2 511 mov ah, 40h 512 int 21h 513 514 mov dx, init0_msg.error_stdout + 256 515 mov cx, init0_msg.error_stdout.length 516 mov bx, 1 517 mov ah, 40h 518 int 21h 519 mov ax, 4CFFh 520 int 21h 521 %endif 522 523 %endif 524 525 526 %if _LCFG 527 %imacro lcfgoption 3+.nolist 528 _fill %1, 0, lcfg 529 %%start: 530 %2 531 %3 532 %%end: 533 %assign %%index %%start - lcfg 534 %rep %%end - %%start 535 %assign LCFGINUSE LCFGINUSE | (1 << %%index) 536 %assign %%index %%index + 1 537 %endrep 538 %endmacro 539 %assign LCFGINUSE 0 540 541 00000109 90 align 16 542 lcfg: 543 00000110 EB1E .: jmp strict short .end 544 00000112 6C434647 lcfgoption 2,, db "lCFG" 545 00000116 3030 lcfgoption 6,, db "00" 546 00000118 FCFF050000000000 lcfgoption 8,, dq .inuse 547 %if _PROGRESS && _PROGRESSMULTI 548 %if _IMAGE_EXE 549 00000120 00 lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP 550 %endif 551 %if _DEVICE 552 lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE 553 %endif 554 %if _BOOTLDR 555 00000121 0001 lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT 556 %endif 557 %endif 558 559 %ifnidn _LCFG_CFG, "" 560 %include _LCFG_CFG 1 <1> ; File auto-generated, do not edit. 561 %endif 562 563 00000123 00 lcfgoption 32,, 564 .end: 565 .size: equ .end - . 566 .inuse equ LCFGINUSE 567 %endif 568 569 570 %if _DEVICE 571 device_entrypoint: 572 %if _TEST_PROGRAM 573 @@: 574 int3 575 sti 576 hlt 577 jmp @B 578 %endif 579 cmp byte [es:bx + 2], 0 ; command code 0 (init) ? 580 je @F 581 582 mov word [es:bx + 3], 8103h ; error, done, code: unknown command 583 retf 584 585 @@: 586 or word [cs:device_header.next], -1 587 push cs 588 push word [cs:device_header.strategy] 589 ; -> far return to payload's strategy 590 push bp 591 push ds 592 push si 593 push di 594 push dx 595 push cx 596 push ax 597 push bx 598 push es 599 600 mov dx, word [es:bx + 14] 601 mov cl, 4 602 shr dx, cl ; = how many full paragraphs (rounded down) 603 add dx, word [es:bx + 14 + 2] 604 ; ax => behind end 605 606 mov di, cs 607 image_size: equ ( + (init0_end - init0_start) + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) 613 add di, image_size >> 4 ; di => end of image 614 615 cmp dx, di ; enough memory to hold all of us ? 616 jb @F ; no --> 617 ; yes 618 .have_some_memory: 619 ; dx => after end of memory 620 mov bx, 2 ; device mode 621 push ax 622 mov ax, cs 623 add ax, (init0_end - init0_start) >> 4 624 mov si, cs ; => destination 625 jmp init0_common 626 627 628 @@: 629 push cs 630 pop ds 631 mov dx, .msg_no_memory 632 mov ah, 09h 633 int 21h 634 635 mov ax, 3000h 636 int 21h 637 cmp al, 5 638 jae @F 639 mov dx, .msg_dos_below_5 640 mov ah, 09h 641 int 21h 642 @@: 643 644 mov dx, .msg_linebreak 645 mov ah, 09h 646 int 21h 647 648 ; tear down the stack frame and modify the request header 649 pop es 650 pop bx 651 mov word [es:bx + 3], 8103h ; set error, done, invalid command 652 mov byte [es:bx + 13], 0 ; set number of units = 0 653 mov word [es:bx + 14 + 2], cs 654 and word [es:bx + 14], 0 ; -> after end of memory to allocate 655 pop ax 656 pop cx 657 pop dx 658 pop di 659 pop si 660 pop ds 661 pop bp 662 add sp, 4 ; discard far return to payload's strategy 663 retf ; return to DOS 664 665 666 .msg_no_memory: ascic "Load error: Not enough memory." 667 .msg_dos_below_5: ascic " Note: DOS must be at least version 5." 668 .msg_linebreak: ascic 13,10 669 %endif 670 671 672 ; Move paragraphs 673 ; 674 ; INP: ax => source 675 ; dx => destination 676 ; cx = number of paragraphs 677 ; CHG: cx, ds, si, es, di 678 ; OUT: ax and dx unchanged 679 ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 680 ; Do not provide a wrapped/HMA source or destination! 681 init0_movp: 682 00000130 39D0 cmp ax, dx ; source above destination ? 683 00000132 770A ja .up ; yes, move up (forwards) --> 684 00000134 747B je .return ; same, no need to move --> 685 00000136 50 push ax 686 00000137 01C8 add ax, cx ; (expected not to carry) 687 00000139 39D0 cmp ax, dx ; end of source is above destination ? 688 0000013B 58 pop ax 689 0000013C 7730 ja .down ; yes, move from top down --> 690 ; Here, the end of source is below-or-equal the destination, 691 ; so they do not overlap. In this case we prefer moving up. 692 693 .up: 694 0000013E 50 push ax 695 0000013F 52 push dx 696 .uploop: 697 00000140 8ED8 mov ds, ax 698 00000142 8EC2 mov es, dx 699 00000144 31FF xor di, di 700 00000146 31F6 xor si, si ; -> start of segment 701 00000148 81E90010 sub cx, 1000h ; 64 KiB left ? 702 0000014C 7610 jbe .uplast ; no --> 703 0000014E 51 push cx 704 0000014F B90080 mov cx, 10000h /2 705 00000152 F3A5 rep movsw ; move 64 KiB 706 00000154 59 pop cx 707 00000155 050010 add ax, 1000h 708 00000158 81C20010 add dx, 1000h ; -> next segment 709 0000015C EBE2 jmp short .uploop ; proceed for more --> 710 .uplast: 711 0000015E 81C10010 add cx, 1000h ; restore counter 712 00000162 D1E1 shl cx, 1 713 00000164 D1E1 shl cx, 1 714 00000166 D1E1 shl cx, 1 ; *8, paragraphs to words 715 00000168 F3A5 rep movsw ; move last part 716 0000016A 5A pop dx 717 0000016B 58 pop ax 718 0000016C EB43 jmp short .return 719 720 .down: 721 0000016E FD std ; _AMD_ERRATUM_109_WORKAROUND as below 722 .dnloop: 723 0000016F 81E90010 sub cx, 1000h ; 64 KiB left ? 724 00000173 761A jbe .dnlast ; no --> 725 00000175 50 push ax 726 00000176 52 push dx 727 00000177 01C8 add ax, cx 728 00000179 01CA add dx, cx 729 0000017B 8ED8 mov ds, ax ; -> 64 KiB not yet moved 730 0000017D 8EC2 mov es, dx 731 0000017F 5A pop dx 732 00000180 58 pop ax 733 00000181 BFFEFF mov di, -2 734 00000184 89FE mov si, di ; moved from last word down 735 00000186 51 push cx 736 00000187 B90080 mov cx, 10000h /2 737 0000018A F3A5 rep movsw ; move 64 KiB 738 0000018C 59 pop cx 739 0000018D EBE0 jmp short .dnloop ; proceed for more --> 740 .dnlast: 741 0000018F 81C10010 add cx, 1000h ; restore counter 742 00000193 D1E1 shl cx, 1 743 00000195 D1E1 shl cx, 1 744 00000197 D1E1 shl cx, 1 ; *8, paragraphs to words 745 00000199 89CF mov di, cx 746 0000019B 4F dec di 747 0000019C D1E7 shl di, 1 ; words to offset, -> last word 748 0000019E 89FE mov si, di 749 000001A0 8ED8 mov ds, ax 750 000001A2 8EC2 mov es, dx ; first segment correct 751 752 753 numdef AMD_ERRATUM_109_WORKAROUND, 1 754 %if 0 755 756 Jack R. Ellis pointed out this erratum: 757 758 Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69: 759 760 109 Certain Reverse REP MOVS May Produce Unpredictable Behavior 761 762 Description 763 764 In certain situations a REP MOVS instruction may lead to 765 incorrect results. An incorrect address size, data size 766 or source operand segment may be used or a succeeding 767 instruction may be skipped. This may occur under the 768 following conditions: 769 770 * EFLAGS.DF=1 (the string is being moved in the reverse direction). 771 772 * The number of items being moved (RCX) is between 1 and 20. 773 774 * The REP MOVS instruction is preceded by some microcoded instruction 775 that has not completely retired by the time the REP MOVS begins 776 execution. The set of such instructions includes BOUND, CLI, LDS, 777 LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions. 778 779 Potential Effect on System 780 781 Incorrect results may be produced or the system may hang. 782 783 Suggested Workaround 784 785 Contact your AMD representative for information on a BIOS update. 786 787 %endif 788 789 %if _AMD_ERRATUM_109_WORKAROUND 790 000001A4 E308 jcxz @FF 791 000001A6 83F914 cmp cx, 20 792 000001A9 7703 ja @FF 793 @@: 794 000001AB A5 movsw 795 000001AC E2FD loop @B 796 @@: 797 %endif 798 000001AE F3A5 rep movsw ; move first part 799 000001B0 FC cld 800 .return: 801 000001B1 C3 retn 802 803 804 addsection INIT0B, align=16 vstart=0 follows=INIT0 805 ; INP: ax:cx = cs:ip = cs:0 806 ; ax => INIT0B 807 ; dx => payload source 808 ; ss:sp -> (dword pointer to lCFG block) 809 ; if app/device mode supported: 810 ; si => depack destination 811 ; bx = mode 812 init0b_start: 813 %if _LCFG || _PROGRESS 814 815 00000000 05210F add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) ) >> 4 ; => INIT1 819 820 %if _LCFG && _PASSLCFG 821 %if (_IMAGE_EXE || _DEVICE) 822 mov cx, si ; preserve si 823 %endif 824 pop si 825 pop ds ; -> lCFG block 826 mov es, ax 827 mov di, transfer_lcfg_block 828 ; -> destination 829 %if (_IMAGE_EXE || _DEVICE) 830 push cx 831 %endif 832 push di 833 mov cx, words(lcfg.size) 834 rep movsw ; cx = 0 835 pop di ; es:di -> relocated lCFG block, same difference 836 %if (_IMAGE_EXE || _DEVICE) 837 pop si ; preserve si 838 %endif 839 %elif _LCFG 840 00000003 5F pop di 841 00000004 07 pop es ; es:di -> (original) lCFG block 842 %endif 843 844 00000005 50 push ax 845 00000006 51 push cx ; -> far return address to init1_start 846 847 %if _PROGRESS && _PROGRESSMULTI 848 %if (_IMAGE_EXE || _DEVICE) 849 00000007 56 push si 850 00000008 53 push bx 851 %endif 852 %if _BOOTLDR 853 %if _LCFG 854 00000009 31C0 xor ax, ax 855 0000000B 268A4512 mov al, byte [es:di + lcfg.progress_boot - lcfg] 856 0000000F 97 xchg di, ax ; di = boot default progress 857 ; es:ax -> lCFG block 858 %else ; _LCFG 859 mov di, _PROGRESSDEFAULTBOOT 860 %endif ; _LCFG 861 %endif ; _BOOTLDR 862 %if (_IMAGE_EXE || _DEVICE) 863 %if _BOOTLDR 864 00000010 85DB test bx, bx 865 00000012 7503E9A700 jz .default 866 %endif ; _BOOTLDR 867 %if _LCFG 868 00000017 06 push es 869 %if _BOOTLDR 870 00000018 50 push ax ; -> lCFG block 871 %else ; _BOOTLDR 872 push di 873 %endif ; _BOOTLDR 874 %endif ; _LCFG 875 %if _PROGRESSVAR 876 00000019 B451 mov ah, 51h 877 0000001B CD21 int 21h 878 @@: 879 0000001D 8EDB mov ds, bx 880 0000001F A12C00 mov ax, word [2Ch] 881 00000022 85C0 test ax, ax 882 00000024 7510 jnz .gotenv 883 00000026 A11600 mov ax, word [16h] 884 00000029 40 inc ax 885 0000002A 7469 jz .default_nonboot 886 0000002C 48 dec ax 887 0000002D 7466 jz .default_nonboot 888 0000002F 39C3 cmp bx, ax 889 00000031 7462 je .default_nonboot 890 00000033 93 xchg bx, ax 891 00000034 EBE7 jmp @B 892 893 .gotenv: 894 00000036 0E push cs 895 00000037 1F pop ds ; => cs 896 00000038 8EC0 mov es, ax ; => environment 897 %ifnidni _PROGRESSVARNAME, "" 898 0000003A BB[EA00] mov bx, progressvarname1 899 0000003D E80C00 call .findenv 900 00000040 732E jnc .foundenv ; match --> 901 00000042 BB[ED00] mov bx, progressvarname2 902 %endif 903 00000045 E80400 call .findenv 904 00000048 7326 jnc .foundenv ; match --> 905 0000004A EB49 jmp .default_nonboot 906 907 .findenv: 908 0000004C 31FF xor di, di 909 @@: 910 %ifnidni _PROGRESSVARNAME, "" 911 0000004E 89DE mov si, bx ; -> variable name 912 %else 913 mov si, progressvarname2 ; -> variable name 914 %endif 915 00000050 31C0 xor ax, ax 916 00000052 AC lodsb ; get length 917 00000053 91 xchg cx, ax ; cx = length 918 00000054 57 push di 919 00000055 F3A6 repe cmpsb ; match ? 920 00000057 7415 je .findret_pop ; (NC) yes --> 921 00000059 5F pop di 922 0000005A B90080 mov cx, 8000h ; maximum env size 923 0000005D 29F9 sub cx, di ; any left ? 924 0000005F 760B jbe .findret_CY ; no --> 925 00000061 B000 mov al, 0 926 00000063 F2AE repne scasb ; find next NUL 927 00000065 7505 jne .findret_CY 928 00000067 263805 cmp byte [es:di], al ; double NUL ? 929 0000006A 75E2 jne @B ; no, loop --> 930 .findret_CY: 931 0000006C F9 stc ; not found 932 0000006D C3 retn 933 934 .findret_pop: 935 0000006E 59 pop cx 936 0000006F C3 retn 937 938 .foundenv: 939 %if _LCFG 940 00000070 5E pop si 941 00000071 5E pop si ; discard far pointer to lCFG 942 %endif 943 00000072 89FE mov si, di ; es:si -> var content 944 00000074 31FF xor di, di ; = 0 945 00000076 31C0 xor ax, ax ; ah = 0 946 @@: 947 00000078 26AC es lodsb ; next candidate digit 948 0000007A 2C30 sub al, '0' ; digit ? 949 0000007C 7212 jb @F ; no --> 950 0000007E 3C09 cmp al, 9 951 00000080 770E ja @F ; no --> 952 00000082 01FF add di, di ; times 2 953 00000084 89FB mov bx, di 954 00000086 01FF add di, di ; times 4 955 00000088 01FF add di, di ; times 8 956 0000008A 01DF add di, bx ; times 8 + times 2 = times 10 957 0000008C 01C7 add di, ax ; add in next digit 958 0000008E EBE8 jmp @B ; and loop 959 960 @@: 961 00000090 83E71F and di, 31 ; mask to low 5 bits 962 00000093 EB0B jmp @F 963 %endif ; _PROGRESSVAR 964 965 .default_nonboot: 966 %if _LCFG 967 00000095 5F pop di 968 00000096 07 pop es ; -> lCFG block 969 00000097 5B pop bx ; = 1 if app, = 2 if device 970 00000098 53 push bx 971 00000099 268B4510 mov ax, word [es:di + lcfg.progress_app - lcfg] 972 %if _DEVICE 973 %if lcfg.progress_app + 1 != lcfg.progress_dev 974 %error Unexpected layout 975 %endif 976 ; al = app, ah = device 977 dec bx 978 jz .default_app 979 xchg al, ah ; al = device 980 .default_app: 981 %endif ; _DEVICE 982 0000009D B400 mov ah, 0 ; ax = default 983 0000009F 97 xchg di, ax ; di = default 984 %else ; _LCFG 985 mov di, _PROGRESSDEFAULT 986 %endif ; _LCFG 987 @@: 988 000000A0 F7C71000 test di, 16 989 000000A4 7405 jz @F 990 000000A6 83E7EF and di, ~16 991 000000A9 EB13 jmp .outputdevice ; if 16 set skip device check 992 @@: 993 000000AB 52 push dx 994 000000AC B80044 mov ax, 4400h ; IOCTL get device information 995 000000AF BB0100 mov bx, 1 ; StdOut 996 000000B2 B283 mov dl, 83h ; default if 21.4400 fails 997 000000B4 CD21 int 21h 998 000000B6 F6C280 test dl, 80h 999 000000B9 5A pop dx 1000 000000BA 7502 jnz .outputdevice 1001 000000BC 31FF xor di, di ; stdout is a file: force no progress marker 1002 .outputdevice: 1003 %endif ; (_IMAGE_EXE || _DEVICE) 1004 1005 .default: 1006 %if (_IMAGE_EXE || _DEVICE) 1007 000000BE 5B pop bx 1008 000000BF 5E pop si 1009 %endif 1010 000000C0 83FF05 cmp di, step_progress_table.amount 1011 ; valid ? 1012 000000C3 7202 jb @F ; yes --> 1013 000000C5 31FF xor di, di ; disable 1014 @@: 1015 000000C7 D1E7 shl di, 1 ; = word index 1016 000000C9 59 pop cx ; = 0 1017 000000CA 1F pop ds ; ds => INIT1 1018 1019 000000CB 2E8B85[E000] mov ax, word [cs:step_progress_table + di] 1020 ; ax = rel16 for step progress handler 1021 000000D0 1E push ds 1022 000000D1 51 push cx ; -> init1_start 1023 000000D2 A3[6800] mov word [step_progress.handler], ax 1024 ; patch it 1025 1026 000000D5 83FF04 cmp di, 2 * 2 ; none or dots ? 1027 000000D8 7305 jae @F ; no, skip --> 1028 000000DA C606[0600]A9 mov byte [..@empty_step_progress], __TEST_IMM16 1029 ; for none and dots do not call here 1030 @@: 1031 %endif ; _PROGRESS && _PROGRESSMULTI 1032 000000DF CB retf 1033 %endif 1034 1035 %if _PROGRESS && _PROGRESSMULTI 1036 align 2, db 0 1037 step_progress_table: 1038 .: 1039 000000E0 1600 dw step_progress.0_step - step_progress.base 1040 000000E2 3B00 dw step_progress.1_step - step_progress.base 1041 000000E4 0000 dw step_progress.2_step - step_progress.base 1042 000000E6 4100 dw step_progress.3_step - step_progress.base 1043 000000E8 8600 dw step_progress.4_step - step_progress.base 1044 .amount equ ($ - .) / 2 1045 1046 %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE) 1047 %ifnidni _PROGRESSVARNAME, "" 1048 000000EA 02003D progressvarname1: counted _PROGRESSVARNAME, '=' 1049 %endif 1050 000000ED 0D4C444F5350524F47- progressvarname2: counted "LDOSPROGRESS=" 1050 000000F6 524553533D 1051 %endif 1052 %endif 1053 1054 000000FB 90 align 16 1055 init0b_end: 1056 1057 1058 addsection PAYLOAD, align=16 follows=INIT0B 1059 payload: 1060 00000000 incbin _PAYLOAD_FILE 1061 .end: 1062 0000F105 26 align 16, db 38 1063 payload_end: 1064 1065 %if _OPTIMISE_INPUT_SMALL 1066 %ifn (payload_end - payload) <= 65_520 1067 %error Input declared small is not small 1068 %endif 1069 %else 1070 %if (payload_end - payload) <= 65_520 1071 %warning Input could be declared small 1071 ****************** warning: Input could be declared small [-w+user] 1072 %endif 1073 %endif 1074 1075 1076 addsection INIT1, align=16 follows=PAYLOAD vstart=0 1077 init1_start: 1078 ; INP: ax = cs = INIT1 1079 ; dx = cs - (payload_end - payload) >> 4 => source data 1080 ; if kernel mode: 1081 ; ss:bp -> LOADDATA and LOADSTACKVARS 1082 ; ss:sp -> valid stack above [bp + ldLoadTop] 1083 ; 60h => destination 1084 ; any mode: 1085 ; ss:sp -> word value for ax 1086 ; bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode 1087 ; si => destination (60h for kernel mode, 1088 ; after PSP for EXE mode, 1089 ; at device header for device mode) 1090 ; (not set if only kernel mode supported) 1091 ; if EXE mode: 1092 ; ss:sp -> valid stack above INIT1 1093 ; bp = unset 1094 ; if device mode: 1095 ; ss:sp -> device entrypoint stack 1096 ; holds: es, bx, ax, cx, dx, di, si, ds, bp, 1097 ; far address of payload strategy entrypoint, 1098 ; far return address to DOS 1099 ; bp = unset 1100 ; STT: UP 1101 ; CHG: ax, bx, cx, dx, es, ds, si, di 1102 %if _IMAGE_EXE || _DEVICE 1103 lframe 1104 00000000 5589E5 lenter 1105 lvar word, exemode ; must be bp - 2! 1106 00000003 53 push bx 1107 %if ?exemode != -2 1108 %error exemode variable must be directly below bp 1109 %endif 1110 00000004 56 push si 1111 %if _PROGRESS 1112 00000005 F8 clc ; NC 1113 %endif 1114 %else 1115 xor bx, bx ; always tell them it is kernel mode (NC) 1116 %endif 1117 1118 %if _PROGRESS 1119 ; clc 1120 ..@empty_step_progress: ; SMC, byte patched to __TEST_IMM16 if none or dots 1121 %if _TEST_PROGRAM 1122 00000006 90 times 3 nop 1123 %else 1124 call step_progress.CF ; display empty / 0.0% 1125 %endif 1126 @@: 1127 %endif 1128 1129 %if _IMAGE_EXE || _DEVICE 1130 00000009 8EC6 mov es, si ; es => destination 1131 %else 1132 mov ax, 60h 1133 mov es, ax ; es => destination 1134 %endif 1135 0000000B 31FF xor di, di ; -> destination 1136 1137 0000000D 8EDA mov ds, dx 1138 0000000F 31F6 xor si, si ; -> source 1139 1140 00000011 B905F1 mov cx, (payload.end - payload) & 0FFFFh 1141 %if (payload.end - payload) >> 16 1142 mov dx, (payload.end - payload) >> 16 ; = length of source 1143 %else 1144 00000014 31D2 xor dx, dx 1145 %endif 1146 %if _PAYLOAD_KERNEL_MAX_PARAS 1147 mov ax, _PAYLOAD_KERNEL_MAX_PARAS 1148 test bx, bx 1149 jz @F 1150 %endif 1151 00000016 B8FFFF mov ax, -1 1152 @@: 1153 1154 ; INP: ds:si -> source 1155 ; dx:cx = length of source 1156 ; es:di -> destination (below source) 1157 ; bx = EXE mode flag 1158 ; (1 if EXE mode, 0 if kernel mode) 1159 ; (always 0 if this is a build without EXE mode) 1160 ; if _PAYLOAD_KERNEL_MAX_PARAS: 1161 ; ax = maximum amount in paragraphs of destination needed 1162 ; (-1 if full source should be decompressed) 1163 ; else: 1164 ; ax = -1 1165 ; Note: The destination reaches up to below the source. 1166 00000019 E8DD01 call depack 1167 %ifn _TEST_PROGRAM 1168 jc strict short error ; -2 (replaced by retf \ nop) 1169 %endif 1170 %if _IMAGE_EXE || _DEVICE 1171 0000001C 5E pop si ; si 1172 %if _TEST_PROGRAM 1173 0000001D 58 pop ax ; (discard ?exemode, leave bx as returned) 1174 %else 1175 pop bx ; ?exemode 1176 %endif 1177 0000001E 5D pop bp ; bp 1178 0000001F 58 pop ax ; ax 1179 lleave ctx 1180 %endif 1181 %if _TEST_PROGRAM 1182 00000020 CB retf ; +1 (replace jc error) 1183 00000021 90 nop ; +1 1184 %endif 1185 1186 %if _DEVICE 1187 test bl, 2 1188 jz .jmp_exe_or_kernel_mode 1189 1190 .jmp_device_mode: 1191 mov ds, si 1192 or word [device_header.next], -1 1193 %if _LCFG && _PASSLCFG 1194 mov word [device_header.pass_lcfg], transfer_lcfg_block 1195 mov word [device_header.pass_lcfg + 2], cs 1196 %endif 1197 pop es 1198 pop bx 1199 pop ax 1200 pop cx 1201 pop dx 1202 pop di 1203 pop si 1204 pop ds 1205 pop bp 1206 retf ; transfer to payload strategy entrypoint 1207 ; still on stack: far return address to DOS 1208 1209 .jmp_exe_or_kernel_mode: 1210 %endif 1211 1212 %if _IMAGE_EXE 1213 00000022 F6C301 test bl, 1 1214 00000025 7410 jz .jmp_kernel_mode 1215 1216 .jmp_exe_mode: 1217 %if ! _IMAGE_EXE_AUTO_STACK 1218 mov cx, cs 1219 lea dx, [si + _IMAGE_EXE_SS] 1220 push dx ; stack = relocated ss value 1221 add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4 1222 cmp cx, dx ; INIT1 code is above intended stack ? 1223 jae @F ; yes --> 1224 1225 lframe 1226 lenter 1227 lvar word, exemode 1228 push bx 1229 %if ?exemode != -2 1230 %error exemode variable must be directly below bp 1231 %endif 1232 mov bx, -1 ; unimplemented, return error 1233 jmp error 1234 lleave ctx 1235 @@: 1236 cli 1237 pop ss ; = relocated ss value 1238 mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh ; change stack 1239 sti 1240 %endif 1241 1242 00000027 31C9 xor cx, cx 1243 00000029 51 push cx ; put zero on top of stack 1244 1245 %if _IMAGE_EXE_IP < 256 1246 mov cl, _IMAGE_EXE_IP 1247 %elif (_IMAGE_EXE_IP & 255) == 0 1248 mov ch, _IMAGE_EXE_IP >> 8 1249 %else 1250 0000002A B94001 mov cx, _IMAGE_EXE_IP 1251 %endif 1252 1253 %if _IMAGE_EXE_CS == -16 1254 0000002D 83C6F0 add si, -16 1255 00000030 8EDE mov ds, si 1256 00000032 8EC6 mov es, si 1257 %else 1258 lea dx, [si - 10h] ; => PSP 1259 mov ds, dx 1260 mov es, dx ; ds = es => PSP 1261 %if _IMAGE_EXE_CS 1262 add si, _IMAGE_EXE_CS ; = relocated cs value 1263 %endif 1264 %endif 1265 00000034 56 push si 1266 00000035 51 push cx 1267 %if _LCFG && _PASSLCFG 1268 mov di, transfer_lcfg_block 1269 mov cx, cs 1270 %endif 1271 00000036 CB retf ; jump to EXE mode of image 1272 1273 %endif 1274 .jmp_kernel_mode: 1275 %if _LCFG && _PASSLCFG 1276 mov di, transfer_lcfg_block 1277 mov cx, cs 1278 %endif 1279 00000037 EA00006000 jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET 1280 1281 1282 %if _TEST_PROGRAM 1283 disp_al_counter: 1284 0000003C 2EFF06[4200] inc word [cs:init1_c_mode_counter] ; 5 bytes 1285 00000041 C3 retn ; 1 byte 1286 1287 00000042 0000 init1_c_mode_counter: dw 0 ; 2 bytes, total 8 1288 %else 1289 %if _PROGRESS 1290 disp_al_counter equ step_progress 1291 %else 1292 disp_al_counter equ disp_al 1293 %endif 1294 %endif 1295 1296 1297 error: 1298 %ifn _TEST_PROGRAM ; 2 bytes 1299 push cs 1300 pop ds 1301 %endif 1302 %if _DEBUG0 1303 mov si, msg.error_begin 1304 call disp_error 1305 xchg ax, bx ; ax = error code 1306 call disp_ax_hex 1307 %ifn _TEST_PROGRAM ; 3 bytes 1308 mov si, msg.error_end 1309 %endif 1310 %else 1311 %ifn _TEST_PROGRAM ; 3 bytes 1312 mov si, msg.error 1313 %endif 1314 %endif 1315 %ifn _TEST_PROGRAM ; 3 bytes, total 2 + 3 + 3 = 8 1316 call disp_error 1317 %endif 1318 %if _DEVICE 1319 test byte [bp - 2], 2 1320 jz .exit_app_or_kernel 1321 1322 pop si ; => device segment 1323 pop bx ; mode word 1324 pop bp 1325 pop ax 1326 mov es, si 1327 xor di, di ; -> device header 1328 push cs 1329 pop ds 1330 mov si, device_header_copy ; -> to reset header 1331 mov cx, words(device_header_copy.length) 1332 rep movsw ; overwrite device header with default 1333 ; (reset to a valid state after unsuccessful 1334 ; decompression, which may have partially 1335 ; written the header already) 1336 push es 1337 pop ds ; -> device segment 1338 pop es 1339 pop bx 1340 mov word [es:bx + 3], 8103h ; set error, done, invalid command 1341 mov byte [es:bx + 13], 0 ; set number of units = 0 1342 mov word [es:bx + 14 + 2], ds 1343 and word [es:bx + 14], 0 ; -> after end of memory to allocate 1344 pop ax 1345 pop cx 1346 pop dx 1347 pop di 1348 pop si 1349 pop ds 1350 pop bp 1351 add sp, 4 ; discard far return to payload's strategy 1352 retf ; return to DOS 1353 1354 1355 .exit_app_or_kernel: 1356 %endif 1357 1358 %if _IMAGE_EXE 1359 %if _BOOTLDR 1360 00000044 F646FE01 test byte [bp - 2], 1 1361 00000048 7405 jz .exit_kernel_mode 1362 %endif 1363 1364 0000004A B87F4C mov ax, 4C7Fh 1365 0000004D CD21 int 21h 1366 1367 .exit_kernel_mode: 1368 %endif 1369 %if _BOOTLDR 1370 0000004F 31C0 xor ax, ax 1371 00000051 CD16 int 16h 1372 00000053 CD19 int 19h 1373 %endif 1374 1375 1376 %if _PROGRESS 1377 step_progress: 1378 00000055 F9 stc 1379 .CF: 1380 00000056 53 push bx 1381 00000057 51 push cx 1382 00000058 52 push dx 1383 00000059 1E push ds 1384 0000005A 56 push si 1385 0000005B 57 push di 1386 0000005C 50 push ax 1387 1388 0000005D 0E push cs 1389 0000005E 1F pop ds 1390 1391 0000005F 8316[9001]00 adc word [.counter], 0 1392 00000064 A1[9001] mov ax, word [.counter] 1393 1394 %if _PROGRESSMULTI 1395 %if _IMAGE_EXE || _DEVICE 1396 %assign defaultprogresshandler _PROGRESSDEFAULT 1397 %else 1398 %assign defaultprogresshandler _PROGRESSDEFAULTBOOT 1399 %endif 1400 00000067 E91600 jmp strict near . %+ defaultprogresshandler %+ _step 1401 .handler: equ $ - 2 ; SMC, patched to dispatch to handler 1402 .base: 1403 %endif 1404 1405 .2_step: 1406 0000006A BAE803 mov dx, 1000 1407 0000006D F7E2 mul dx ; dx:ax = counter times 1000 1408 %if _PROGRESSAMOUNT 1409 0000006F B90100 mov cx, _PROGRESSAMOUNT 1410 00000072 F7F1 div cx ; ax = 0..1000 1411 %else 1412 %warning Progress amount is zero 1413 mov ax, 1 1414 %endif 1415 1416 %if 0 1417 cmp word [.display], ax 1418 je .ret 1419 mov word [.display], ax 1420 %endif 1421 00000074 BE[9901] mov si, .message_number_end - 1 1422 00000077 E80E00 call .format_percentage 1423 1424 0000007A BE[9201] mov si, .message 1425 0000007D E82A01 call disp_error 1426 1427 .ret: 1428 00000080 58 pop ax 1429 .ret_ax: 1430 00000081 5F pop di 1431 00000082 5E pop si 1432 00000083 1F pop ds 1433 00000084 5A pop dx 1434 00000085 59 pop cx 1435 00000086 5B pop bx 1436 .retn: 1437 00000087 C3 retn 1438 1439 1440 .format_percentage: 1441 00000088 BB0200 mov bx, 2 ; skip dot 1442 1443 0000008B B90A00 mov cx, 10 ; base 1444 @@: 1445 0000008E 31D2 xor dx, dx ; dx:ax = current number 1446 00000090 F7F1 div cx ; dl = remainder, ax = next number 1447 00000092 80C230 add dl, '0' ; make decit 1448 00000095 8814 mov byte [si], dl ; store 1449 00000097 29DE sub si, bx ; -> next digit slot 1450 00000099 80FB02 cmp bl, 2 ; did we just store fractional ? 1451 0000009C B301 mov bl, 1 ; ! next iteration do not skip dot 1452 0000009E 74EE je @B ; yes, loop always --> 1453 000000A0 85C0 test ax, ax ; nonzero left ? 1454 000000A2 75EA jnz @B ; yes, loop if so --> 1455 000000A4 C3 retn 1456 1457 1458 %if _PROGRESSMULTI 1459 .0_step: equ .ret 1460 1461 .1_step: 1462 000000A5 58 pop ax 1463 000000A6 E80F01 call disp_al 1464 000000A9 EBD6 jmp .ret_ax 1465 1466 .3_step: 1467 000000AB BB4B00 mov bx, 80 - 1 - 4 1468 000000AE F7E3 mul bx ; dx:ax = counter times 75 1469 %if _PROGRESSAMOUNT 1470 000000B0 B90100 mov cx, _PROGRESSAMOUNT 1471 000000B3 F7F1 div cx ; ax = 0..75 1472 %else 1473 %warning Progress amount is zero 1474 mov ax, 1 1475 %endif 1476 1477 000000B5 3906[8E01] cmp word [.display], ax 1478 000000B9 74C5 je .ret 1479 000000BB A3[8E01] mov word [.display], ax 1480 1481 000000BE 50 push ax 1482 000000BF 91 xchg cx, ax 1483 000000C0 B00D mov al, 13 1484 000000C2 E8F300 call disp_al 1485 000000C5 B05B mov al, '[' 1486 000000C7 E8EE00 call disp_al 1487 000000CA B020 mov al, 32 1488 000000CC E8E900 call disp_al 1489 1490 000000CF B023 mov al, '#' 1491 000000D1 E305 jcxz @FF 1492 @@: 1493 000000D3 E8E200 call disp_al 1494 000000D6 E2FB loop @B 1495 @@: 1496 1497 000000D8 B020 mov al, 32 1498 000000DA 59 pop cx 1499 000000DB 29CB sub bx, cx 1500 000000DD 7607 jbe @FF 1501 000000DF 89D9 mov cx, bx 1502 @@: 1503 000000E1 E8D400 call disp_al 1504 000000E4 E2FB loop @B 1505 @@: 1506 1507 .m4done: 1508 000000E6 E8CF00 call disp_al 1509 000000E9 B05D mov al, ']' 1510 000000EB E8CA00 call disp_al 1511 000000EE EB90 jmp .ret 1512 1513 1514 .4_step: 1515 000000F0 50 push ax 1516 1517 000000F1 BAE803 mov dx, 1000 1518 000000F4 F7E2 mul dx ; dx:ax = counter times 1000 1519 %if _PROGRESSAMOUNT 1520 000000F6 B90100 mov cx, _PROGRESSAMOUNT 1521 000000F9 F7F1 div cx ; ax = 0..1000 1522 %else 1523 %warning Progress amount is zero 1524 mov ax, 1 1525 %endif 1526 1527 000000FB BE[A301] mov si, .message_4_number_end - 1 1528 000000FE E887FF call .format_percentage 1529 1530 00000101 58 pop ax 1531 00000102 BB4B00 mov bx, 80 - 1 - 4 1532 00000105 F7E3 mul bx ; dx:ax = counter times 75 1533 %if _PROGRESSAMOUNT 1534 00000107 B90100 mov cx, _PROGRESSAMOUNT 1535 0000010A F7F1 div cx ; ax = 0..75 1536 %else 1537 %warning Progress amount is zero 1538 mov ax, 1 1539 %endif 1540 1541 0000010C 50 push ax 1542 0000010D 91 xchg cx, ax 1543 0000010E B00D mov al, 13 1544 00000110 E8A500 call disp_al 1545 00000113 B05B mov al, '[' 1546 00000115 E8A000 call disp_al 1547 00000118 B020 mov al, 32 1548 0000011A E89B00 call disp_al 1549 1550 0000011D 31FF xor di, di 1551 0000011F BA2200 mov dx, (80 - 1 - 4 - .message_4_length) / 2 1552 00000122 803E[9F01]20 cmp byte [.message_4_number], 32 1553 00000127 7401 je @F 1554 00000129 47 inc di 1555 @@: 1556 0000012A 29FA sub dx, di 1557 1558 0000012C B023 mov al, '#' 1559 0000012E E306 jcxz @FF 1560 @@: 1561 00000130 E88500 call disp_al 1562 00000133 4A dec dx 1563 00000134 E0FA loopnz @B 1564 @@: 1565 1566 00000136 85D2 test dx, dx 1567 00000138 752E jnz .notyetm4 1568 1569 0000013A BE[9F01] mov si, .message_4 1570 0000013D 29FE sub si, di 1571 0000013F E86800 call disp_error 1572 1573 00000142 29F9 sub cx, di 1574 00000144 760E jbe @FF 1575 00000146 83E907 sub cx, .message_4_length 1576 00000149 7609 jbe @FF 1577 0000014B 89CA mov dx, cx 1578 0000014D B023 mov al, '#' 1579 @@: 1580 0000014F E86600 call disp_al 1581 00000152 E2FB loop @B 1582 @@: 1583 00000154 59 pop cx 1584 00000155 B020 mov al, 32 1585 00000157 83EB29 sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length 1586 0000015A 29D3 sub bx, dx 1587 0000015C 7607 jbe @FF 1588 0000015E 89D9 mov cx, bx 1589 @@: 1590 00000160 E85500 call disp_al 1591 00000163 E2FB loop @B 1592 @@: 1593 00000165 E97EFF jmp .m4done 1594 1595 .notyetm4: 1596 00000168 B020 mov al, 32 1597 0000016A 59 pop cx 1598 0000016B 29CB sub bx, cx 1599 0000016D 7608 jbe @FF 1600 0000016F 89D9 mov cx, bx 1601 @@: 1602 00000171 E84400 call disp_al 1603 00000174 4A dec dx 1604 00000175 E0FA loopnz @B 1605 @@: 1606 1607 00000177 BE[9F01] mov si, .message_4 1608 0000017A 29FE sub si, di 1609 0000017C E82B00 call disp_error 1610 1611 0000017F B020 mov al, 32 1612 00000181 29F9 sub cx, di 1613 00000183 83E907 sub cx, .message_4_length 1614 ; jbe @FF 1615 @@: 1616 00000186 E82F00 call disp_al 1617 00000189 E2FB loop @B 1618 @@: 1619 0000018B E958FF jmp .m4done 1620 %endif 1621 1622 align 2, db 0 1623 %if _PROGRESSMULTI 1624 0000018E FFFF .display: dw -1 1625 %endif 1626 00000190 0000 .counter: dw 0 1627 00000192 0D5B20 .message: db 13,"[ " 1628 00000195 2020312E30 .message_number:db " 1.0" ; enough digit slots for 100.0%, 1629 ; blanks are pre-init until written 1630 .message_number_end: 1631 0000019A 25205D00 db "% ]",0 1632 %if _PROGRESSMULTI 1633 0000019E 20 db " " 1634 .message_4: 1635 0000019F 2020312E30 .message_4_number:db " 1.0" ; enough digit slots for 100.0%, 1636 ; blanks are pre-init until written 1637 .message_4_number_end: 1638 000001A4 252000 db "% ",0 1639 .message_4_length: equ $ - 1 - .message_4 1640 %endif 1641 %endif 1642 1643 1644 %if _DEVICE 1645 align 16 1646 device_header_copy: 1647 .: 1648 .next: 1649 dd -1 ; already initialised 1650 .attributes: 1651 dw _DEVICE_ATTRIBUTE 1652 .strategy: 1653 dw .strategy_entry - . ; -> strategy entry 1654 .interrupt: 1655 dw .interrupt_entry - . ; -> interrupt entry 1656 .name: 1657 fill 8, 32, db _DEVICE_NAME 1658 1659 .strategy_entry: 1660 fill 4, 90h, jmp .set_error ; rel8 or rel16 jump, not minus . 1661 .interrupt_entry: 1662 fill 4, 90h, retf 1663 1664 .set_error: 1665 mov word [es:bx + 3], 8103h ; set error, done, invalid command 1666 retf 1667 .length: equ $ - . 1668 %endif 1669 1670 1671 disp_error.loop: 1672 000001A7 E80E00 call disp_al 1673 disp_error: 1674 000001AA AC lodsb 1675 000001AB 84C0 test al, al 1676 000001AD 75F8 jnz .loop 1677 000001AF C3 retn 1678 1679 %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3 1680 disp_ax_hex: ; ax 1681 xchg al,ah 1682 call disp_al_hex ; display former ah 1683 xchg al,ah ; and fall trough for al 1684 disp_al_hex: ; al 1685 push cx 1686 mov cl,4 1687 ror al,cl 1688 call disp_al_lownibble_hex ; display former high-nibble 1689 rol al,cl 1690 pop cx 1691 ; and fall trough for low-nibble 1692 disp_al_lownibble_hex: 1693 push ax ; save ax for call return 1694 and al,00001111b ; high nibble must be zero 1695 add al,'0' ; if number is 0-9, now it's the correct character 1696 cmp al,'9' 1697 jna .decimalnum ; if we get decimal number with this, ok --> 1698 add al,7 ; otherwise, add 7 and we are inside our alphabet 1699 .decimalnum: 1700 call disp_al 1701 pop ax 1702 retn 1703 %endif 1704 1705 1706 disp_al_for_progress: 1707 %if _PROGRESS && _PROGRESSMULTI 1708 000001B0 2E833E[6800]16 cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base 1709 000001B6 741B je disp_al.retn 1710 %endif 1711 disp_al: 1712 %if _TEST_PROGRAM 1713 000001B8 C3 retn 1714 %else 1715 push ax 1716 %endif 1717 %if _BOOTLDR 1718 000001B9 53 push bx 1719 000001BA 55 push bp 1720 000001BB B40E mov ah, 0Eh 1721 000001BD BB0700 mov bx, 7 1722 %endif 1723 %if _IMAGE_EXE || _DEVICE 1724 000001C0 52 push dx 1725 1726 %if _BOOTLDR 1727 000001C1 F646FE03 test byte [bp - 2], 1 | 2 1728 000001C5 7406 jz .display_kernel_mode 1729 %endif 1730 1731 000001C7 92 xchg dx, ax ; dl = input al 1732 000001C8 B402 mov ah, 02h 1733 000001CA CD21 int 21h 1734 %if _BOOTLDR 1735 000001CC A9 db __TEST_IMM16 ; (skip int) 1736 %endif 1737 1738 .display_kernel_mode: 1739 %endif 1740 %if _BOOTLDR 1741 000001CD CD10 int 10h 1742 %endif 1743 %if _IMAGE_EXE 1744 000001CF 5A pop dx 1745 %endif 1746 %if _BOOTLDR 1747 000001D0 5D pop bp 1748 000001D1 5B pop bx 1749 %endif 1750 000001D2 58 pop ax 1751 .retn: 1752 disp_error.ret: 1753 000001D3 C3 retn 1754 1755 1756 msg: 1757 %if _DEBUG0 1758 .error_begin: db "Load error: Decompression failure, code ",0 1759 .error_end: db "h.",13,10,0 1760 %else 1761 000001D4 4C6F6164206572726F- .error: db "Load error: Decompression failure.",13,10,0 1761 000001DD 723A204465636F6D70- 1761 000001E6 72657373696F6E2066- 1761 000001EF 61696C7572652E0D0A- 1761 000001F8 00 1762 %endif 1763 1764 1765 %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1 1766 %assign NEED_NORMALISE_BOTH_POINTERS 1 1767 %assign CHECK_POINTERS_VARIABLE_SRC 1 1768 %assign CHECK_POINTERS_VARIABLE_DST 1 1769 1770 ; Specific depacker's file is included within label msg. 1771 ; In the file, lframe is used and lleave ctx is not used. 1772 1773 %if _BRIEFLZ 1774 %include "brieflz.asm" 1775 %endif 1776 1777 1778 %if _LZ4 1779 %include "lz4.asm" 1 <1> 2 <1> %if 0 3 <1> 4 <1> 8086 Assembly lDOS iniload payload LZ4 depacker 5 <1> by E. C. Masloch, 2018 6 <1> 7 <1> Usage of the works is permitted provided that this 8 <1> instrument is retained with the works, so that any entity 9 <1> that uses the works is notified of this instrument. 10 <1> 11 <1> DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY. 12 <1> 13 <1> %endif 14 <1> 15 <1> 16 <1> lz4_flg_version_mask: equ 1100_0000b 17 <1> lz4_flg_version: equ 0100_0000b 18 <1> lz4_flg_b_indep: equ 0010_0000b 19 <1> lz4_flg_b_checksum: equ 0001_0000b 20 <1> lz4_flg_c_size: equ 0000_1000b 21 <1> lz4_flg_c_checksum: equ 0000_0100b 22 <1> lz4_flg_reserved: equ 0000_0010b 23 <1> lz4_flg_dict_id: equ 0000_0001b 24 <1> 25 <1> lz4_bd_reserved_mask: equ 1000_1111b 26 <1> ; BD block max size is not used by us 27 <1> 28 <1> 29 <1> ; INP: ds:si -> source 30 <1> ; dx:cx = length of source 31 <1> ; es:di -> destination (below source) 32 <1> ; if _IMAGE_EXE: 33 <1> ; bx = EXE mode flag (bit 0) 34 <1> ; else: 35 <1> ; bx = 0 36 <1> ; if _PAYLOAD_KERNEL_MAX_PARAS: 37 <1> ; ax = maximum amount in paragraphs of destination needed 38 <1> ; (-1 if full source should be decompressed) 39 <1> ; else: 40 <1> ; ax = -1 41 <1> ; OUT: NC if success 42 <1> ; CY if error, 43 <1> ; bx = ?errordata (if _DEBUG0) 44 <1> ; CHG: ax, (bx), cx, dx, es, ds, si, di 45 <1> ; STT: UP 46 <1> ; 47 <1> ; Note: The destination reaches up to below the source. 48 <1> ; Note: The input pointers need not be normalised yet. 49 <1> ; Normalised means that the offset part is below 16. 50 <1> depack: 51 <1> lframe near 52 <1> %if _IMAGE_EXE || _DEBUG0 || _COUNTER 53 000001F9 5589E5 <1> lenter early 54 <1> %if _IMAGE_EXE 55 <1> lvar word, exemode ; must be bp - 2! 56 000001FC 53 <1> push bx 57 <1> %if ?exemode != -2 58 <1> %error exemode variable must be directly below bp 59 <1> %endif 60 <1> %endif 61 <1> %if _DEBUG0 || _COUNTER 62 000001FD 31DB <1> xor bx, bx 63 <1> %endif 64 <1> %if _DEBUG0 65 <1> lvar word, errordata 66 <1> push bx 67 <1> %endif 68 <1> %endif 69 <1> lvar word, token_and_counter 70 <1> lequ ?token_and_counter, token 71 <1> lequ ?token_and_counter + 1, counter 72 <1> %if _COUNTER 73 000001FF 53 <1> push bx ; initialise counter (high byte) to zero 74 <1> %endif 75 <1> lvar dword, src_behind_block 76 <1> lvar word, frame_descriptor_flg_and_bd 77 00000200 8D66F6 <1> lenter 78 <1> 79 00000203 E8A302 <1> call normalise_both_pointers 80 <1> 81 <1> lvar dword, src 82 00000206 1E <1> push ds 83 00000207 56 <1> push si 84 <1> lvar dword, original_dst 85 00000208 06 <1> push es 86 00000209 57 <1> push di 87 <1> lvar dword, dst 88 0000020A 06 <1> push es 89 0000020B 57 <1> push di 90 <1> lvar dword, length_of_source 91 0000020C 52 <1> push dx 92 0000020D 51 <1> push cx 93 <1> 94 <1> %if _PAYLOAD_KERNEL_MAX_PARAS 95 <1> cmp ax, -1 ; no maximum specified ? 96 <1> je @FF ; retain -1 in ax --> 97 <1> test di, di ; do we need an additional paragraph ? 98 <1> jz @F ; no --> 99 <1> inc ax ; es + ax => paragraph after necessary part 100 <1> @@: 101 <1> mov dx, es 102 <1> add ax, dx ; => paragraph after necessary part 103 <1> ; If the normalised destination pointer's segment grows 104 <1> ; to this segment then enough has been decompressed. 105 <1> d0 mov byte [bp + ?errordata], 40h 106 <1> jc .error ; should not carry 107 <1> @@: 108 <1> lvar word, dst_max_segment 109 <1> push ax 110 <1> %endif 111 <1> 112 0000020E 1E <1> push ds 113 0000020F 56 <1> push si 114 00000210 E8F602 <1> call pointer_to_linear 115 <1> 116 00000213 89D3 <1> mov bx, dx 117 00000215 91 <1> xchg cx, ax ; bx:cx = source linear 118 <1> 119 00000216 06 <1> push es 120 00000217 57 <1> push di 121 00000218 E8EE02 <1> call pointer_to_linear 122 <1> 123 <1> %if _ALLOW_OVERLAPPING 124 0000021B 034EE6 <1> add cx, word [bp + ?length_of_source] 125 0000021E 135EE8 <1> adc bx, word [bp + ?length_of_source + 2] 126 <1> ; In case of allowing overlapping source and destination, 127 <1> ; the ?length_of_destination variable is set to 128 <1> ; ?src + ?length_of_source - ?dst, allowing to write to 129 <1> ; all of the source buffer (with the checks already in place 130 <1> ; from the default handling). Additional checks are done by 131 <1> ; calling check_pointers_not_overlapping. This is done after 132 <1> ; every change of ?dst to verify that the write pointer stays 133 <1> ; below-or-equal the read pointer. 134 <1> ; This means the remaining source data may be corrupted by a 135 <1> ; write, but nothing after the source data is written to, 136 <1> ; so the error handling (in INIT1 after the data) still works. 137 <1> %endif 138 <1> 139 00000221 29C1 <1> sub cx, ax 140 00000223 19D3 <1> sbb bx, dx ; bx:cx = source linear - destination linear 141 <1> 142 <1> lvar dword, length_of_destination 143 00000225 53 <1> push bx ; push into [bp + ?length_of_destination + 2] 144 00000226 51 <1> push cx ; push into [bp + ?length_of_destination] 145 <1> 146 <1> %if _ALLOW_OVERLAPPING 147 00000227 E86302 <1> call check_pointers_not_overlapping 148 <1> ; Note: We initially check here that the write pointer is 149 <1> ; low enough, ie below-or-equal the read pointer. 150 <1> ; Doing this check here (as well as after any 151 <1> ; copied match) allows us to drop the check done 152 <1> ; after moving literal bytes. 153 <1> d0 mov byte [bp + ?errordata], 1Bh 154 0000022A 720D <1> jc .error 155 <1> %endif 156 <1> 157 <1> .loop_frame: 158 0000022C 31C9 <1> xor cx, cx 159 0000022E 394EE8 <1> cmp word [bp + ?length_of_source + 2], cx 160 00000231 7517 <1> jne @F 161 00000233 394EE6 <1> cmp word [bp + ?length_of_source], cx 162 00000236 7512 <1> jne @F 163 <1> 164 <1> .end: 165 00000238 A8 <1> db __TEST_IMM8 ; (NC) 166 <1> .error: 167 00000239 F9 <1> stc 168 <1> 169 <1> %if _COUNTER 170 0000023A 9F <1> lahf 171 0000023B B00D <1> mov al, 13 172 0000023D E870FF <1> call disp_al_for_progress 173 00000240 B00A <1> mov al, 10 174 00000242 E86BFF <1> call disp_al_for_progress 175 00000245 9E <1> sahf 176 <1> %endif 177 <1> d0 mov bx, word [bp + ?errordata] 178 00000246 89EC5D <1> lleave code 179 00000249 C3 <1> lret 180 <1> 181 <1> 182 <1> @@: 183 0000024A B104 <1> mov cl, 4 184 0000024C E81B02 <1> call read_le_data_src 185 <1> d0 mov byte [bp + ?errordata], 1 186 0000024F 72E8 <1> jc .error 187 <1> 188 00000251 81FA4D18 <1> cmp dx, 184Dh ; signature match ? 189 <1> d0 mov byte [bp + ?errordata], 2 190 00000255 75E2 <1> jne .error ; no --> 191 00000257 3D0422 <1> cmp ax, 2204h ; usual frame ? 192 0000025A 7427 <1> je @F ; yes --> 193 <1> 194 0000025C 24F0 <1> and al, ~0Fh 195 0000025E 3D502A <1> cmp ax, 2A50h ; skippable frame ? 196 <1> d0 mov byte [bp + ?errordata], 3 197 00000261 75D6 <1> jne .error ; no --> 198 <1> 199 <1> ; cx = 4 still here 200 00000263 E80402 <1> call read_le_data_src ; read length of skippable frame 201 <1> d0 mov byte [bp + ?errordata], 4 202 00000266 72D1 <1> jc .error 203 <1> 204 00000268 1E <1> push ds 205 00000269 56 <1> push si 206 0000026A 89C1 <1> mov cx, ax 207 0000026C 89D3 <1> mov bx, dx ; displacement = skippable frame length 208 0000026E E86902 <1> call normalise_pointer_with_displacement_bxcx 209 00000271 8F46F2 <1> pop word [bp + ?src] 210 00000274 8F46F4 <1> pop word [bp + ?src + 2] ; ?src += length 211 <1> d0 mov byte [bp + ?errordata], 1Dh 212 00000277 72C0 <1> jc .error 213 <1> 214 00000279 2946E6 <1> sub word [bp + ?length_of_source], ax 215 0000027C 1956E8 <1> sbb word [bp + ?length_of_source + 2], dx 216 <1> ; ?length_of_source -= length 217 <1> d0 mov byte [bp + ?errordata], 5 218 0000027F 72B8 <1> jc .error 219 00000281 EBA9 <1> jmp .loop_frame 220 <1> 221 <1> 222 <1> @@: 223 00000283 B102 <1> mov cl, 2 224 00000285 E8E201 <1> call read_le_data_src ; read FLG (low byte), BD (high byte) 225 <1> d0 mov byte [bp + ?errordata], 6 226 <1> .error_CY_1: 227 00000288 72AF <1> jc .error 228 <1> 229 0000028A 8946F6 <1> mov word [bp + ?frame_descriptor_flg_and_bd], ax 230 0000028D 89C3 <1> mov bx, ax 231 0000028F 80E3C0 <1> and bl, lz4_flg_version_mask 232 00000292 80FB40 <1> cmp bl, lz4_flg_version ; version correct ? 233 <1> d0 mov byte [bp + ?errordata], 7 234 <1> .error_NZ_1: 235 00000295 75A2 <1> jne .error ; no --> 236 <1> 237 00000297 A9038F <1> test ax, (lz4_bd_reserved_mask << 8) | lz4_flg_reserved | lz4_flg_dict_id ; unsupported bits set? 239 <1> d0 mov byte [bp + ?errordata], 8 240 0000029A 75F9 <1> jnz .error_NZ_1 ; yes --> 241 <1> 242 <1> ; not checked: lz4_flg_b_indep (linked is always supported), 243 <1> ; lz4_flg_b_checksum, lz4_flg_c_checksum (both checked later) 244 <1> 245 0000029C A808 <1> test al, lz4_flg_c_size ; content size field present ? 246 0000029E 7407 <1> jz @F ; no --> 247 000002A0 B108 <1> mov cl, 8 248 000002A2 E8C501 <1> call read_le_data_src ; (skip content size field) 249 <1> d0 mov byte [bp + ?errordata], 9 250 000002A5 72E1 <1> jc .error_CY_1 251 <1> @@: 252 000002A7 B101 <1> mov cl, 1 253 000002A9 E8BE01 <1> call read_le_data_src ; (skip header checksum field) 254 <1> d0 mov byte [bp + ?errordata], 0Ah 255 000002AC 72DA <1> jc .error_CY_1 256 <1> 257 <1> .loop_block: 258 <1> %if _COUNTER && !_PROGRESS 259 <1> mov al, '#' 260 <1> call disp_al 261 <1> %endif 262 000002AE B90400 <1> mov cx, 4 263 000002B1 E8B601 <1> call read_le_data_src ; read block size field 264 <1> ; leaves ds:si -> source 265 <1> d0 mov byte [bp + ?errordata], 0Bh 266 000002B4 72D2 <1> jc .error_CY_1 267 <1> 268 000002B6 85D2 <1> test dx, dx ; nonzero ? 269 000002B8 7512 <1> jnz @FF 270 000002BA 85C0 <1> test ax, ax 271 000002BC 750E <1> jnz @FF ; yes --> 272 <1> 273 000002BE F646F604 <1> test byte [bp + ?frame_descriptor_flg_and_bd], lz4_flg_c_checksum 274 000002C2 7405 <1> jz @F 275 <1> ; cx = 4 already 276 000002C4 E8A301 <1> call read_le_data_src ; (skip c checksum field) 277 <1> d0 mov byte [bp + ?errordata], 0Ch 278 <1> .error_CY_2: 279 000002C7 72BF <1> jc .error_CY_1 280 <1> @@: 281 000002C9 E960FF <1> jmp .loop_frame ; next frame, if any --> 282 <1> 283 <1> 284 <1> @@: 285 000002CC 1E <1> push ds 286 000002CD 56 <1> push si ; -> source 287 000002CE 89D3 <1> mov bx, dx 288 000002D0 80E77F <1> and bh, ~80h ; clear "uncompressed" flag 289 000002D3 89C1 <1> mov cx, ax ; bx:cx = block size 290 000002D5 E80202 <1> call normalise_pointer_with_displacement_bxcx 291 <1> ; -> source after block 292 000002D8 8F46F8 <1> pop word [bp + ?src_behind_block] 293 000002DB 8F46FA <1> pop word [bp + ?src_behind_block + 2] 294 <1> d0 mov byte [bp + ?errordata], 1Eh 295 000002DE 7303E956FF <1> jc .error 296 000002E3 F6C680 <1> test dh, 80h ; is it uncompressed ? 297 000002E6 7448 <1> jz .compressed ; no --> 298 <1> 299 <1> .uncompressed: 300 000002E8 87DA <1> xchg bx, dx ; get size without "uncompressed" flag 301 000002EA E8FC00 <1> call lz4_copy_literal_or_uncompressed 302 <1> d0 mov byte [bp + ?errordata], 0Dh 303 000002ED 72D8 <1> jc .error_CY_2 304 <1> 305 <1> .end_block: 306 000002EF FF76FA <1> push word [bp + ?src_behind_block + 2] 307 000002F2 FF76F8 <1> push word [bp + ?src_behind_block] 308 000002F5 E81102 <1> call pointer_to_linear 309 000002F8 89C1 <1> mov cx, ax 310 000002FA 89D3 <1> mov bx, dx ; bx:cx = linear ?src_behind_block 311 <1> 312 000002FC FF76F4 <1> push word [bp + ?src + 2] 313 000002FF FF76F2 <1> push word [bp + ?src] 314 00000302 E80402 <1> call pointer_to_linear ; dx:ax = linear ?src 315 <1> 316 00000305 29C1 <1> sub cx, ax 317 00000307 19D3 <1> sbb bx, dx ; ?src_behind_block - ?src 318 <1> ; = amount to skip 319 <1> d0 mov byte [bp + ?errordata], 0Fh 320 00000309 72BC <1> jc .error_CY_2 321 <1> 322 0000030B 294EE6 <1> sub word [bp + ?length_of_source], cx 323 0000030E 195EE8 <1> sbb word [bp + ?length_of_source + 2], bx 324 <1> d0 mov byte [bp + ?errordata], 10h 325 <1> .error_CY_3: 326 00000311 72B4 <1> jc .error_CY_2 ; not enough data to skip --> 327 <1> 328 00000313 FF76FA <1> push word [bp + ?src_behind_block + 2] 329 00000316 FF76F8 <1> push word [bp + ?src_behind_block] 330 00000319 8F46F2 <1> pop word [bp + ?src] 331 0000031C 8F46F4 <1> pop word [bp + ?src + 2] ; set ?src -> behind block 332 <1> 333 0000031F F646F610 <1> test byte [bp + ?frame_descriptor_flg_and_bd], lz4_flg_b_checksum 334 00000323 7408 <1> jz @F ; no block checksum --> 335 00000325 B90400 <1> mov cx, 4 336 00000328 E83F01 <1> call read_le_data_src ; (skip block checksum field) 337 <1> d0 mov byte [bp + ?errordata], 0Eh 338 0000032B 72E4 <1> jc .error_CY_3 339 <1> @@: 340 <1> 341 0000032D E97EFF <1> jmp .loop_block 342 <1> 343 <1> 344 <1> .compressed: 345 <1> .loop_sequence: 346 <1> 347 <1> %if _COUNTER 348 00000330 FE46FD <1> inc byte [bp + ?counter] 349 00000333 F646FD1F <1> test byte [bp + ?counter], _COUNTER - 1 350 00000337 7505 <1> jnz @F 351 00000339 B02E <1> mov al, '.' 352 0000033B E8FEFC <1> call disp_al_counter 353 <1> @@: 354 <1> %endif 355 <1> 356 0000033E BB[BC03] <1> mov bx, .lodsb 357 00000341 E8EE00 <1> call lz4_func_bx_with_src ; load token 358 <1> d0 mov byte [bp + ?errordata], 11h 359 00000344 72CB <1> jc .error_CY_3 360 00000346 8846FC <1> mov byte [bp + ?token], al 361 <1> 362 00000349 B104 <1> mov cl, 4 363 0000034B D2E8 <1> shr al, cl 364 0000034D E8F300 <1> call lz4_get_length ; dx:cx = length of literals 365 <1> d0 mov byte [bp + ?errordata], 12h 366 00000350 72BF <1> jc .error_CY_3 367 <1> 368 00000352 89C8 <1> mov ax, cx ; dx:ax = length of literals (may be 0) 369 00000354 E89200 <1> call lz4_copy_literal_or_uncompressed 370 <1> ; copy over the literals 371 <1> d0 mov byte [bp + ?errordata], 13h 372 00000357 72B8 <1> jc .error_CY_3 373 <1> 374 00000359 E87800 <1> call lz4_check_behind_block_higher_than_src 375 <1> ; do we have more data in this block ? 376 0000035C 725B <1> jc .end_sequence ; no --> 377 <1> 378 0000035E BB[C803] <1> mov bx, .lodsw 379 00000361 E8CE00 <1> call lz4_func_bx_with_src ; load match offset 380 <1> d0 mov byte [bp + ?errordata], 14h 381 <1> .error_CY_4: 382 00000364 72AB <1> jc .error_CY_3 383 <1> 384 00000366 85C0 <1> test ax, ax ; offset is 0 ? 385 <1> d0 mov byte [bp + ?errordata], 15h 386 00000368 F9 <1> stc 387 00000369 74F9 <1> jz .error_CY_4 ; yes, error --> 388 <1> 389 0000036B 89C1 <1> mov cx, ax 390 0000036D F7D9 <1> neg cx ; -1 .. -65535 391 0000036F BBFFFF <1> mov bx, -1 ; sign-extend (always negative sense) 392 <1> 393 00000372 FF76EC <1> push word [bp + ?dst + 2] 394 00000375 FF76EA <1> push word [bp + ?dst] 395 00000378 E85F01 <1> call normalise_pointer_with_displacement_bxcx 396 0000037B 5E <1> pop si 397 0000037C 1F <1> pop ds ; ds:si -> source of matching 398 <1> d0 mov byte [bp + ?errordata], 1Fh 399 0000037D 7203E9B7FE <1> jnc .error 400 <1> 401 00000382 8CD8 <1> mov ax, ds ; is source of matching within ?dst ? 402 00000384 3946F0 <1> cmp word [bp + ?original_dst + 2], ax 403 <1> d0 mov byte [bp + ?errordata], 16h 404 <1> .error_A_1: 405 00000387 7603E9ADFE <1> ja .error 406 0000038C 7205 <1> jb @F 407 0000038E 3976EE <1> cmp word [bp + ?original_dst], si 408 <1> d0 mov byte [bp + ?errordata], 17h 409 00000391 77F4 <1> ja .error_A_1 ; no, ?original_dst is above it --> 410 <1> @@: 411 <1> 412 00000393 8A46FC <1> mov al, byte [bp + ?token] 413 00000396 240F <1> and al, 0Fh ; get match length from token 414 00000398 E8A800 <1> call lz4_get_length ; dx:cx = length of match - 4 415 <1> d0 mov byte [bp + ?errordata], 18h 416 0000039B 72C7 <1> jc .error_CY_4 417 0000039D 89C8 <1> mov ax, cx ; dx:ax = length of match - 4 418 0000039F 83C004 <1> add ax, 4 419 000003A2 83D200 <1> adc dx, 0 ; dx:ax = length of match 420 <1> d0 mov byte [bp + ?errordata], 19h 421 000003A5 72BD <1> jc .error_CY_4 422 000003A7 E85400 <1> call lz4_copy_data ; give ?dst -> dest, ds:si -> source 423 <1> ; returns: ?dst incremented, ds:si -> after match source 424 <1> d0 mov byte [bp + ?errordata], 1Ah 425 000003AA 72B8 <1> jc .error_CY_4 426 <1> 427 <1> %if _ALLOW_OVERLAPPING 428 000003AC E8DE00 <1> call check_pointers_not_overlapping 429 <1> d0 mov byte [bp + ?errordata], 1Ch 430 000003AF 72B3 <1> jc .error_CY_4 431 <1> %endif 432 <1> 433 <1> .next_sequence: 434 000003B1 E82000 <1> call lz4_check_behind_block_higher_than_src 435 000003B4 7203E977FF <1> jnc .loop_sequence ; process next sequence --> 436 <1> 437 <1> .end_sequence: 438 000003B9 E933FF <1> jmp .end_block 439 <1> 440 <1> 441 <1> ; INP: ds:si -> source data 442 <1> ; ?length_of_source 443 <1> ; OUT: CY if error (source buffer too small) 444 <1> ; NC if success, 445 <1> ; al = value read 446 <1> ; ds:si incremented (NOT normalised) 447 <1> ; ?length_of_source decremented 448 <1> .lodsb: 449 000003BC 836EE601 <1> sub word [bp + ?length_of_source], 1 450 000003C0 835EE800 <1> sbb word [bp + ?length_of_source + 2], 0 451 000003C4 7201 <1> jb .retn 452 000003C6 AC <1> lodsb 453 <1> .retn: 454 000003C7 C3 <1> retn 455 <1> 456 <1> 457 <1> ; INP: ds:si -> source data 458 <1> ; ?length_of_source 459 <1> ; OUT: CY if error (source buffer too small) 460 <1> ; NC if success, 461 <1> ; ax = value read 462 <1> ; ds:si incremented (NOT normalised) 463 <1> ; ?length_of_source decremented 464 <1> .lodsw: 465 000003C8 836EE602 <1> sub word [bp + ?length_of_source], 2 466 000003CC 835EE800 <1> sbb word [bp + ?length_of_source + 2], 0 467 000003D0 72F5 <1> jb .retn 468 000003D2 AD <1> lodsw 469 000003D3 C3 <1> retn 470 <1> 471 <1> 472 <1> ; INP: ?src_behind_block -> block end (normalised) 473 <1> ; ?src -> current address in source buffer 474 <1> ; OUT: CY if ?src is >= (above-or-equal) ?src_behind_block 475 <1> ; NC else (?src is below ?src_behind_block, more data) 476 <1> ; CHG: ax, dx 477 <1> ; 478 <1> ; Note: Although ?src should always equal ?src_behind_block 479 <1> ; if CY here, we actually check for above-or-equal. 480 <1> lz4_check_behind_block_higher_than_src: 481 000003D4 8B56FA <1> mov dx, word [bp + ?src_behind_block + 2] 482 000003D7 8B46F8 <1> mov ax, word [bp + ?src_behind_block] 483 <1> ; dx:ax -> behind block 484 <1> 485 000003DA 3956F4 <1> cmp word [bp + ?src + 2], dx ; compare segment 486 000003DD 7708 <1> ja .error ; ?src > dx:ax --> 487 000003DF 7205 <1> jb .success ; ?src < dx:ax --> 488 000003E1 3946F2 <1> cmp word [bp + ?src], ax ; segment is same, compare offset 489 000003E4 7301 <1> jae .error ; ?src >= dx:ax --> 490 <1> 491 <1> .success: 492 000003E6 A8 <1> db __TEST_IMM8 ; (NC) 493 <1> .error: 494 000003E7 F9 <1> stc 495 000003E8 C3 <1> retn 496 <1> 497 <1> 498 <1> ; INP: ?dst -> destination (normalised) 499 <1> ; ?src -> source (normalised) 500 <1> ; dx:ax = how long the literal data is (0 is valid) 501 <1> ; OUT: ?dst incremented (normalised) 502 <1> ; ?src incremented (normalised) 503 <1> ; ?length_of_destination shortened 504 <1> ; ?length_of_source shortened 505 <1> ; CY if error (either buffer too small) 506 <1> ; NC if success 507 <1> ; CHG: cx, dx, ax, es, di, ds, si 508 <1> lz4_copy_literal_or_uncompressed: 509 000003E9 C576F2 <1> lds si, [bp + ?src] 510 <1> 511 000003EC 2946E6 <1> sub word [bp + ?length_of_source], ax 512 000003EF 1956E8 <1> sbb word [bp + ?length_of_source + 2], dx 513 <1> ; enough data exists ? 514 000003F2 7209 <1> jb .return ; no --> (CY) 515 <1> 516 000003F4 E80700 <1> call lz4_copy_data ; CY/NC depending on status 517 <1> 518 000003F7 8976F2 <1> mov word [bp + ?src], si 519 000003FA 8C5EF4 <1> mov word [bp + ?src + 2], ds 520 <1> ; (CF preserved) 521 <1> .return: 522 000003FD C3 <1> retn 523 <1> 524 <1> 525 <1> ; INP: ?dst -> destination (normalised) 526 <1> ; ds:si -> source (normalised) 527 <1> ; dx:ax = how long the data is (0 is valid) 528 <1> ; OUT: ?dst incremented (normalised) 529 <1> ; ds:si incremented (normalised) 530 <1> ; ?length_of_destination shortened 531 <1> ; CY if error (buffer too small) 532 <1> ; NC if success 533 <1> ; Instead of returning, this may jump to depack.end 534 <1> ; if the destination segment grows up to the value 535 <1> ; stored in the ?dst_max_segment variable. It is 536 <1> ; assumed that this will use the stack frame to leave 537 <1> ; the function, therefore discarding any of the stack 538 <1> ; contents between the frame and the stack top. 539 <1> ; CHG: cx, dx, ax, es, di, ds, si 540 <1> lz4_copy_data: 541 <1> d0 inc byte [bp + ?errordata + 1] 542 000003FE 2946E2 <1> sub word [bp + ?length_of_destination], ax 543 00000401 1956E4 <1> sbb word [bp + ?length_of_destination + 2], dx 544 <1> ; enough space left ? 545 00000404 722A <1> jb .error ; no --> 546 <1> 547 00000406 C47EEA <1> les di, [bp + ?dst] 548 <1> .loop: 549 00000409 B9F0FF <1> mov cx, 64 * 1024 - 16 ; block size 550 <1> ; If both pointers are normalised, moving 0FFF0h bytes is 551 <1> ; valid and results in a maximum offset of 0FFFFh in either. 552 <1> 553 0000040C 85D2 <1> test dx, dx ; >= 1_0000h ? 554 0000040E 7508 <1> jnz @F ; yes, full block --> 555 00000410 85C0 <1> test ax, ax ; == 0 ? 556 00000412 7415 <1> jz .end ; yes, done --> 557 00000414 39C8 <1> cmp ax, cx ; can move in one (last) block ? 558 00000416 7607 <1> jbe .last ; yes --> 559 <1> @@: 560 <1> ; no, move one block and continue 561 00000418 29C8 <1> sub ax, cx 562 0000041A 83DA00 <1> sbb dx, 0 ; left over remaining 563 0000041D EB03 <1> jmp .copy 564 <1> 565 <1> .last: 566 0000041F 91 <1> xchg cx, ax ; cx = remaining length 567 00000420 31C0 <1> xor ax, ax ; no more remaining 568 <1> 569 <1> .copy: 570 00000422 F3A4 <1> rep movsb ; move one block (full or partial) 571 <1> 572 00000424 E88200 <1> call normalise_both_pointers 573 00000427 EBE0 <1> jmp .loop 574 <1> 575 <1> .end: 576 00000429 897EEA <1> mov word [bp + ?dst], di 577 0000042C 8C46EC <1> mov word [bp + ?dst + 2], es 578 <1> %if _PAYLOAD_KERNEL_MAX_PARAS 579 <1> mov ax, es 580 <1> cmp ax, word [bp + ?dst_max_segment] 581 <1> jae depack.end 582 <1> %endif 583 <1> 584 0000042F A8 <1> db __TEST_IMM8 ; (NC) 585 <1> .error: 586 00000430 F9 <1> stc 587 00000431 C3 <1> retn 588 <1> 589 <1> 590 <1> ; INP: ?src -> source data 591 <1> ; bx = function to call 592 <1> ; OUT: ds:si = ?src -> behind data (normalised) 593 <1> ; CY if error (buffer too small) 594 <1> ; NC if success 595 <1> ; (CF is passed from what the function at bx returns) 596 <1> ; 597 <1> ; Protocol of function in bx called by this: 598 <1> ; INP: ds:si -> source data 599 <1> ; ?length_of_source 600 <1> ; (may take more inputs depending on function) 601 <1> ; OUT: ds:si incremented (NOT normalised) 602 <1> ; ?length_of_source decremented 603 <1> ; CY if error (buffer too small or other error) 604 <1> ; NC if success 605 <1> ; (may give more outputs depending on function) 606 <1> lz4_func_bx_with_src: 607 00000432 C576F2 <1> lds si, [bp + ?src] 608 00000435 FFD3 <1> call bx 609 00000437 9C <1> pushf 610 00000438 E87500 <1> call normalise_dssi_pointer 611 0000043B 8976F2 <1> mov word [bp + ?src], si 612 0000043E 8C5EF4 <1> mov word [bp + ?src + 2], ds 613 00000441 9D <1> popf 614 00000442 C3 <1> retn 615 <1> 616 <1> 617 <1> ; INP: ?src -> source data 618 <1> ; ?length_of_source 619 <1> ; al = first field data (0 to 15) 620 <1> ; OUT: dx:cx = length value 621 <1> ; ?src incremented 622 <1> ; ?length_of_source decremented 623 <1> ; CY if error (too high or out of source data) 624 <1> ; NC if success 625 <1> ; CHG: ax, bx 626 <1> lz4_get_length: 627 00000443 1E <1> push ds 628 00000444 56 <1> push si 629 <1> 630 00000445 31C9 <1> xor cx, cx 631 00000447 31D2 <1> xor dx, dx ; dx:cx = length field 632 00000449 B40F <1> mov ah, 15 ; first byte maximum value 633 <1> .loop: 634 0000044B 00C1 <1> add cl, al 635 0000044D 80D500 <1> adc ch, 0 636 00000450 83D200 <1> adc dx, 0 ; add in this byte 637 00000453 7211 <1> jc .error ; if too high --> 638 00000455 38E0 <1> cmp al, ah ; is this the maximum value ? 639 00000457 750C <1> jne .end ; no --> 640 00000459 BB[BC03] <1> mov bx, depack.lodsb 641 0000045C E8D3FF <1> call lz4_func_bx_with_src ; load next byte 642 0000045F 7205 <1> jc .error 643 00000461 B4FF <1> mov ah, 255 ; next maximum value is 255 644 00000463 EBE6 <1> jmp .loop ; --> 645 <1> 646 <1> .end: 647 00000465 A8 <1> db __TEST_IMM8 ; (NC) 648 <1> .error: 649 00000466 F9 <1> stc 650 <1> 651 00000467 5E <1> pop si 652 00000468 1F <1> pop ds 653 00000469 C3 <1> retn 654 <1> 655 <1> 656 <1> ; INP: ?src -> source data (normalised) 657 <1> ; cx = size to read, 1 to 4 or higher (at most 0FFF0h) 658 <1> ; ?length_of_source 659 <1> ; OUT: If cx >= 4, 660 <1> ; dx:ax = value read as little-endian 661 <1> ; If cx == 3, 662 <1> ; dl:ax = value read 663 <1> ; If cx == 2, 664 <1> ; ax = value read 665 <1> ; If cx == 1, 666 <1> ; al = value read 667 <1> ; If cx == 0, 668 <1> ; invalid, CY 669 <1> ; ds:si = ?src = incremented source (normalised) 670 <1> ; ?length_of_source decremented 671 <1> ; CY if error (source buffer too small, or cx zero) 672 <1> ; NC if success 673 <1> ; CHG: ds, si, dx, ax 674 <1> ; 675 <1> ; Note: Always reads four bytes at INP:ds:si -> data. 676 <1> read_le_data_src: 677 0000046A E31F <1> jcxz .error 678 <1> 679 0000046C 294EE6 <1> sub word [bp + ?length_of_source], cx 680 0000046F 835EE800 <1> sbb word [bp + ?length_of_source + 2], 0 681 00000473 7216 <1> jb .error 682 <1> 683 00000475 C576F2 <1> lds si, [bp + ?src] 684 <1> 685 00000478 AD <1> lodsw 686 00000479 92 <1> xchg ax, dx ; dx = low word (first) 687 0000047A AD <1> lodsw ; ax = high word (second) 688 0000047B 92 <1> xchg ax, dx ; fix order, dx:ax = dword 689 <1> 690 0000047C 83EE04 <1> sub si, 4 691 0000047F 01CE <1> add si, cx 692 <1> 693 00000481 E82C00 <1> call normalise_dssi_pointer 694 00000484 8976F2 <1> mov word [bp + ?src], si 695 00000487 8C5EF4 <1> mov word [bp + ?src + 2], ds 696 <1> 697 0000048A A8 <1> db __TEST_IMM8 ; (NC) 698 <1> .error: 699 0000048B F9 <1> stc 700 0000048C C3 <1> retn 701 <1> 1780 %endif 1781 1782 1783 %if _SNAPPY 1784 %include "snappy.asm" 1785 %endif 1786 1787 1788 %if _EXODECR 1789 %include "exodecr.asm" 1790 %endif 1791 1792 1793 %if _X 1794 %include "x.asm" 1795 %endif 1796 1797 1798 %if _HEATSHRINK 1799 %include "heatshr.asm" 1800 %endif 1801 1802 1803 %if _LZD 1804 %include "lzd.asm" 1805 %endif 1806 1807 1808 %if _LZO 1809 %include "lzo.asm" 1810 %endif 1811 1812 1813 %if _LZSA2 1814 %include "lzsa2.asm" 1815 %endif 1816 1817 1818 %if _APL 1819 %include "apl.asm" 1820 %endif 1821 1822 1823 %if _BZP 1824 %include "bzp.asm" 1825 %endif 1826 1827 1828 %if _ZEROCOMP 1829 %include "zerocomp.asm" 1830 %endif 1831 1832 1833 %if _MVCOMP 1834 %include "mvcomp.asm" 1835 %endif 1836 1837 1838 %if _LZEXEDAT 1839 %include "lzexedat.asm" 1840 %endif 1841 1842 1843 %if _ALLOW_OVERLAPPING 1844 ; INP: ?src, ?dst 1845 ; OUT: CY if error (?src < ?dst) 1846 ; NC if success 1847 ; CHG: ax, bx, cx, dx 1848 check_pointers_not_overlapping: 1849 %if CHECK_POINTERS_VARIABLE_DST 1850 0000048D FF76EC push word [bp + ?dst + 2] 1851 00000490 FF76EA push word [bp + ?dst] 1852 %else 1853 push es 1854 push di 1855 %endif 1856 00000493 E87300 call pointer_to_linear 1857 1858 00000496 91 xchg cx, ax 1859 00000497 87DA xchg bx, dx ; bx:cx = linear ?dst after write 1860 1861 %if CHECK_POINTERS_VARIABLE_SRC 1862 00000499 FF76F4 push word [bp + ?src + 2] 1863 0000049C FF76F2 push word [bp + ?src] 1864 %else 1865 push ds 1866 push si 1867 %endif 1868 0000049F E86700 call pointer_to_linear ; dx:ax = linear ?src before next read 1869 1870 000004A2 39DA cmp dx, bx ; ?src >= ?dst ? 1871 000004A4 7502 jne @F 1872 000004A6 39C8 cmp ax, cx 1873 @@: 1874 ; (CY) if error (src < dst) 1875 ; (NC) if no error 1876 000004A8 C3 retn 1877 %endif 1878 1879 ; This leaves the lframe context created within the 1880 ; specific depacker's file. The above function 1881 ; check_pointers_not_overlapping uses the frame. 1882 lleave ctx 1883 1884 1885 ; INP: ds:si = pointer 1886 ; es:di = pointer 1887 ; OUT: ds:si normalised 1888 ; es:di normalised 1889 %if NEED_NORMALISE_BOTH_POINTERS 1890 normalise_both_pointers: 1891 000004A9 06 push es 1892 000004AA 57 push di 1893 000004AB E80A00 call normalise_pointer 1894 000004AE 5F pop di 1895 000004AF 07 pop es 1896 %endif 1897 1898 normalise_dssi_pointer: 1899 000004B0 1E push ds 1900 000004B1 56 push si 1901 000004B2 E80300 call normalise_pointer 1902 000004B5 5E pop si 1903 000004B6 1F pop ds 1904 000004B7 C3 retn 1905 1906 1907 ; INP: word [ss:sp + 2] = segment 1908 ; word [ss:sp] = offset 1909 ; 1910 ; Note: Does not work correctly with pointers that point to 1911 ; a HMA location. Do not use then! 1912 normalise_pointer: 1913 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1914 lframe near 1915 lpar word, segment 1916 lpar word, offset 1917 lpar_return 1918 000004B8 5589E5 lenter 1919 1920 000004BB 837E040F cmp word [bp + ?offset], 15 1921 000004BF 7617 jbe .ret 1922 1923 000004C1 53 push bx 1924 000004C2 51 push cx 1925 1926 000004C3 31DB xor bx, bx 1927 000004C5 31C9 xor cx, cx 1928 000004C7 FF7606 push word [bp + ?segment] 1929 000004CA FF7604 push word [bp + ?offset] 1930 000004CD E80A00 call normalise_pointer_with_displacement_bxcx 1931 000004D0 8F4604 pop word [bp + ?offset] 1932 000004D3 8F4606 pop word [bp + ?segment] 1933 1934 000004D6 59 pop cx 1935 000004D7 5B pop bx 1936 .ret: 1937 000004D8 5D lleave 1938 000004D9 C3 lret 1939 1940 1941 ; INP: word [ss:sp + 2] = segment 1942 ; word [ss:sp] = offset 1943 ; bx:cx = add/sub displacement 1944 ; OUT: CY if the displacement carries 1945 ; NC if not 1946 normalise_pointer_with_displacement_bxcx: 1947 %endif 1948 lframe near 1949 lpar word, segment 1950 lpar word, offset 1951 lpar_return 1952 000004DA 5589E5 lenter 1953 1954 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1955 cmp word [bp + ?offset], 15 1956 jbe .ret 1957 %endif 1958 1959 000004DD 50 push ax 1960 000004DE 51 push cx 1961 000004DF 52 push dx 1962 1963 000004E0 FF7606 push word [bp + ?segment] 1964 000004E3 FF7604 push word [bp + ?offset] 1965 000004E6 E82000 call pointer_to_linear 1966 1967 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1968 ; push bx 1969 ; ; sign-extend cx into bx:cx 1970 ; cmp cx, 8000h ; CY if < 8000h (NC if negative) 1971 ; cmc ; NC if positive 1972 ; sbb bx, bx ; 0 if was NC, -1 if was CY 1973 1974 000004E9 01C1 add cx, ax 1975 000004EB 11DA adc dx, bx ; dx:cx = dx:ax + bx:cx 1976 ; pop bx 1977 000004ED 9F lahf ; ah = flags 1978 %else 1979 xchg ax, cx 1980 %endif 1981 1982 %if 0 1983 ; Adds in HMA support for this function. Not currently used. 1984 cmp dx, 10h ; dx:ax >= 10_0000h ? 1985 jb @F ; no, linear-to-pointer normally --> 1986 ; ja .error 1987 1988 add cx, 10h 1989 ; jc .error 1990 mov word [bp + ?offset], cx 1991 or word [bp + ?segment], -1 1992 jmp .return 1993 @@: 1994 %endif 1995 1996 000004EE 53 push bx 1997 000004EF 89CB mov bx, cx 1998 000004F1 83E10F and cx, 15 1999 000004F4 894E04 mov word [bp + ?offset], cx 2000 2001 000004F7 B104 mov cl, 4 2002 @@: 2003 000004F9 D1EA shr dx, 1 2004 000004FB D1DB rcr bx, 1 2005 000004FD E2FA loop @B 2006 2007 000004FF 895E06 mov word [bp + ?segment], bx 2008 00000502 5B pop bx 2009 2010 ; test dx, dx 2011 ; jnz .error 2012 2013 .return: 2014 2015 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2016 00000503 9E sahf ; restore flags from ah 2017 %endif 2018 00000504 5A pop dx 2019 00000505 59 pop cx 2020 00000506 58 pop ax 2021 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2022 .ret: 2023 %endif 2024 00000507 5D lleave 2025 00000508 C3 lret 2026 2027 2028 ; INP: word [ss:sp + 2] = segment 2029 ; word [ss:sp] = offset 2030 ; OUT: dx:ax = linear address 2031 pointer_to_linear: 2032 lframe near 2033 lpar word, segment 2034 lpar word, offset 2035 00000509 5589E5 lenter 2036 2037 0000050C 8B4606 mov ax, word [bp + ?segment] 2038 0000050F 31D2 xor dx, dx 2039 00000511 51 push cx 2040 00000512 B90400 mov cx, 4 2041 @@: 2042 00000515 D1E0 shl ax, 1 2043 00000517 D1D2 rcl dx, 1 2044 00000519 E2FA loop @B 2045 2046 0000051B 034604 add ax, word [bp + ?offset] 2047 0000051E 11CA adc dx, cx ; cx = 0 here 2048 00000520 59 pop cx 2049 2050 00000521 5D lleave 2051 00000522 C20400 lret 2052 2053 2054 %if _PASSLCFG 2055 align 16 2056 transfer_lcfg_block: 2057 times lcfg.size nop 2058 %endif 2059 00000525 90 align 16 2060 init1_end: 2061 2062 2063 usesection INIT0 2064 %if _TEST_PROGRAM 2065 init0_msg: 2066 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 2067 .error_stderr_file: db "Error: Unable to open own executable file.",13,10 2068 .error_stderr_file.length equ $ - .error_stderr_file 2069 %endif 2070 000001B2 4572726F723A204E6F- .error_stderr: db "Error: Not enough memory allocated.",13,10 2070 000001BB 7420656E6F75676820- 2070 000001C4 6D656D6F727920616C- 2070 000001CD 6C6F63617465642E0D- 2070 000001D6 0A 2071 .error_stderr.length: equ $ - .error_stderr 2072 .error_c_stdout: 2073 000001D7 30 .error_stdout: db "0" 2074 %if 0 2075 _autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE + (payload_end - payload) + (init1_end - init1_start) + ADDITIONAL_MEMORY ) 2080 %endif 2081 000001D8 0D0A db 13,10 2082 .error_c_stdout.length: equ $ - .error_c_stdout 2083 .error_stdout.length: equ $ - .error_stdout 2084 2085 000001DA 90 align 1024 2086 %if ($ - $$) != 1024 2087 %error Wrong INIT0 size 2088 %endif 2089 %endif 2090 2091 align 16 2092 init0_end: 2093 2094 2095 %assign num (init1_end - init1_start) + (init0_end - init0_start) 2096 %if _BRIEFLZ 2097 %define which iniblz 2098 %elif _LZ4 2099 %define which inilz4 2100 %elif _SNAPPY 2101 %define which inisz 2102 %elif _EXODECR 2103 %define which iniexo 2104 %elif _X 2105 %define which inix 2106 %elif _HEATSHRINK 2107 %define which inihs 2108 %elif _LZD 2109 %define which inilz 2110 %elif _LZO 2111 %define which inilzo 2112 %elif _LZSA2 2113 %define which inilzsa2 2114 %elif _APL 2115 %define which iniapl 2116 %elif _BZP 2117 %define which inibzp 2118 %elif _ZEROCOMP 2119 %define which inizero 2120 %elif _MVCOMP 2121 %define which inimv 2122 %elif _LZEXEDAT 2123 %define which inilzexe 2124 %endif 2125 %warning which: num bytes used for depacker 2125 ****************** warning: inilz4: 2352 bytes used for depacker [-w+user] 2126 2127 2128 %if _TEST_PROGRAM 2129 addsection INIT2, align=16 follows=INIT1 vstart=0 2130 init2_start: 2131 ; si => after PSP 2132 ; cs => INIT2 2133 ; psp, free, payload, init1, init2, payload space, stack 2134 ; 2135 ; The correct allocation for the test program 2136 ; is image size (init0, payload, init1, init2) 2137 ; minus init0 plus compressed payload size 2138 ; plus decompressed size plus stack. For 2139 ; simplicity, init0 subtraction may be skipped. 2140 2141 ; ss:sp -> word amount repetitions, word ax 2142 ; bx = 1 if A mode test, 2143 ; 8001h if B mode test, 2144 ; 4001h if C mode test 2145 00000000 53 push bx ; push into ?whichtest 2146 2147 lframe 0 2148 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 2149 lpar word, handle 2150 %endif 2151 lpar word, repetitions 2152 lpar word, whichtest 2153 %if _RELOAD_XMS 2154 lvar dword, xmsentry 2155 lvar word, xmshandle 2156 %endif 2157 %if _INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2158 lequ 128, buffersize 2159 lvar ?buffersize, buffer 2160 %endif 2161 00000001 5589E5 lenter 2162 2163 %if _RELOAD_FILE && _RELOAD_XMS 2164 or word [bp + ?xmshandle], -1 2165 %endif 2166 2167 00000004 8B5604 mov dx, word [bp + ?repetitions] 2168 00000007 83FAFF cmp dx, -1 2169 0000000A 7509 jne @F 2170 2171 .cmdline_error: 2172 %if _DEBUG0 2173 mov bx, -1 2174 %endif 2175 0000000C BA[D602] mov dx, init2_msg.cmdline_error 2176 0000000F B92400 mov cx, init2_msg.cmdline_error.length 2177 00000012 E98401 jmp init2_error 2178 2179 2180 @@: 2181 00000015 F6460340 testopt [bp + ?whichtest], 4000h 2182 00000019 750C jnz .a_or_c 2183 0000001B F6460380 testopt [bp + ?whichtest], 8000h 2184 0000001F 7406 jz .a_or_c 2185 .b: 2186 00000021 85D2 test dx, dx 2187 00000023 74E7 jz .cmdline_error 2188 00000025 EB04 jmp @F 2189 2190 .a_or_c: 2191 00000027 85D2 test dx, dx 2192 00000029 75E1 jnz .cmdline_error 2193 @@: 2194 2195 %if _RELOAD_XMS 2196 push si 2197 mov ax, 4300h 2198 int 2Fh 2199 cmp al, 80h 2200 %if _RELOAD_FILE 2201 jne .noxms 2202 %else 2203 jne init2_error_xms 2204 %endif 2205 mov ax, 4310h 2206 int 2Fh 2207 mov word [bp + ?xmsentry], bx 2208 mov word [bp + ?xmsentry + 2], es 2209 mov ah, 09h 2210 mov dx, KiB(payload_end - payload) 2211 call far [bp + ?xmsentry] 2212 cmp ax, 1 2213 %if _RELOAD_FILE 2214 jne .noxms 2215 %else 2216 jne init2_error_xms 2217 %endif 2218 mov word [bp + ?xmshandle], dx 2219 mov ax, cs 2220 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2223 push cs 2224 pop ds 2225 mov si, init2_xmsm_to_save 2226 mov word [si + XMSM.dsthdl], dx 2227 mov word [si + XMSM.srcadr + 2], ax 2228 %ifn _RELOAD_FILE 2229 push ax 2230 %endif 2231 mov ah, 0Bh 2232 call far [bp + ?xmsentry] 2233 cmp ax, 1 2234 jne init2_error_xms_free 2235 %ifn _RELOAD_FILE 2236 pop ax ; => payload 2237 %else 2238 .noxms: 2239 mov ax, cs 2240 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2243 @@: 2244 %endif 2245 pop si 2246 %elif _RELOAD_FILE 2247 mov ax, cs 2248 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2251 %else 2252 0000002B 8CCA mov dx, cs 2253 0000002D 81C23914 add dx, (init2_end - init2_start) >> 4 2254 ; => payload saving area 2255 00000031 8CC8 mov ax, cs 2256 00000033 2D640F sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2259 00000036 B9110F mov cx, (payload_end - payload) >> 4 2260 00000039 E8C102 call init2_movp ; copy payload to payload saving area 2261 %endif 2262 ; We save away the payload here because a failure 2263 ; to decompress generally overwrites part of that 2264 ; payload which was used as source. 2265 2266 0000003C 89C2 mov dx, ax ; dx => payload source to use 2267 0000003E 8CC8 mov ax, cs 2268 00000040 83E853 sub ax, (init1_end - init1_start) >> 4 2269 ; ax => INIT1 2270 00000043 BB0100 mov bx, 1 ; say we're in EXE mode 2271 00000046 52 push dx 2272 00000047 50 push ax 2273 00000048 56 push si ; si => target 2274 00000049 0E push cs 2275 0000004A E80D01 call .transfer ; call decompression 2276 0000004D 5E pop si 2277 0000004E 58 pop ax 2278 0000004F 5A pop dx 2279 ; Returns here after decompression. 2280 ; CY if error. 2281 00000050 7309 jnc @F 2282 2283 00000052 BA[2702] mov dx, init2_msg.initial_error 2284 00000055 B93C00 mov cx, init2_msg.initial_error.length 2285 00000058 E93E01 jmp init2_error_free 2286 2287 @@: 2288 %if _INCLUDE_UNCOMPRESSED 2289 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2290 payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed 2291 %else 2292 payload_uncompressed_size equ _TEST_PROGRAM_DECOMPRESSED_SIZE 2293 %endif 2294 0000005B E80201 call checkdecompressed 2295 0000005E 7409 je @F 2296 2297 %if _WRITE_WRONG_FILE 2298 call writefiles 2299 %endif 2300 2301 %if _DEBUG0 2302 mov bx, -1 2303 %endif 2304 00000060 BA[6302] mov dx, init2_msg.initial_error_2 2305 00000063 B93C00 mov cx, init2_msg.initial_error_2.length 2306 00000066 E93001 jmp init2_error_free 2307 2308 @@: 2309 %endif 2310 2311 00000069 F6460340 testopt [bp + ?whichtest], 4000h 2312 0000006D 741D jz @F 2313 0000006F 8CC8 mov ax, cs 2314 00000071 83E853 sub ax, (init1_end - init1_start) >> 4 2315 ; ax => INIT1 2316 00000074 8EC0 mov es, ax 2317 00000076 26A1[4200] mov ax, word [es:init1_c_mode_counter] 2318 0000007A E85601 call init2_disp_ax_dec 2319 0000007D B00D mov al, 13 2320 0000007F E84601 call init2_disp_al 2321 00000082 B00A mov al, 10 2322 00000084 E84101 call init2_disp_al 2323 %if _RELOAD_XMS 2324 call freexms 2325 %endif 2326 00000087 B8004C mov ax, 4C00h 2327 0000008A CD21 int 21h 2328 2329 @@: 2330 lvar word, upperbound 2331 0000008C 52 push dx 2332 lvar word, lowerbound 2333 0000008D 56 push si 2334 lvar word, current_init1 2335 0000008E 50 push ax 2336 2337 %if _TEST_PROGRESS 2338 0000008F BA[1C02] mov dx, init2_msg.progress.1 2339 00000092 B90700 mov cx, init2_msg.progress.1.length 2340 .loop: 2341 00000095 0E push cs 2342 00000096 1F pop ds 2343 00000097 BB0200 mov bx, 2 2344 0000009A B440 mov ah, 40h 2345 0000009C CD21 int 21h 2346 %else 2347 .loop: 2348 %endif 2349 2350 0000009E 8B56FE mov dx, [bp + ?upperbound] 2351 2352 000000A1 F6460380 testopt [bp + ?whichtest], 8000h 2353 000000A5 7419 jz @F 2354 2355 000000A7 FF4E04 dec word [bp + ?repetitions] 2356 000000AA 751E jnz .test_b_skip_bound 2357 2358 %if _TEST_PROGRESS 2359 000000AC 0E push cs 2360 000000AD 1F pop ds 2361 000000AE BA[2502] mov dx, init2_msg.progress.linebreak 2362 000000B1 B90200 mov cx, init2_msg.progress.linebreak.length 2363 000000B4 BB0200 mov bx, 2 2364 000000B7 B440 mov ah, 40h 2365 000000B9 CD21 int 21h 2366 %endif 2367 %if _RELOAD_XMS 2368 call freexms 2369 %endif 2370 000000BB B8004C mov ax, 4C00h 2371 000000BE CD21 int 21h 2372 2373 2374 @@: 2375 000000C0 2B56FC sub dx, [bp + ?lowerbound] 2376 000000C3 746C jz .found 2377 000000C5 D1EA shr dx, 1 2378 ; Rounding down, so that we never retry upper bound. 2379 ; The upper bound is known to be working. 2380 000000C7 0356FC add dx, [bp + ?lowerbound] 2381 2382 .test_b_skip_bound: 2383 000000CA 52 push dx 2384 000000CB 81C2110F add dx, (payload_end - payload) >> 4 2385 000000CF 8B46FA mov ax, [bp + ?current_init1] 2386 000000D2 B95300 mov cx, (init1_end - init1_start) >> 4 2387 000000D5 E82502 call init2_movp 2388 000000D8 8956FA mov [bp + ?current_init1], dx 2389 000000DB 5A pop dx 2390 2391 %if _RELOAD_XMS 2392 mov ax, [bp + ?xmshandle] 2393 %if _RELOAD_FILE 2394 cmp ax, -1 2395 je .restore_no_xms 2396 %endif 2397 push si 2398 push cs 2399 pop ds 2400 mov si, init2_xmsm_from_save 2401 mov word [si + XMSM.srchdl], ax 2402 mov word [si + XMSM.dstadr + 2], dx 2403 mov ah, 0Bh 2404 call far [bp + ?xmsentry] 2405 cmp ax, 1 2406 jne init2_error_xms_free 2407 pop si 2408 %if _RELOAD_FILE 2409 jmp .restore_done 2410 %endif 2411 %endif 2412 %if _RELOAD_FILE 2413 .restore_no_xms: 2414 size_compressed equ (payload.end - payload) 2415 push dx 2416 mov ds, dx 2417 mov cx, ((- size_compressed) >> 16) & 0FFFFh 2418 mov dx, (- size_compressed) & 0FFFFh 2419 mov ax, 4202h 2420 mov bx, [bp + ?handle] 2421 int 21h 2422 jc init2_error_file 2423 mov dx, size_compressed >> 16 2424 mov ax, size_compressed & 0FFFFh 2425 @@: 2426 mov cx, 0FF00h 2427 test dx, dx 2428 jnz @F 2429 cmp ax, cx 2430 jae @F 2431 mov cx, ax 2432 @@: 2433 sub ax, cx 2434 sbb dx, 0 2435 push dx 2436 push ax 2437 xor dx, dx 2438 mov ah, 3Fh 2439 int 21h 2440 jc init2_error_file 2441 cmp ax, cx 2442 jne init2_error_file 2443 mov dx, ds 2444 add dx, 0FF0h 2445 mov ds, dx 2446 pop ax 2447 pop dx 2448 mov cx, ax 2449 or cx, dx 2450 jnz @BB 2451 pop dx 2452 .restore_done: 2453 %endif 2454 %ifn _RELOAD_XMS || _RELOAD_FILE 2455 000000DC 8CC8 mov ax, cs 2456 000000DE 053914 add ax, (init2_end - init2_start) >> 4 2457 ; => payload in saving area 2458 000000E1 B9110F mov cx, (payload_end - payload) >> 4 2459 000000E4 E81602 call init2_movp ; copy payload from payload saving area 2460 %endif 2461 ; dx => source 2462 000000E7 8B46FA mov ax, [bp + ?current_init1] 2463 000000EA BB0100 mov bx, 1 2464 000000ED 52 push dx 2465 000000EE 56 push si 2466 000000EF 0E push cs 2467 000000F0 E86700 call .transfer 2468 000000F3 5E pop si 2469 000000F4 5A pop dx 2470 ; Returns here after decompression. 2471 ; CY if error. 2472 000000F5 7312 jnc @F 2473 2474 000000F7 F6460380 testopt [bp + ?whichtest], 8000h 2475 000000FB 7511 jnz .test_b_fail 2476 2477 ; error: this attempt is one below the new lower bound 2478 000000FD 42 inc dx 2479 000000FE 8956FC mov word [bp + ?lowerbound], dx 2480 2481 %if _TEST_PROGRESS 2482 00000101 BA[2302] mov dx, init2_msg.progress.fail 2483 00000104 B90100 mov cx, init2_msg.progress.fail.length 2484 %endif 2485 00000107 EB8C jmp .loop 2486 2487 @@: 2488 %if _INCLUDE_UNCOMPRESSED 2489 00000109 E85400 call checkdecompressed 2490 0000010C 7417 je @F 2491 2492 %if _WRITE_WRONG_FILE 2493 call writefiles 2494 %endif 2495 2496 .test_b_fail: 2497 %if _TEST_PROGRESS 2498 0000010E 0E push cs 2499 0000010F 1F pop ds 2500 00000110 BA[2502] mov dx, init2_msg.progress.linebreak 2501 00000113 B90200 mov cx, init2_msg.progress.linebreak.length 2502 00000116 BB0200 mov bx, 2 2503 00000119 B440 mov ah, 40h 2504 0000011B CD21 int 21h 2505 %endif 2506 %if _DEBUG0 2507 mov bx, -2 2508 %endif 2509 0000011D BA[9F02] mov dx, init2_msg.subsequent_error_2 2510 00000120 B93700 mov cx, init2_msg.subsequent_error_2.length 2511 00000123 EB74 jmp init2_error_free 2512 2513 @@: 2514 %endif 2515 ; success: this attempt is the new upper bound 2516 00000125 8956FE mov word [bp + ?upperbound], dx 2517 %if _TEST_PROGRESS 2518 00000128 BA[2402] mov dx, init2_msg.progress.success 2519 0000012B B90100 mov cx, init2_msg.progress.success.length 2520 %endif 2521 0000012E E964FF jmp .loop 2522 2523 .found: 2524 %if _TEST_PROGRESS 2525 00000131 0E push cs 2526 00000132 1F pop ds 2527 00000133 BA[2502] mov dx, init2_msg.progress.linebreak 2528 00000136 B90200 mov cx, init2_msg.progress.linebreak.length 2529 00000139 BB0200 mov bx, 2 2530 0000013C B440 mov ah, 40h 2531 0000013E CD21 int 21h 2532 %endif 2533 00000140 8B46FE mov ax, word [bp + ?upperbound] 2534 00000143 29F0 sub ax, si ; = how many paragraphs in buffer before source 2535 00000145 05640F add ax, paras( (init1_end - init1_start) + (payload_end - payload) ) 2537 ; = how many paragraphs needed for process 2538 00000148 E88800 call init2_disp_ax_dec 2539 0000014B B00D mov al, 13 2540 0000014D E87800 call init2_disp_al 2541 00000150 B00A mov al, 10 2542 00000152 E87300 call init2_disp_al 2543 %if _RELOAD_XMS 2544 call freexms 2545 %endif 2546 00000155 B8004C mov ax, 4C00h 2547 00000158 CD21 int 21h 2548 2549 2550 .transfer: 2551 0000015A 31FF xor di, di 2552 0000015C 57 push di ; placeholder ax value on stack 2553 0000015D 50 push ax ; INIT1 segment 2554 0000015E 57 push di ; zero = init1_start 2555 0000015F CB retf ; transfer to INIT1:init1_start 2556 2557 2558 2559 %if _INCLUDE_UNCOMPRESSED 2560 2561 2562 %if _WRITE_WRONG_FILE 2563 ; INP: si => decompressed image 2564 ; payload_uncompressed_size = size 2565 ; ! _INCLUDE_UNCOMPRESSED_IN_IMAGE: 2566 ; word [bp + ?handle] = file handle 2567 ; [bp + ?buffer] = ?buffersize buffer 2568 ; OUT: WRONG.BIN contains what we decompressed 2569 ; WRONG2.BIN contains expected payload 2570 ; CHG: ds, si, ax, bx, cx, dx 2571 ; STT: UP 2572 writefiles: 2573 push cs 2574 pop ds 2575 mov dx, init2_msg.wrong_file_name 2576 xor cx, cx 2577 mov ah, 3Ch 2578 int 21h 2579 jc .notfile 2580 2581 mov bx, ax 2582 mov cx, payload_uncompressed_size >> 4 2583 xor dx, dx 2584 .loopfile: 2585 mov ds, si 2586 mov ah, 40h 2587 push cx 2588 mov cx, 16 2589 int 21h 2590 pop cx 2591 inc si 2592 loop .loopfile 2593 2594 mov ds, si 2595 mov cx, payload_uncompressed_size & 15 2596 mov ah, 40h 2597 int 21h 2598 2599 mov ah, 3Eh 2600 int 21h 2601 2602 .notfile: 2603 2604 push cs 2605 pop ds 2606 mov dx, init2_msg.wrong_file_name2 2607 xor cx, cx 2608 mov ah, 3Ch 2609 int 21h 2610 jc .notfile2 2611 2612 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2613 mov bx, ax 2614 mov cx, payload_uncompressed_size >> 4 2615 mov si, cs 2616 add si, (payload_uncompressed - init2_start) >> 4 2617 xor dx, dx 2618 .loopfile2: 2619 mov ds, si 2620 mov ah, 40h 2621 push cx 2622 mov cx, 16 2623 int 21h 2624 pop cx 2625 inc si 2626 loop .loopfile2 2627 2628 mov ds, si 2629 mov cx, payload_uncompressed_size & 15 2630 mov ah, 40h 2631 int 21h 2632 2633 mov ah, 3Eh 2634 int 21h 2635 %else 2636 xchg si, ax 2637 2638 %if _RELOAD_FILE 2639 mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh 2640 mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh 2641 %else 2642 mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh 2643 mov dx, (- payload_uncompressed_size) & 0FFFFh 2644 %endif 2645 mov ax, 4202h 2646 mov bx, [bp + ?handle] 2647 int 21h 2648 jc .closefile2 2649 2650 push ss 2651 pop ds 2652 lea dx, [bp + ?buffer] 2653 2654 %if payload_uncompressed_size == 0 2655 %error Empty payload not allowed 2656 %endif 2657 %if (payload_uncompressed_size / ?buffersize) != 0 2658 mov cx, payload_uncompressed_size / ?buffersize 2659 %if ?buffersize == 0 || (?buffersize & 15) != 0 2660 %error Unexpected layout 2661 %endif 2662 .loop: 2663 push cx 2664 mov cx, ?buffersize 2665 call transferchunk 2666 pop cx 2667 jc .closefile2 2668 loop .loop 2669 %endif 2670 %if (payload_uncompressed_size % ?buffersize) != 0 2671 mov cx, payload_uncompressed_size % ?buffersize 2672 call transferchunk 2673 %endif 2674 2675 .closefile2: 2676 mov bx, si 2677 mov ah, 3Eh 2678 int 21h 2679 %endif 2680 2681 .notfile2: 2682 retn 2683 2684 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2685 ; INP: ds:dx -> buffer 2686 ; cx = size to transfer, must fit in buffer 2687 ; ?handle = source file handle 2688 ; si = destination file handle 2689 ; OUT: NC if success 2690 ; CY if error 2691 ; CHG: ax, bx 2692 ; STT: UP 2693 transferchunk: 2694 mov bx, word [bp + ?handle] 2695 mov ah, 3Fh 2696 int 21h 2697 jc .ret 2698 cmp ax, cx 2699 stc 2700 jne .ret ; if partial read --> (CY) 2701 mov bx, si 2702 mov ah, 40h 2703 int 21h 2704 jc .ret 2705 cmp ax, cx 2706 je .ret ; if not partial write --> (NC) 2707 stc 2708 .ret: 2709 retn 2710 %endif 2711 2712 %endif 2713 2714 2715 ; INP: si => decompressed image 2716 ; payload_uncompressed_size = size 2717 ; ! _INCLUDE_UNCOMPRESSED_IN_IMAGE: 2718 ; word [bp + ?handle] = file handle 2719 ; [bp + ?buffer] = ?buffersize buffer 2720 ; OUT: ZR if matching 2721 ; NZ if mismatching 2722 ; CHG: es, ds, di, bx, cx 2723 ; STT: UP 2724 checkdecompressed: 2725 00000160 50 push ax 2726 00000161 52 push dx 2727 00000162 56 push si 2728 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2729 %if _PAYLOAD_KERNEL_MAX_PARAS 2730 mov cx, _PAYLOAD_KERNEL_MAX_PARAS 2731 mov bx, 0 2732 %else 2733 00000163 B9FF13 mov cx, payload_uncompressed_size >> 4 2734 00000166 BB0A00 mov bx, payload_uncompressed_size & 15 2735 %endif 2736 00000169 8CCF mov di, cs 2737 0000016B 83C739 add di, (payload_uncompressed - init2_start) >> 4 2738 0000016E E319 jcxz .end 2739 .loop: 2740 00000170 51 push cx 2741 00000171 B90800 mov cx, 8 2742 00000174 8EDE mov ds, si 2743 00000176 8EC7 mov es, di 2744 00000178 46 inc si 2745 00000179 47 inc di 2746 0000017A 56 push si 2747 0000017B 57 push di 2748 0000017C 31F6 xor si, si 2749 0000017E 31FF xor di, di 2750 00000180 F3A7 repe cmpsw 2751 00000182 5F pop di 2752 00000183 5E pop si 2753 00000184 59 pop cx 2754 00000185 750E jne .ret 2755 00000187 E2E7 loop .loop 2756 .end: 2757 00000189 8EDE mov ds, si 2758 0000018B 8EC7 mov es, di 2759 0000018D 31F6 xor si, si 2760 0000018F 31FF xor di, di ; (ZR) 2761 00000191 89D9 mov cx, bx 2762 00000193 F3A6 repe cmpsb 2763 %else 2764 %if _RELOAD_FILE 2765 size_compressed_plus_uncompressed equ payload_uncompressed_size + (payload.end - payload) 2767 mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh 2768 mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh 2769 %else 2770 mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh 2771 mov dx, (- payload_uncompressed_size) & 0FFFFh 2772 %endif 2773 mov ax, 4202h 2774 mov bx, [bp + ?handle] 2775 int 21h 2776 jc .error 2777 %if payload_uncompressed_size == 0 2778 %error Empty payload not allowed 2779 %endif 2780 %if (payload_uncompressed_size / ?buffersize) != 0 2781 mov cx, payload_uncompressed_size / ?buffersize 2782 %if ?buffersize == 0 || (?buffersize & 15) != 0 2783 %error Unexpected layout 2784 %endif 2785 .loop: 2786 push cx 2787 mov cx, ?buffersize 2788 call comparechunk 2789 pop cx 2790 jne .ret 2791 loop .loop 2792 %endif 2793 %if (payload_uncompressed_size % ?buffersize) != 0 2794 mov cx, payload_uncompressed_size % ?buffersize 2795 call comparechunk 2796 %endif 2797 %endif 2798 .ret: 2799 00000195 5E pop si 2800 00000196 5A pop dx 2801 00000197 58 pop ax 2802 00000198 C3 retn 2803 2804 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2805 .error: 2806 or al, 1 ; NZ 2807 jmp .ret 2808 %endif 2809 %endif 2810 2811 2812 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2813 ; INP: ?buffer -> ?buffersize buffer 2814 ; cx = amount of bytes, 0 < cx <= ?buffersize 2815 ; si => chunk 2816 ; ?handle = handle 2817 ; seek -> chunk 2818 ; OUT: NZ if mismatch or error 2819 ; ZR else, 2820 ; si => next chunk (assumes full chunk) 2821 ; CHG: ds, es, di, ax, bx, cx, dx 2822 ; STT: UP 2823 comparechunk: 2824 push ss 2825 pop ds 2826 lea dx, [bp + ?buffer] 2827 mov bx, [bp + ?handle] 2828 mov ah, 3Fh 2829 int 21h 2830 jc .error 2831 cmp ax, cx 2832 jne .error 2833 mov es, si 2834 add si, ?buffersize / 16 2835 push si 2836 xor di, di 2837 mov si, dx 2838 repe cmpsb 2839 pop si 2840 .ret: 2841 retn 2842 2843 .error: 2844 or al, 1 ; NZ 2845 retn 2846 %endif 2847 2848 %if _RELOAD_XMS 2849 freexms: 2850 push ax 2851 push bx 2852 push dx 2853 mov dx, -1 2854 xchg dx, [bp + ?xmshandle] 2855 %if _RELOAD_FILE 2856 cmp dx, -1 2857 je @F 2858 %endif 2859 mov ah, 0Ah 2860 call far [bp + ?xmsentry] 2861 @@: 2862 pop dx 2863 pop bx 2864 pop ax 2865 retn 2866 2867 init2_error_xms_free: 2868 call freexms 2869 init2_error_xms: 2870 mov dx, init2_msg.xms_error 2871 mov cx, init2_msg.xms_error.length 2872 jmp init2_error 2873 %endif 2874 2875 %if _RELOAD_FILE 2876 init2_error_file: 2877 mov dx, init2_msg.file_error 2878 mov cx, init2_msg.file_error.length 2879 %endif 2880 2881 init2_error_free: 2882 %if _RELOAD_XMS 2883 call freexms 2884 %endif 2885 init2_error: 2886 %if _DEBUG0 2887 push bx 2888 %endif 2889 00000199 0E push cs 2890 0000019A 1F pop ds 2891 0000019B BB0200 mov bx, 2 2892 0000019E B440 mov ah, 40h 2893 000001A0 CD21 int 21h 2894 2895 %if _DEBUG0 2896 mov dx, init2_msg.rc 2897 mov cx, init2_msg.rc.length 2898 mov bx, 2 2899 mov ah, 40h 2900 int 21h 2901 pop ax 2902 call init2_error_disp_ax_hex 2903 mov dx, init2_msg.linebreak 2904 mov cx, init2_msg.linebreak.length 2905 mov bx, 2 2906 mov ah, 40h 2907 int 21h 2908 %endif 2909 2910 000001A2 F6460340 testopt [bp + ?whichtest], 4000h 2911 000001A6 7408 jz @F 2912 000001A8 BA[FA02] mov dx, init2_msg.error_c_stdout 2913 000001AB B90300 mov cx, init2_msg.error_c_stdout.length 2914 000001AE EB0C jmp @FF 2915 @@: 2916 000001B0 F6460380 testopt [bp + ?whichtest], 8000h 2917 000001B4 750D jnz @FF 2918 000001B6 BA[FA02] mov dx, init2_msg.error_stdout 2919 000001B9 B90300 mov cx, init2_msg.error_stdout.length 2920 @@: 2921 000001BC BB0100 mov bx, 1 2922 000001BF B440 mov ah, 40h 2923 000001C1 CD21 int 21h 2924 @@: 2925 000001C3 B8FF4C mov ax, 4CFFh 2926 000001C6 CD21 int 21h 2927 2928 lleave ctx 2929 2930 2931 %if _DEBUG0 2932 init2_error_disp_ax_hex: ; ax 2933 xchg al,ah 2934 call init2_error_disp_al_hex ; display former ah 2935 xchg al,ah ; and fall trough for al 2936 init2_error_disp_al_hex: ; al 2937 push cx 2938 mov cl,4 2939 ror al,cl 2940 call init2_error_disp_al_lownibble_hex 2941 ; display former high-nibble 2942 rol al,cl 2943 pop cx 2944 ; and fall trough for low-nibble 2945 init2_error_disp_al_lownibble_hex: 2946 push ax ; save ax for call return 2947 and al,00001111b ; high nibble must be zero 2948 add al,'0' ; if number is 0-9, now it's the correct character 2949 cmp al,'9' 2950 jna .decimalnum ; if we get decimal number with this, ok --> 2951 add al,7 ; otherwise, add 7 and we are inside our alphabet 2952 .decimalnum: 2953 call init2_error_disp_al 2954 pop ax 2955 retn 2956 2957 2958 init2_error_disp_al: 2959 push dx 2960 push cx 2961 push bx 2962 push ax 2963 mov dx, sp 2964 push ds 2965 push ss 2966 pop ds 2967 mov cx, 1 2968 mov bx, 2 2969 mov ah, 40h 2970 int 21h 2971 pop ds 2972 pop ax 2973 pop bx 2974 pop cx 2975 pop dx 2976 retn 2977 %endif 2978 2979 2980 init2_disp_al: 2981 000001C8 52 push dx 2982 000001C9 50 push ax 2983 000001CA 88C2 mov dl, al 2984 000001CC B402 mov ah, 2 2985 000001CE CD21 int 21h 2986 000001D0 58 pop ax 2987 000001D1 5A pop dx 2988 000001D2 C3 retn 2989 2990 2991 ; Display number in ax decimal 2992 ; 2993 ; INP: ax = number 2994 ; OUT: displayed using Int21.02 2995 ; CHG: none 2996 init2_disp_ax_dec: ; ax (no leading zeros) 2997 000001D3 53 push bx 2998 000001D4 31DB xor bx, bx 2999 .pushax: 3000 000001D6 52 push dx 3001 000001D7 50 push ax 3002 000001D8 08DB or bl, bl 3003 000001DA 7405 jz .nobl 3004 000001DC 80EB05 sub bl, 5 3005 000001DF F6DB neg bl 3006 .nobl: 3007 000001E1 51 push cx 3008 000001E2 B91027 mov cx, 10000 3009 000001E5 E81B00 call .divide_out 3010 000001E8 B9E803 mov cx, 1000 3011 000001EB E81500 call .divide_out 3012 000001EE B96400 mov cx, 100 3013 000001F1 E80F00 call .divide_out 3014 000001F4 B10A mov cl, 10 3015 000001F6 E80A00 call .divide_out 3016 ; (Divisor 1 is useless) 3017 000001F9 0430 add al, '0' 3018 000001FB E8CAFF call init2_disp_al 3019 000001FE 59 pop cx 3020 000001FF 58 pop ax 3021 00000200 5A pop dx 3022 00000201 5B pop bx ; Caller's register 3023 00000202 C3 retn 3024 3025 3026 ; INP: ax = number 3027 ; cx = divisor 3028 ; OUT: ax = remainder of operation 3029 ; result displayed 3030 .divide_out: 3031 00000203 52 push dx 3032 00000204 31D2 xor dx, dx 3033 00000206 F7F1 div cx ; 0:ax / cx 3034 00000208 52 push dx ; remainder 3035 00000209 FECB dec bl 3036 0000020B 7503 jnz .nobl2 3037 0000020D 80CF01 or bh, 1 3038 .nobl2: 3039 00000210 08C7 or bh, al 3040 00000212 7405 jz .leadingzero 3041 00000214 0430 add al, '0' 3042 00000216 E8AFFF call init2_disp_al ; display result 3043 .leadingzero: 3044 00000219 58 pop ax ; remainder 3045 0000021A 5A pop dx 3046 0000021B C3 retn 3047 3048 3049 init2_msg: 3050 %if _TEST_PROGRESS 3051 0000021C 496E666F3A2031 .progress.1: db "Info: 1" 3052 .progress.1.length: equ $ - .progress.1 3053 00000223 46 .progress.fail: db "F" 3054 .progress.fail.length: equ $ - .progress.fail 3055 00000224 53 .progress.success: db "S" 3056 .progress.success.length: equ $ - .progress.success 3057 00000225 0D0A .progress.linebreak: db 13,10 3058 .progress.linebreak.length: equ $ - .progress.linebreak 3059 %endif 3060 %if _WRITE_WRONG_FILE 3061 .wrong_file_name: asciz "WRONG.BIN" 3062 .wrong_file_name2: asciz "WRONG2.BIN" 3063 %endif 3064 00000227 4572726F723A205465- .initial_error: db "Error: Test program failed to decompress with full buffer." 3064 00000230 73742070726F677261- 3064 00000239 6D206661696C656420- 3064 00000242 746F206465636F6D70- 3064 0000024B 726573732077697468- 3064 00000254 2066756C6C20627566- 3064 0000025D 6665722E 3065 00000261 0D0A .linebreak: db 13,10 3066 .initial_error.length: equ $ - .initial_error 3067 .linebreak.length: equ $ - .linebreak 3068 %if _DEBUG0 3069 .rc: db "Error: Failure code=" 3070 .rc.length: equ $ - .rc 3071 %endif 3072 %if _INCLUDE_UNCOMPRESSED 3073 00000263 4572726F723A205465- .initial_error_2: db "Error: Test program decompressed wrongly with full buffer.",13,10 3073 0000026C 73742070726F677261- 3073 00000275 6D206465636F6D7072- 3073 0000027E 65737365642077726F- 3073 00000287 6E676C792077697468- 3073 00000290 2066756C6C20627566- 3073 00000299 6665722E0D0A 3074 .initial_error_2.length: equ $ - .initial_error_2 3075 0000029F 4572726F723A205465- .subsequent_error_2: db "Error: Test program decompressed wrongly during test.",13,10 3075 000002A8 73742070726F677261- 3075 000002B1 6D206465636F6D7072- 3075 000002BA 65737365642077726F- 3075 000002C3 6E676C792064757269- 3075 000002CC 6E6720746573742E0D- 3075 000002D5 0A 3076 .subsequent_error_2.length: equ $ - .subsequent_error_2 3077 %endif 3078 000002D6 4572726F723A20496E- .cmdline_error: db "Error: Invalid command line input.",13,10 3078 000002DF 76616C696420636F6D- 3078 000002E8 6D616E64206C696E65- 3078 000002F1 20696E7075742E0D0A 3079 .cmdline_error.length: equ $ - .cmdline_error 3080 %if _RELOAD_XMS 3081 .xms_error: db "Error: XMS failure.",13,10 3082 .xms_error.length: equ $ - .xms_error 3083 %endif 3084 %if _RELOAD_FILE 3085 .file_error: db "Error: File read failure.",13,10 3086 .file_error.length: equ $ - .file_error 3087 %endif 3088 3089 .error_c_stdout: 3090 000002FA 30 .error_stdout: db "0" 3091 %if 0 3092 _autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE + (payload_end - payload) + (init1_end - init1_start) + ADDITIONAL_MEMORY ) 3097 %endif 3098 000002FB 0D0A db 13,10 3099 .error_c_stdout.length: equ $ - .error_c_stdout 3100 .error_stdout.length: equ $ - .error_stdout 3101 3102 3103 ; Move paragraphs 3104 ; 3105 ; INP: ax => source 3106 ; dx => destination 3107 ; cx = number of paragraphs 3108 ; CHG: - 3109 ; OUT: ax and dx unchanged 3110 ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 3111 ; Do not provide a wrapped/HMA source or destination! 3112 init2_movp: 3113 000002FD 51 push cx 3114 000002FE 1E push ds 3115 000002FF 56 push si 3116 00000300 06 push es 3117 00000301 57 push di 3118 3119 00000302 39D0 cmp ax, dx ; source above destination ? 3120 00000304 770A ja .up ; yes, move up (forwards) --> 3121 00000306 747B je .return ; same, no need to move --> 3122 00000308 50 push ax 3123 00000309 01C8 add ax, cx ; (expected not to carry) 3124 0000030B 39D0 cmp ax, dx ; end of source is above destination ? 3125 0000030D 58 pop ax 3126 0000030E 7730 ja .down ; yes, move from top down --> 3127 ; Here, the end of source is below-or-equal the destination, 3128 ; so they do not overlap. In this case we prefer moving up. 3129 3130 .up: 3131 00000310 50 push ax 3132 00000311 52 push dx 3133 .uploop: 3134 00000312 8ED8 mov ds, ax 3135 00000314 8EC2 mov es, dx 3136 00000316 31FF xor di, di 3137 00000318 31F6 xor si, si ; -> start of segment 3138 0000031A 81E90010 sub cx, 1000h ; 64 KiB left ? 3139 0000031E 7610 jbe .uplast ; no --> 3140 00000320 51 push cx 3141 00000321 B90080 mov cx, 10000h /2 3142 00000324 F3A5 rep movsw ; move 64 KiB 3143 00000326 59 pop cx 3144 00000327 050010 add ax, 1000h 3145 0000032A 81C20010 add dx, 1000h ; -> next segment 3146 0000032E EBE2 jmp short .uploop ; proceed for more --> 3147 .uplast: 3148 00000330 81C10010 add cx, 1000h ; restore counter 3149 00000334 D1E1 shl cx, 1 3150 00000336 D1E1 shl cx, 1 3151 00000338 D1E1 shl cx, 1 ; *8, paragraphs to words 3152 0000033A F3A5 rep movsw ; move last part 3153 0000033C 5A pop dx 3154 0000033D 58 pop ax 3155 0000033E EB43 jmp short .return 3156 3157 .down: 3158 00000340 FD std ; _AMD_ERRATUM_109_WORKAROUND as below 3159 .dnloop: 3160 00000341 81E90010 sub cx, 1000h ; 64 KiB left ? 3161 00000345 761A jbe .dnlast ; no --> 3162 00000347 50 push ax 3163 00000348 52 push dx 3164 00000349 01C8 add ax, cx 3165 0000034B 01CA add dx, cx 3166 0000034D 8ED8 mov ds, ax ; -> 64 KiB not yet moved 3167 0000034F 8EC2 mov es, dx 3168 00000351 5A pop dx 3169 00000352 58 pop ax 3170 00000353 BFFEFF mov di, -2 3171 00000356 89FE mov si, di ; moved from last word down 3172 00000358 51 push cx 3173 00000359 B90080 mov cx, 10000h /2 3174 0000035C F3A5 rep movsw ; move 64 KiB 3175 0000035E 59 pop cx 3176 0000035F EBE0 jmp short .dnloop ; proceed for more --> 3177 .dnlast: 3178 00000361 81C10010 add cx, 1000h ; restore counter 3179 00000365 D1E1 shl cx, 1 3180 00000367 D1E1 shl cx, 1 3181 00000369 D1E1 shl cx, 1 ; *8, paragraphs to words 3182 0000036B 89CF mov di, cx 3183 0000036D 4F dec di 3184 0000036E D1E7 shl di, 1 ; words to offset, -> last word 3185 00000370 89FE mov si, di 3186 00000372 8ED8 mov ds, ax 3187 00000374 8EC2 mov es, dx ; first segment correct 3188 3189 ; Refer to comment in init0_movp. 3190 %if _AMD_ERRATUM_109_WORKAROUND 3191 00000376 E308 jcxz @FF 3192 00000378 83F914 cmp cx, 20 3193 0000037B 7703 ja @FF 3194 @@: 3195 0000037D A5 movsw 3196 0000037E E2FD loop @B 3197 @@: 3198 %endif 3199 00000380 F3A5 rep movsw ; move first part 3200 00000382 FC cld 3201 .return: 3202 00000383 5F pop di 3203 00000384 07 pop es 3204 00000385 5E pop si 3205 00000386 1F pop ds 3206 00000387 59 pop cx 3207 00000388 C3 retn 3208 3209 3210 00000389 90 align 4 3211 %if _RELOAD_XMS 3212 init2_xmsm_from_save: 3213 istruc XMSM 3214 at XMSM.size_, dd payload_end - payload 3215 iend 3216 init2_xmsm_to_save: 3217 istruc XMSM 3218 at XMSM.size_, dd payload_end - payload 3219 iend 3220 %endif 3221 3222 0000038C 90 align 16 3223 3224 %if _INCLUDE_UNCOMPRESSED && _INCLUDE_UNCOMPRESSED_IN_IMAGE 3225 strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN" 3226 payload_uncompressed: 3227 00000390 incbin _UNCOMPRESSED_FILE 3228 .end: 3229 0001438A 26 db 38 3230 0001438B 26 align 16, db 38 3231 %endif 3232 init2_end: 3233 %endif 3234