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 nop 230 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 int3 239 sti 240 hlt 241 jmp @B 242 %endif 243 %if _BOOTLDR 244 %if ! _IMAGE_EXE 245 j_zero_entrypoint: 246 %endif 247 xor bx, bx ; 0 = kernel mode 248 push ax 249 mov ax, cs 250 add ax, (init0_end - init0_start) >> 4 251 mov dx, word [ bp + ldLoadTop ] ; => after end of available space 252 mov si, 60h ; => destination 253 jmp init0_common 254 %endif 255 256 %if _IMAGE_EXE 257 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 mov bx, 1 ; EXE mode 276 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 mov si, 81h 310 xor dx, dx 311 xor ax, ax 312 cmdline: 313 .: 314 lodsb 315 cmp al, 9 316 je . 317 cmp al, 32 318 je . 319 cmp al, 13 320 je .end 321 cmp al, '0' 322 jb .notdigit 323 cmp al, '9' 324 ja .notdigit 325 .digit: 326 sub al, '0' 327 mov cx, dx ; times 1 328 add dx, dx 329 jc .invalid 330 add dx, dx ; times 4 331 jc .invalid 332 add dx, cx ; times 5 333 jc .invalid 334 add dx, dx ; times 10 335 jc .invalid 336 add dx, ax ; add in low digit 337 jc .invalid 338 jmp . 339 340 .notdigit: 341 cmp al, 'A' 342 je .a 343 cmp al, 'a' 344 je .a 345 cmp al, 'B' 346 je .b 347 cmp al, 'b' 348 je .b 349 cmp al, 'C' 350 je .c 351 cmp al, 'c' 352 je .c 353 .invalid: 354 mov dx, -1 ; invalid 355 jmp .end 356 357 .a: 358 and bh, ~ 80h ; A mode. determine min alloc size 359 jmp . 360 361 .b: 362 or bh, 80h ; B mode. repeat depack, counter in command line 363 jmp . 364 365 .c: 366 or bh, 40h ; C mode. how often would the counter be called 367 jmp . 368 369 .end: 370 ; bx for ?whichtest 371 push dx ; for ?repetitions 372 %endif 373 mov dx, ss ; => after end of available space 374 mov ax, cs 375 add ax, (256 + (init0_end - init0_start)) >> 4 ; => source 376 mov si, cs 377 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 cld 394 %if _TEST_PROGRAM 395 %ifn _RELOAD_XMS || _RELOAD_FILE 396 sub dx, ( (payload_end - payload) ) >> 4 397 jc .error 398 %endif 399 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) + (init2_end - init2_start) ) >> 4 405 sub dx, cx 406 jc .error 407 cmp dx, ax 408 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 push si ; preserve destination 420 call init0_movp ; move up payload + INIT1 421 pop si 422 %else 423 00000000 FC cld 424 00000001 8CC8 mov ax, cs 425 00000003 83C00E add ax, (init0_end - init0_start) >> 4 426 00000006 B9BF0C mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 431 00000009 8B56E2 mov dx, word [ bp + ldLoadTop ] 432 0000000C 29CA sub dx, cx 433 0000000E E83F00 call init0_movp 434 %endif 435 436 %if _LCFG && ! _TEST_PROGRAM 437 00000011 0E push cs 438 00000012 E80000 call @F ; position-independent far pointer 439 @@: 440 00000015 58 pop ax 441 00000016 83C01B add ax, lcfg - @B ; -> lCFG block 442 00000019 50 push ax 443 %endif 444 445 0000001A 89D0 mov ax, dx ; => INIT0B 446 ; (same as => payload if INIT0B is empty) 447 %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM 448 0000001C 83C204 add dx, ( + (init0b_end - init0b_start) ) >> 4 ; => payload 451 %else 452 %if _TEST_PROGRAM 453 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 0000001F 31C9 xor cx, cx 466 00000021 50 push ax 467 00000022 51 push cx 468 00000023 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 mov di, bx ; whichtest 477 478 push cs 479 pop ds 480 mov dx, init0_msg.error_stderr + 256 481 mov cx, init0_msg.error_stderr.length 482 mov bx, 2 483 mov ah, 40h 484 int 21h 485 486 test di, 4000h ; whichtest 487 jz @F 488 mov dx, init0_msg.error_c_stdout + 256 489 mov cx, init0_msg.error_c_stdout.length 490 jmp @FF 491 @@: 492 test di, di ; whichtest 493 js @FF 494 mov dx, init0_msg.error_stdout + 256 495 mov cx, init0_msg.error_stdout.length 496 @@: 497 mov bx, 1 498 mov ah, 40h 499 int 21h 500 @@: 501 mov ax, 4CFFh 502 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 00000024 90 align 16 542 lcfg: 543 00000030 EB1E .: jmp strict short .end 544 00000032 6C434647 lcfgoption 2,, db "lCFG" 545 00000036 3030 lcfgoption 6,, db "00" 546 00000038 FCFF040000000000 lcfgoption 8,, dq .inuse 547 %if _PROGRESS && _PROGRESSMULTI 548 %if _IMAGE_EXE 549 lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP 550 %endif 551 %if _DEVICE 552 lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE 553 %endif 554 %if _BOOTLDR 555 00000040 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 00000043 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 00000050 39D0 cmp ax, dx ; source above destination ? 683 00000052 770A ja .up ; yes, move up (forwards) --> 684 00000054 747B je .return ; same, no need to move --> 685 00000056 50 push ax 686 00000057 01C8 add ax, cx ; (expected not to carry) 687 00000059 39D0 cmp ax, dx ; end of source is above destination ? 688 0000005B 58 pop ax 689 0000005C 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 0000005E 50 push ax 695 0000005F 52 push dx 696 .uploop: 697 00000060 8ED8 mov ds, ax 698 00000062 8EC2 mov es, dx 699 00000064 31FF xor di, di 700 00000066 31F6 xor si, si ; -> start of segment 701 00000068 81E90010 sub cx, 1000h ; 64 KiB left ? 702 0000006C 7610 jbe .uplast ; no --> 703 0000006E 51 push cx 704 0000006F B90080 mov cx, 10000h /2 705 00000072 F3A5 rep movsw ; move 64 KiB 706 00000074 59 pop cx 707 00000075 050010 add ax, 1000h 708 00000078 81C20010 add dx, 1000h ; -> next segment 709 0000007C EBE2 jmp short .uploop ; proceed for more --> 710 .uplast: 711 0000007E 81C10010 add cx, 1000h ; restore counter 712 00000082 D1E1 shl cx, 1 713 00000084 D1E1 shl cx, 1 714 00000086 D1E1 shl cx, 1 ; *8, paragraphs to words 715 00000088 F3A5 rep movsw ; move last part 716 0000008A 5A pop dx 717 0000008B 58 pop ax 718 0000008C EB43 jmp short .return 719 720 .down: 721 0000008E FD std ; _AMD_ERRATUM_109_WORKAROUND as below 722 .dnloop: 723 0000008F 81E90010 sub cx, 1000h ; 64 KiB left ? 724 00000093 761A jbe .dnlast ; no --> 725 00000095 50 push ax 726 00000096 52 push dx 727 00000097 01C8 add ax, cx 728 00000099 01CA add dx, cx 729 0000009B 8ED8 mov ds, ax ; -> 64 KiB not yet moved 730 0000009D 8EC2 mov es, dx 731 0000009F 5A pop dx 732 000000A0 58 pop ax 733 000000A1 BFFEFF mov di, -2 734 000000A4 89FE mov si, di ; moved from last word down 735 000000A6 51 push cx 736 000000A7 B90080 mov cx, 10000h /2 737 000000AA F3A5 rep movsw ; move 64 KiB 738 000000AC 59 pop cx 739 000000AD EBE0 jmp short .dnloop ; proceed for more --> 740 .dnlast: 741 000000AF 81C10010 add cx, 1000h ; restore counter 742 000000B3 D1E1 shl cx, 1 743 000000B5 D1E1 shl cx, 1 744 000000B7 D1E1 shl cx, 1 ; *8, paragraphs to words 745 000000B9 89CF mov di, cx 746 000000BB 4F dec di 747 000000BC D1E7 shl di, 1 ; words to offset, -> last word 748 000000BE 89FE mov si, di 749 000000C0 8ED8 mov ds, ax 750 000000C2 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 000000C4 E308 jcxz @FF 791 000000C6 83F914 cmp cx, 20 792 000000C9 7703 ja @FF 793 @@: 794 000000CB A5 movsw 795 000000CC E2FD loop @B 796 @@: 797 %endif 798 000000CE F3A5 rep movsw ; move first part 799 000000D0 FC cld 800 .return: 801 000000D1 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 05130C 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 push si 850 push bx 851 %endif 852 %if _BOOTLDR 853 %if _LCFG 854 00000007 31C0 xor ax, ax 855 00000009 268A4512 mov al, byte [es:di + lcfg.progress_boot - lcfg] 856 0000000D 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 test bx, bx 865 jz .default 866 %endif ; _BOOTLDR 867 %if _LCFG 868 push es 869 %if _BOOTLDR 870 push ax ; -> lCFG block 871 %else ; _BOOTLDR 872 push di 873 %endif ; _BOOTLDR 874 %endif ; _LCFG 875 %if _PROGRESSVAR 876 mov ah, 51h 877 int 21h 878 @@: 879 mov ds, bx 880 mov ax, word [2Ch] 881 test ax, ax 882 jnz .gotenv 883 mov ax, word [16h] 884 inc ax 885 jz .default_nonboot 886 dec ax 887 jz .default_nonboot 888 cmp bx, ax 889 je .default_nonboot 890 xchg bx, ax 891 jmp @B 892 893 .gotenv: 894 push cs 895 pop ds ; => cs 896 mov es, ax ; => environment 897 %ifnidni _PROGRESSVARNAME, "" 898 mov bx, progressvarname1 899 call .findenv 900 jnc .foundenv ; match --> 901 mov bx, progressvarname2 902 %endif 903 call .findenv 904 jnc .foundenv ; match --> 905 jmp .default_nonboot 906 907 .findenv: 908 xor di, di 909 @@: 910 %ifnidni _PROGRESSVARNAME, "" 911 mov si, bx ; -> variable name 912 %else 913 mov si, progressvarname2 ; -> variable name 914 %endif 915 xor ax, ax 916 lodsb ; get length 917 xchg cx, ax ; cx = length 918 push di 919 repe cmpsb ; match ? 920 je .findret_pop ; (NC) yes --> 921 pop di 922 mov cx, 8000h ; maximum env size 923 sub cx, di ; any left ? 924 jbe .findret_CY ; no --> 925 mov al, 0 926 repne scasb ; find next NUL 927 jne .findret_CY 928 cmp byte [es:di], al ; double NUL ? 929 jne @B ; no, loop --> 930 .findret_CY: 931 stc ; not found 932 retn 933 934 .findret_pop: 935 pop cx 936 retn 937 938 .foundenv: 939 %if _LCFG 940 pop si 941 pop si ; discard far pointer to lCFG 942 %endif 943 mov si, di ; es:si -> var content 944 xor di, di ; = 0 945 xor ax, ax ; ah = 0 946 @@: 947 es lodsb ; next candidate digit 948 sub al, '0' ; digit ? 949 jb @F ; no --> 950 cmp al, 9 951 ja @F ; no --> 952 add di, di ; times 2 953 mov bx, di 954 add di, di ; times 4 955 add di, di ; times 8 956 add di, bx ; times 8 + times 2 = times 10 957 add di, ax ; add in next digit 958 jmp @B ; and loop 959 960 @@: 961 and di, 31 ; mask to low 5 bits 962 jmp @F 963 %endif ; _PROGRESSVAR 964 965 .default_nonboot: 966 %if _LCFG 967 pop di 968 pop es ; -> lCFG block 969 pop bx ; = 1 if app, = 2 if device 970 push bx 971 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 mov ah, 0 ; ax = default 983 xchg di, ax ; di = default 984 %else ; _LCFG 985 mov di, _PROGRESSDEFAULT 986 %endif ; _LCFG 987 @@: 988 test di, 16 989 jz @F 990 and di, ~16 991 jmp .outputdevice ; if 16 set skip device check 992 @@: 993 push dx 994 mov ax, 4400h ; IOCTL get device information 995 mov bx, 1 ; StdOut 996 mov dl, 83h ; default if 21.4400 fails 997 int 21h 998 test dl, 80h 999 pop dx 1000 jnz .outputdevice 1001 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 pop bx 1008 pop si 1009 %endif 1010 0000000E 83FF05 cmp di, step_progress_table.amount 1011 ; valid ? 1012 00000011 7202 jb @F ; yes --> 1013 00000013 31FF xor di, di ; disable 1014 @@: 1015 00000015 D1E7 shl di, 1 ; = word index 1016 00000017 59 pop cx ; = 0 1017 00000018 1F pop ds ; ds => INIT1 1018 1019 00000019 2E8B85[2E00] mov ax, word [cs:step_progress_table + di] 1020 ; ax = rel16 for step progress handler 1021 0000001E 1E push ds 1022 0000001F 51 push cx ; -> init1_start 1023 00000020 A3[4300] mov word [step_progress.handler], ax 1024 ; patch it 1025 1026 00000023 83FF04 cmp di, 2 * 2 ; none or dots ? 1027 00000026 7305 jae @F ; no, skip --> 1028 00000028 C606[0200]A9 mov byte [..@empty_step_progress], __TEST_IMM16 1029 ; for none and dots do not call here 1030 @@: 1031 %endif ; _PROGRESS && _PROGRESSMULTI 1032 0000002D CB retf 1033 %endif 1034 1035 %if _PROGRESS && _PROGRESSMULTI 1036 align 2, db 0 1037 step_progress_table: 1038 .: 1039 0000002E 1600 dw step_progress.0_step - step_progress.base 1040 00000030 3B00 dw step_progress.1_step - step_progress.base 1041 00000032 0000 dw step_progress.2_step - step_progress.base 1042 00000034 4100 dw step_progress.3_step - step_progress.base 1043 00000036 8600 dw step_progress.4_step - step_progress.base 1044 .amount equ ($ - .) / 2 1045 1046 %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE) 1047 %ifnidni _PROGRESSVARNAME, "" 1048 progressvarname1: counted _PROGRESSVARNAME, '=' 1049 %endif 1050 progressvarname2: counted "LDOSPROGRESS=" 1051 %endif 1052 %endif 1053 1054 00000038 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 0000C0EC 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 lenter 1105 lvar word, exemode ; must be bp - 2! 1106 push bx 1107 %if ?exemode != -2 1108 %error exemode variable must be directly below bp 1109 %endif 1110 push si 1111 %if _PROGRESS 1112 clc ; NC 1113 %endif 1114 %else 1115 00000000 31DB 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 times 3 nop 1123 %else 1124 00000002 E82C00 call step_progress.CF ; display empty / 0.0% 1125 %endif 1126 @@: 1127 %endif 1128 1129 %if _IMAGE_EXE || _DEVICE 1130 mov es, si ; es => destination 1131 %else 1132 00000005 B86000 mov ax, 60h 1133 00000008 8EC0 mov es, ax ; es => destination 1134 %endif 1135 0000000A 31FF xor di, di ; -> destination 1136 1137 0000000C 8EDA mov ds, dx 1138 0000000E 31F6 xor si, si ; -> source 1139 1140 00000010 B9ECC0 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 00000013 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 00000015 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 00000018 E8D203 call depack 1167 %ifn _TEST_PROGRAM 1168 0000001B 7205 jc strict short error ; -2 (replaced by retf \ nop) 1169 %endif 1170 %if _IMAGE_EXE || _DEVICE 1171 pop si ; si 1172 %if _TEST_PROGRAM 1173 pop ax ; (discard ?exemode, leave bx as returned) 1174 %else 1175 pop bx ; ?exemode 1176 %endif 1177 pop bp ; bp 1178 pop ax ; ax 1179 lleave ctx 1180 %endif 1181 %if _TEST_PROGRAM 1182 retf ; +1 (replace jc error) 1183 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 test bl, 1 1214 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 xor cx, cx 1243 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 mov cx, _IMAGE_EXE_IP 1251 %endif 1252 1253 %if _IMAGE_EXE_CS == -16 1254 add si, -16 1255 mov ds, si 1256 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 push si 1266 push cx 1267 %if _LCFG && _PASSLCFG 1268 mov di, transfer_lcfg_block 1269 mov cx, cs 1270 %endif 1271 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 0000001D EA00006000 jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET 1280 1281 1282 %if _TEST_PROGRAM 1283 disp_al_counter: 1284 inc word [cs:init1_c_mode_counter] ; 5 bytes 1285 retn ; 1 byte 1286 1287 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 00000022 0E push cs 1300 00000023 1F 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 00000024 BE[A201] mov si, msg.error 1313 %endif 1314 %endif 1315 %ifn _TEST_PROGRAM ; 3 bytes, total 2 + 3 + 3 = 8 1316 00000027 E85C01 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 test byte [bp - 2], 1 1361 jz .exit_kernel_mode 1362 %endif 1363 1364 mov ax, 4C7Fh 1365 int 21h 1366 1367 .exit_kernel_mode: 1368 %endif 1369 %if _BOOTLDR 1370 0000002A 31C0 xor ax, ax 1371 0000002C CD16 int 16h 1372 0000002E CD19 int 19h 1373 %endif 1374 1375 1376 %if _PROGRESS 1377 step_progress: 1378 00000030 F9 stc 1379 .CF: 1380 00000031 53 push bx 1381 00000032 51 push cx 1382 00000033 52 push dx 1383 00000034 1E push ds 1384 00000035 56 push si 1385 00000036 57 push di 1386 00000037 50 push ax 1387 1388 00000038 0E push cs 1389 00000039 1F pop ds 1390 1391 0000003A 8316[6C01]00 adc word [.counter], 0 1392 0000003F A1[6C01] 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 00000042 E93B00 jmp strict near . %+ defaultprogresshandler %+ _step 1401 .handler: equ $ - 2 ; SMC, patched to dispatch to handler 1402 .base: 1403 %endif 1404 1405 .2_step: 1406 00000045 BAE803 mov dx, 1000 1407 00000048 F7E2 mul dx ; dx:ax = counter times 1000 1408 %if _PROGRESSAMOUNT 1409 0000004A B9A400 mov cx, _PROGRESSAMOUNT 1410 0000004D 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 0000004F BE[7501] mov si, .message_number_end - 1 1422 00000052 E80E00 call .format_percentage 1423 1424 00000055 BE[6E01] mov si, .message 1425 00000058 E82B01 call disp_error 1426 1427 .ret: 1428 0000005B 58 pop ax 1429 .ret_ax: 1430 0000005C 5F pop di 1431 0000005D 5E pop si 1432 0000005E 1F pop ds 1433 0000005F 5A pop dx 1434 00000060 59 pop cx 1435 00000061 5B pop bx 1436 .retn: 1437 00000062 C3 retn 1438 1439 1440 .format_percentage: 1441 00000063 BB0200 mov bx, 2 ; skip dot 1442 1443 00000066 B90A00 mov cx, 10 ; base 1444 @@: 1445 00000069 31D2 xor dx, dx ; dx:ax = current number 1446 0000006B F7F1 div cx ; dl = remainder, ax = next number 1447 0000006D 80C230 add dl, '0' ; make decit 1448 00000070 8814 mov byte [si], dl ; store 1449 00000072 29DE sub si, bx ; -> next digit slot 1450 00000074 80FB02 cmp bl, 2 ; did we just store fractional ? 1451 00000077 B301 mov bl, 1 ; ! next iteration do not skip dot 1452 00000079 74EE je @B ; yes, loop always --> 1453 0000007B 85C0 test ax, ax ; nonzero left ? 1454 0000007D 75EA jnz @B ; yes, loop if so --> 1455 0000007F C3 retn 1456 1457 1458 %if _PROGRESSMULTI 1459 .0_step: equ .ret 1460 1461 .1_step: 1462 00000080 58 pop ax 1463 00000081 E81001 call disp_al 1464 00000084 EBD6 jmp .ret_ax 1465 1466 .3_step: 1467 00000086 BB4B00 mov bx, 80 - 1 - 4 1468 00000089 F7E3 mul bx ; dx:ax = counter times 75 1469 %if _PROGRESSAMOUNT 1470 0000008B B9A400 mov cx, _PROGRESSAMOUNT 1471 0000008E F7F1 div cx ; ax = 0..75 1472 %else 1473 %warning Progress amount is zero 1474 mov ax, 1 1475 %endif 1476 1477 00000090 3906[6A01] cmp word [.display], ax 1478 00000094 74C5 je .ret 1479 00000096 A3[6A01] mov word [.display], ax 1480 1481 00000099 50 push ax 1482 0000009A 91 xchg cx, ax 1483 0000009B B00D mov al, 13 1484 0000009D E8F400 call disp_al 1485 000000A0 B05B mov al, '[' 1486 000000A2 E8EF00 call disp_al 1487 000000A5 B020 mov al, 32 1488 000000A7 E8EA00 call disp_al 1489 1490 000000AA B023 mov al, '#' 1491 000000AC E305 jcxz @FF 1492 @@: 1493 000000AE E8E300 call disp_al 1494 000000B1 E2FB loop @B 1495 @@: 1496 1497 000000B3 B020 mov al, 32 1498 000000B5 59 pop cx 1499 000000B6 29CB sub bx, cx 1500 000000B8 7607 jbe @FF 1501 000000BA 89D9 mov cx, bx 1502 @@: 1503 000000BC E8D500 call disp_al 1504 000000BF E2FB loop @B 1505 @@: 1506 1507 .m4done: 1508 000000C1 E8D000 call disp_al 1509 000000C4 B05D mov al, ']' 1510 000000C6 E8CB00 call disp_al 1511 000000C9 EB90 jmp .ret 1512 1513 1514 .4_step: 1515 000000CB 50 push ax 1516 1517 000000CC BAE803 mov dx, 1000 1518 000000CF F7E2 mul dx ; dx:ax = counter times 1000 1519 %if _PROGRESSAMOUNT 1520 000000D1 B9A400 mov cx, _PROGRESSAMOUNT 1521 000000D4 F7F1 div cx ; ax = 0..1000 1522 %else 1523 %warning Progress amount is zero 1524 mov ax, 1 1525 %endif 1526 1527 000000D6 BE[7F01] mov si, .message_4_number_end - 1 1528 000000D9 E887FF call .format_percentage 1529 1530 000000DC 58 pop ax 1531 000000DD BB4B00 mov bx, 80 - 1 - 4 1532 000000E0 F7E3 mul bx ; dx:ax = counter times 75 1533 %if _PROGRESSAMOUNT 1534 000000E2 B9A400 mov cx, _PROGRESSAMOUNT 1535 000000E5 F7F1 div cx ; ax = 0..75 1536 %else 1537 %warning Progress amount is zero 1538 mov ax, 1 1539 %endif 1540 1541 000000E7 50 push ax 1542 000000E8 91 xchg cx, ax 1543 000000E9 B00D mov al, 13 1544 000000EB E8A600 call disp_al 1545 000000EE B05B mov al, '[' 1546 000000F0 E8A100 call disp_al 1547 000000F3 B020 mov al, 32 1548 000000F5 E89C00 call disp_al 1549 1550 000000F8 31FF xor di, di 1551 000000FA BA2200 mov dx, (80 - 1 - 4 - .message_4_length) / 2 1552 000000FD 803E[7B01]20 cmp byte [.message_4_number], 32 1553 00000102 7401 je @F 1554 00000104 47 inc di 1555 @@: 1556 00000105 29FA sub dx, di 1557 1558 00000107 B023 mov al, '#' 1559 00000109 E306 jcxz @FF 1560 @@: 1561 0000010B E88600 call disp_al 1562 0000010E 4A dec dx 1563 0000010F E0FA loopnz @B 1564 @@: 1565 1566 00000111 85D2 test dx, dx 1567 00000113 752E jnz .notyetm4 1568 1569 00000115 BE[7B01] mov si, .message_4 1570 00000118 29FE sub si, di 1571 0000011A E86900 call disp_error 1572 1573 0000011D 29F9 sub cx, di 1574 0000011F 760E jbe @FF 1575 00000121 83E907 sub cx, .message_4_length 1576 00000124 7609 jbe @FF 1577 00000126 89CA mov dx, cx 1578 00000128 B023 mov al, '#' 1579 @@: 1580 0000012A E86700 call disp_al 1581 0000012D E2FB loop @B 1582 @@: 1583 0000012F 59 pop cx 1584 00000130 B020 mov al, 32 1585 00000132 83EB29 sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length 1586 00000135 29D3 sub bx, dx 1587 00000137 7607 jbe @FF 1588 00000139 89D9 mov cx, bx 1589 @@: 1590 0000013B E85600 call disp_al 1591 0000013E E2FB loop @B 1592 @@: 1593 00000140 E97EFF jmp .m4done 1594 1595 .notyetm4: 1596 00000143 B020 mov al, 32 1597 00000145 59 pop cx 1598 00000146 29CB sub bx, cx 1599 00000148 7608 jbe @FF 1600 0000014A 89D9 mov cx, bx 1601 @@: 1602 0000014C E84500 call disp_al 1603 0000014F 4A dec dx 1604 00000150 E0FA loopnz @B 1605 @@: 1606 1607 00000152 BE[7B01] mov si, .message_4 1608 00000155 29FE sub si, di 1609 00000157 E82C00 call disp_error 1610 1611 0000015A B020 mov al, 32 1612 0000015C 29F9 sub cx, di 1613 0000015E 83E907 sub cx, .message_4_length 1614 ; jbe @FF 1615 @@: 1616 00000161 E83000 call disp_al 1617 00000164 E2FB loop @B 1618 @@: 1619 00000166 E958FF jmp .m4done 1620 %endif 1621 1622 00000169 00 align 2, db 0 1623 %if _PROGRESSMULTI 1624 0000016A FFFF .display: dw -1 1625 %endif 1626 0000016C 0000 .counter: dw 0 1627 0000016E 0D5B20 .message: db 13,"[ " 1628 00000171 2020312E30 .message_number:db " 1.0" ; enough digit slots for 100.0%, 1629 ; blanks are pre-init until written 1630 .message_number_end: 1631 00000176 25205D00 db "% ]",0 1632 %if _PROGRESSMULTI 1633 0000017A 20 db " " 1634 .message_4: 1635 0000017B 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 00000180 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 00000183 E80E00 call disp_al 1673 disp_error: 1674 00000186 AC lodsb 1675 00000187 84C0 test al, al 1676 00000189 75F8 jnz .loop 1677 0000018B 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 0000018C 2E833E[4300]16 cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base 1709 00000192 740D je disp_al.retn 1710 %endif 1711 disp_al: 1712 %if _TEST_PROGRAM 1713 retn 1714 %else 1715 00000194 50 push ax 1716 %endif 1717 %if _BOOTLDR 1718 00000195 53 push bx 1719 00000196 55 push bp 1720 00000197 B40E mov ah, 0Eh 1721 00000199 BB0700 mov bx, 7 1722 %endif 1723 %if _IMAGE_EXE || _DEVICE 1724 push dx 1725 1726 %if _BOOTLDR 1727 test byte [bp - 2], 1 | 2 1728 jz .display_kernel_mode 1729 %endif 1730 1731 xchg dx, ax ; dl = input al 1732 mov ah, 02h 1733 int 21h 1734 %if _BOOTLDR 1735 db __TEST_IMM16 ; (skip int) 1736 %endif 1737 1738 .display_kernel_mode: 1739 %endif 1740 %if _BOOTLDR 1741 0000019C CD10 int 10h 1742 %endif 1743 %if _IMAGE_EXE 1744 pop dx 1745 %endif 1746 %if _BOOTLDR 1747 0000019E 5D pop bp 1748 0000019F 5B pop bx 1749 %endif 1750 000001A0 58 pop ax 1751 .retn: 1752 disp_error.ret: 1753 000001A1 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 000001A2 4C6F6164206572726F- .error: db "Load error: Decompression failure.",13,10,0 1761 000001AB 723A204465636F6D70- 1761 000001B4 72657373696F6E2066- 1761 000001BD 61696C7572652E0D0A- 1761 000001C6 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" 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" 1 <1> 2 <1> %if 0 3 <1> 4 <1> Lzd - Educational decompressor for the lzip format 5 <1> Copyright (C) 2013-2019 Antonio Diaz Diaz. 6 <1> 7 <1> This program is free software. Redistribution and use in source and 8 <1> binary forms, with or without modification, are permitted provided 9 <1> that the following conditions are met: 10 <1> 11 <1> 1. Redistributions of source code must retain the above copyright 12 <1> notice, this list of conditions and the following disclaimer. 13 <1> 14 <1> 2. Redistributions in binary form must reproduce the above copyright 15 <1> notice, this list of conditions and the following disclaimer in the 16 <1> documentation and/or other materials provided with the distribution. 17 <1> 18 <1> This program is distributed in the hope that it will be useful, 19 <1> but WITHOUT ANY WARRANTY; without even the implied warranty of 20 <1> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 <1> 22 <1> %endif 23 <1> 24 <1> 25 <1> numdef COUNTER, 0, 256 26 <1> %if (_COUNTER - 1) & _COUNTER 27 <1> %error COUNTER must be a power of two 28 <1> %endif 29 <1> 30 <1> 31 <1> amount_states equ 12 32 <1> 33 <1> numdef XLATBSEQ, 7 34 <1> numdef WARNXLATBSEQ, 0 35 <1> 36 <1> 37 <1> %if _XLATBSEQ != 7 38 <1> next_states.beforealign: 39 <1> align 2 40 <1> next_states: 41 <1> .: 42 <1> times 4 db 0 43 <1> db 1, 2, 3, 4, 5, 6, 4, 5 44 <1> .amount: equ $ - . 45 <1> %if .amount != amount_states 46 <1> %error Invalid next_states array content 47 <1> %endif 48 <1> %assign XLATBTABSIZE $ - .beforealign 49 <1> %else 50 <1> %assign XLATBTABSIZE 0 51 <1> %endif 52 <1> 53 <1> 54 <1> State: 55 <1> ; INP: ds:bx -> localvariables 56 <1> ; byte [bx + state.st] 57 <1> ; OUT: CY if st < 7 (is_char() == true) 58 <1> ; NC if st >= 7 (is_char() == false) 59 <1> ; CHG: - 60 <1> .is_char: 61 000001C7 807F2807 <1> cmp byte [bx + state.st], 7 62 000001CB C3 <1> retn 63 <1> 64 <1> 65 <1> ; INP: ds:bx -> localvariables 66 <1> ; byte [bx + state.st] 67 <1> ; OUT: byte [bx + state.st] = al = next state 68 <1> ; CHG: al, ah (ah only if _XLATBSEQ == 6) 69 <1> .set_char: 70 <1> 71 <1> .xlatbseq: 72 <1> %if 0 == _XLATBSEQ ; 10 73 <1> push bx 74 <1> mov al, byte [bx + state.st] 75 <1> mov bx, next_states 76 <1> cs xlatb 77 <1> ; Problem: It is reported that prior to the 386 78 <1> ; a segment override on an xlatb instruction 79 <1> ; does not have any effect. So this choice is 80 <1> ; possibly wrong on those machines. 81 <1> pop bx 82 <1> %elif 1 == _XLATBSEQ ; 13 83 <1> push bx 84 <1> mov al, byte [bx + state.st] 85 <1> mov bx, next_states 86 <1> push ds 87 <1> push cs 88 <1> pop ds 89 <1> xlatb 90 <1> pop ds 91 <1> pop bx 92 <1> %elif 2 == _XLATBSEQ ; 16 93 <1> push bx 94 <1> mov al, byte [bx + state.st] 95 <1> mov bx, next_states 96 <1> add bl, al 97 <1> adc bh, 0 98 <1> mov al, byte [cs:bx] 99 <1> pop bx 100 <1> %elif 3 == _XLATBSEQ ; 14 101 <1> push bx 102 <1> mov al, byte [bx + state.st] 103 <1> xor bx, bx 104 <1> mov bl, al 105 <1> mov al, byte [cs:next_states + bx] 106 <1> pop bx 107 <1> %elif 4 == _XLATBSEQ ; 12 108 <1> push bx 109 <1> mov bl, byte [bx + state.st] 110 <1> mov bh, 0 111 <1> mov al, byte [cs:next_states + bx] 112 <1> pop bx 113 <1> %elif 5 == _XLATBSEQ ; 10 114 <1> push bx 115 <1> mov bl, byte [bx + state.st] 116 <1> ; mov bh, 0 117 <1> ; ! because the pointer stored in ?localvariables 118 <1> ; is normalised bh is already zero here. 119 <1> mov al, byte [cs:next_states + bx] 120 <1> pop bx 121 <1> %elif 6 == _XLATBSEQ ; 12 122 <1> xor ax, ax 123 <1> mov al, byte [bx + state.st] 124 <1> xchg ax, bx 125 <1> mov bl, byte [cs:next_states + bx] 126 <1> xchg ax, bx 127 <1> %elif 7 == _XLATBSEQ ; 16, but minus 13 for table 128 000001CC 8A4728 <1> mov al, byte [bx + state.st] 129 000001CF 2C03 <1> sub al, 3 ; below 4 ? 130 000001D1 7607 <1> jbe .zero ; yes --> 131 000001D3 3C07 <1> cmp al, 10 - 3 ; 10 or 11 initially ? 132 000001D5 7202 <1> jb .have ; no --> 133 000001D7 2C03 <1> sub al, 3 ; convert 134 <1> .have: 135 000001D9 A9 <1> db __TEST_IMM16 ; (skip mov) 136 <1> .zero: 137 000001DA B000 <1> mov al, 0 138 <1> %else 139 <1> %error Invalid xlatb sequence specified 140 <1> %endif 141 <1> %if _WARNXLATBSEQ 142 <1> %assign SIZE $ - .xlatbseq 143 <1> %warning xlatb sequence takes SIZE bytes plus XLATBTABSIZE table 144 <1> %endif 145 <1> .end: 146 000001DC 884728 <1> mov byte [bx + state.st], al 147 000001DF C3 <1> retn 148 <1> 149 <1> 150 <1> ; INP: ds:bx -> localvariables 151 <1> ; byte [bx + state.st] 152 <1> ; al = value to use if is_char() == true 153 <1> ; ah = value to use else 154 <1> ; OUT: byte [bx + state.st] = al = value to use 155 <1> ; CHG: al 156 <1> .select: 157 000001E0 E8E4FF <1> call .is_char 158 000001E3 72F7 <1> jc .end 159 000001E5 88E0 <1> mov al, ah 160 000001E7 EBF3 <1> jmp .end 161 <1> 162 <1> 163 <1> min_dictionary_size: equ 1 << 12 164 <1> max_dictionary_size: equ 1 << 29 165 <1> literal_context_bits: equ 3 166 <1> literal_pos_state_bits: equ 0 ; not used 167 <1> pos_state_bits: equ 2 168 <1> pos_states: equ 1 << pos_state_bits 169 <1> pos_state_mask: equ pos_states - 1 170 <1> 171 <1> len_states: equ 4 172 <1> dis_slot_bits: equ 6 173 <1> start_dis_model: equ 4 174 <1> end_dis_model: equ 14 175 <1> modeled_distances: equ 1 << ( end_dis_model / 2 ) ; 128 176 <1> dis_align_bits: equ 4 177 <1> dis_align_size: equ 1 << dis_align_bits 178 <1> 179 <1> len_low_bits: equ 3 180 <1> len_mid_bits: equ 3 181 <1> len_high_bits: equ 8 182 <1> len_low_symbols: equ 1 << len_low_bits 183 <1> len_mid_symbols: equ 1 << len_mid_bits 184 <1> len_high_symbols: equ 1 << len_high_bits 185 <1> max_len_symbols: equ len_low_symbols + len_mid_symbols + len_high_symbols 186 <1> 187 <1> min_match_len: equ 2 ; must be 2 188 <1> 189 <1> bit_model_move_bits: equ 5 190 <1> bit_model_total_bits: equ 11 191 <1> bit_model_total: equ 1 << bit_model_total_bits 192 <1> 193 <1> 194 <1> struc bit_model 195 00000000 ???? <1> .probability: resw 1 ; initialise to bit_model_total / 2 196 <1> ; at most bit_model_total (800h) 197 <1> endstruc 198 <1> 199 <1> struc len_model 200 00000000 ???? <1> .choice1: resb bit_model_size 201 00000002 ???? <1> .choice2: resb bit_model_size 202 00000004 <1> .bm_low: resb bit_model_size * pos_states * len_low_symbols 203 00000044 <1> .bm_mid: resb bit_model_size * pos_states * len_mid_symbols 204 00000084 <1> .bm_high: resb bit_model_size * len_high_symbols 205 <1> endstruc 206 <1> 207 <1> struc lzip_header 208 00000000 ???????? <1> .magic: resd 1 209 00000004 ?? <1> .version: resb 1 210 00000005 ?? <1> .coded_dict_size: resb 1 211 <1> endstruc 212 <1> 213 <1> struc lzip_trailer 214 00000000 ???????? <1> .uncompressed_checksum: resd 1 215 00000004 ???????????????? <1> .uncompressed_size: resq 1 216 0000000C ???????????????? <1> .member_size: resq 1 217 <1> endstruc 218 <1> 219 <1> struc range_decoder 220 00000000 ???????? <1> .member_pos: resd 1 221 00000004 ???????? <1> .code: resd 1 222 00000008 ???????? <1> .range: resd 1 223 <1> endstruc 224 <1> 225 <1> ; INP: ds:bx -> range_decoder structure 226 <1> ; ss:bp -> depack stack frame 227 <1> ; OUT: ! If an error occurs, jumps to depack.error 228 <1> ; CHG: es, di, ax, cx 229 <1> Range_decoder.init: 230 000001E9 1E <1> push ds 231 000001EA 07 <1> pop es 232 000001EB B80600 <1> mov ax, 6 233 000001EE 89DF <1> mov di, bx ; -> .member_pos 234 000001F0 AB <1> stosw ; low word of .member_pos 235 000001F1 31C0 <1> xor ax, ax 236 000001F3 AB <1> stosw ; high word of .member_pos 237 000001F4 AB <1> stosw 238 000001F5 AB <1> stosw ; .code 239 000001F6 48 <1> dec ax 240 000001F7 AB <1> stosw 241 000001F8 AB <1> stosw ; .range 242 000001F9 B90500 <1> mov cx, 5 243 <1> .loop: 244 000001FC E81900 <1> call getbyteshiftcode 245 000001FF E2FB <1> loop .loop 246 00000201 C3 <1> retn 247 <1> 248 <1> 249 <1> ; INP: ds:bx -> range_decoder structure 250 <1> ; ss:bp -> depack stack frame 251 <1> ; OUT: ! If an error occurs, jumps to depack.error 252 <1> ; CHG: - 253 <1> normaliserange: 254 00000202 807F0B00 <1> cmp byte [bx + range_decoder.range + 3], 0 255 00000206 7521 <1> jnz @F ; (retn) 256 00000208 50 <1> push ax 257 00000209 8B4709 <1> mov ax, word [bx + range_decoder.range + 1] 258 0000020C 89470A <1> mov word [bx + range_decoder.range + 2], ax 259 0000020F 8A6708 <1> mov ah, byte [bx + range_decoder.range] 260 00000212 B000 <1> mov al, 0 261 00000214 894708 <1> mov word [bx + range_decoder.range], ax 262 00000217 58 <1> pop ax 263 <1> ; fall through 264 <1> 265 <1> 266 <1> ; INP: ds:bx -> range_decoder structure 267 <1> ; ss:bp -> depack stack frame 268 <1> ; OUT: ! If an error occurs, jumps to depack.error 269 <1> ; CHG: - 270 <1> getbyteshiftcode: 271 00000218 50 <1> push ax 272 00000219 8B4705 <1> mov ax, word [bx + range_decoder.code + 1] 273 0000021C 894706 <1> mov word [bx + range_decoder.code + 2], ax 274 0000021F 8A6704 <1> mov ah, byte [bx + range_decoder.code] 275 00000222 E8A206 <1> call Range_decoder.get_byte 276 00000225 894704 <1> mov word [bx + range_decoder.code], ax 277 00000228 58 <1> pop ax 278 <1> @@: 279 00000229 C3 <1> retn 280 <1> 281 <1> 282 <1> ; INP: ds:bx -> range_decoder structure 283 <1> ; cx = num_bits 284 <1> ; ss:bp -> depack stack frame 285 <1> ; OUT: ! If an error occurs, jumps to depack.error 286 <1> ; If success, 287 <1> ; dx:ax = symbol 288 <1> ; CHG: di, cx 289 <1> Range_decoder.decode: 290 0000022A 31D2 <1> xor dx, dx 291 0000022C 31C0 <1> xor ax, ax 292 0000022E E32C <1> jcxz .end 293 <1> .loop: 294 00000230 D16F0A <1> shr word [bx + range_decoder.range + 2], 1 295 00000233 D15F08 <1> rcr word [bx + range_decoder.range], 1 296 00000236 D1E0 <1> shl ax, 1 297 00000238 D1D2 <1> rcl dx, 1 298 0000023A 8B7F06 <1> mov di, word [bx + range_decoder.code + 2] 299 0000023D 3B7F0A <1> cmp di, word [bx + range_decoder.range + 2] 300 00000240 7506 <1> jne @F 301 00000242 8B7F04 <1> mov di, word [bx + range_decoder.code] 302 00000245 3B7F08 <1> cmp di, word [bx + range_decoder.range] 303 <1> @@: ; code >= range ? 304 00000248 720D <1> jnae @F ; no, skip --> 305 0000024A 8B7F08 <1> mov di, word [bx + range_decoder.range] 306 0000024D 297F04 <1> sub word [bx + range_decoder.code], di 307 00000250 8B7F0A <1> mov di, word [bx + range_decoder.range + 2] 308 00000253 197F06 <1> sbb word [bx + range_decoder.code + 2], di 309 00000256 40 <1> inc ax ; symbol |= 1 (lowest bit always was zero) 310 <1> @@: 311 00000257 E8A8FF <1> call normaliserange 312 0000025A E2D4 <1> loop .loop 313 <1> .end: 314 0000025C C3 <1> retn 315 <1> 316 <1> 317 <1> ; INP: ds:bx -> range_decoder structure 318 <1> ; es:di -> bit_model structure 319 <1> ; ss:bp -> depack stack frame 320 <1> ; OUT: al = read bit 321 <1> ; NC if zero read 322 <1> ; CY if one read 323 <1> ; ! If an error occurs, jumps to depack.error 324 <1> ; CHG: cx, dx, ax 325 <1> Range_decoder.decode_bit: 326 0000025D 8B570A <1> mov dx, word [bx + range_decoder.range + 2] 327 00000260 8B4708 <1> mov ax, word [bx + range_decoder.range] 328 00000263 B90B00 <1> mov cx, bit_model_total_bits 329 <1> @@: 330 00000266 D1EA <1> shr dx, 1 331 00000268 D1D8 <1> rcr ax, 1 332 0000026A E2FA <1> loop @B 333 <1> 334 0000026C 89D1 <1> mov cx, dx 335 0000026E 26F725 <1> mul word [es:di + bit_model.probability] 336 <1> ; dx:ax = low word + first high word 337 00000271 52 <1> push dx 338 00000272 50 <1> push ax ; on stack = low word + first high word 339 00000273 91 <1> xchg ax, cx 340 00000274 26F725 <1> mul word [es:di + bit_model.probability] 341 <1> ; ax = second high word (dx overflow) 342 00000277 91 <1> xchg ax, cx ; cx 343 00000278 58 <1> pop ax 344 00000279 5A <1> pop dx 345 0000027A 01CA <1> add dx, cx ; = full uint32_t result 346 0000027C B90500 <1> mov cx, bit_model_move_bits 347 <1> 348 0000027F 395706 <1> cmp word [bx + range_decoder.code + 2], dx 349 00000282 7503 <1> jne @F 350 00000284 394704 <1> cmp word [bx + range_decoder.code], ax 351 <1> @@: 352 00000287 7317 <1> jnb .not_code_below_bound 353 <1> 354 <1> .code_below_bound: 355 00000289 894708 <1> mov word [bx + range_decoder.range], ax 356 0000028C 89570A <1> mov word [bx + range_decoder.range + 2], dx 357 0000028F B80008 <1> mov ax, bit_model_total 358 00000292 262B05 <1> sub ax, word [es:di + bit_model.probability] 359 00000295 7228 <1> jc .error 360 00000297 D3E8 <1> shr ax, cl 361 00000299 260105 <1> add word [es:di + bit_model.probability], ax 362 0000029C B000 <1> mov al, 0 363 0000029E EB18 <1> jmp .after_if 364 <1> 365 <1> .not_code_below_bound: 366 000002A0 294708 <1> sub word [bx + range_decoder.range], ax 367 000002A3 19570A <1> sbb word [bx + range_decoder.range + 2], dx 368 000002A6 294704 <1> sub word [bx + range_decoder.code], ax 369 000002A9 195706 <1> sbb word [bx + range_decoder.code + 2], dx 370 <1> 371 000002AC 268B05 <1> mov ax, word [es:di + bit_model.probability] 372 000002AF D3E8 <1> shr ax, cl 373 000002B1 262905 <1> sub word [es:di + bit_model.probability], ax 374 000002B4 7209 <1> jc .error 375 000002B6 B001 <1> mov al, 1 376 <1> 377 <1> .after_if: 378 000002B8 E847FF <1> call normaliserange 379 000002BB 3C01 <1> cmp al, 1 ; CY if 0, NC if 1 380 000002BD F5 <1> cmc ; NC if 0, CY if 1 381 000002BE C3 <1> retn 382 <1> 383 <1> .error: 384 000002BF E9F405 <1> jmp depack.error 385 <1> 386 <1> 387 <1> ; INP: ds:bx -> range_decoder structure 388 <1> ; es:di -> bit_model structure array 389 <1> ; cx = num_bits, <= 15 390 <1> ; ss:bp -> depack stack frame 391 <1> ; OUT: ! If an error occurs, jumps to depack.error 392 <1> ; If success, 393 <1> ; dx:ax = ax = symbol 394 <1> ; CHG: cx, si 395 <1> Range_decoder.decode_tree: 396 000002C2 BE0100 <1> mov si, 1 ; symbol = 1 397 000002C5 83F90F <1> cmp cx, 15 398 000002C8 7721 <1> ja .error 399 000002CA 51 <1> push cx 400 000002CB E312 <1> jcxz .end 401 <1> .loop: 402 000002CD 57 <1> push di 403 <1> ; Here si (symbol) is at most 1 << 14. 404 <1> %if bit_model_size != 2 405 <1> %error Assuming word size for bit_model_size 406 <1> %endif 407 000002CE D1E6 <1> shl si, 1 ; Note that this shift is both used instead of 408 <1> ; multiplying symbol (si) by bit_model_size 409 <1> ; and to actually shift symbol (si) left! 410 000002D0 01F7 <1> add di, si ; index into bit_model array 411 000002D2 7217 <1> jc .error_pop_2 412 000002D4 51 <1> push cx 413 000002D5 E885FF <1> call Range_decoder.decode_bit 414 000002D8 59 <1> pop cx 415 000002D9 83D600 <1> adc si, 0 ; add in the decoded bit 416 000002DC 5F <1> pop di 417 000002DD E2EE <1> loop .loop 418 <1> .end: 419 000002DF 59 <1> pop cx 420 000002E0 B80100 <1> mov ax, 1 421 000002E3 D3E0 <1> shl ax, cl ; = 1 << num_bits 422 000002E5 29C6 <1> sub si, ax ; symbol - ( 1 << num_bits ) 423 000002E7 96 <1> xchg ax, si 424 000002E8 31D2 <1> xor dx, dx ; return symbol 425 000002EA C3 <1> retn 426 <1> 427 <1> .error_pop_2: 428 <1> .error: 429 000002EB E9C805 <1> jmp depack.error 430 <1> 431 <1> 432 <1> ; INP: ds:bx -> range_decoder structure 433 <1> ; es:di -> bit_model structure array 434 <1> ; cx = num_bits, <= 15 435 <1> ; ss:bp -> depack stack frame 436 <1> ; OUT: ! If an error occurs, jumps to depack.error 437 <1> ; If success, 438 <1> ; dx:ax = ax = reversed_symbol 439 <1> ; CHG: cx, si 440 <1> Range_decoder.decode_tree_reversed: 441 000002EE 51 <1> push cx 442 000002EF E8D0FF <1> call Range_decoder.decode_tree 443 000002F2 59 <1> pop cx 444 000002F3 92 <1> xchg dx, ax ; dx = symbol 445 000002F4 31C0 <1> xor ax, ax ; = reversed_symbol 446 000002F6 E306 <1> jcxz .end 447 <1> .loop: 448 000002F8 D1EA <1> shr dx, 1 449 000002FA D1D0 <1> rcl ax, 1 450 000002FC E2FA <1> loop .loop 451 <1> .end: 452 000002FE 31D2 <1> xor dx, dx 453 00000300 C3 <1> retn 454 <1> 455 <1> 456 <1> ; INP: ds:bx -> range_decoder structure 457 <1> ; es:di -> bit_model structure array 458 <1> ; al = match_byte 459 <1> ; ss:bp -> depack stack frame 460 <1> ; OUT: ! If an error occurs, jumps to depack.error 461 <1> ; If success, 462 <1> ; al = return value (symbol & 0FFh) 463 <1> ; CHG: cx, dx, ax 464 <1> Range_decoder.decode_matched: 465 00000301 88C6 <1> mov dh, al ; = match_byte 466 <1> 467 00000303 B80100 <1> mov ax, 1 ; initialise symbol = 1 468 <1> 469 00000306 B90800 <1> mov cx, 8 470 <1> .loop: 471 00000309 52 <1> push dx ; preserve dh = match_byte 472 0000030A 51 <1> push cx ; preserve loop counter 473 0000030B 49 <1> dec cx 474 0000030C D2EE <1> shr dh, cl ; match_byte >> i 475 0000030E 81E20001 <1> and dx, 100h ; dh &= 1 = match_bit, dl = 0 476 00000312 52 <1> push dx 477 00000313 FEC6 <1> inc dh ; = (match_bit << 8) + 100h 478 00000315 01C2 <1> add dx, ax ; = symbol + (match_bit << 8) + 100h 479 <1> ; As symbol is below 256, this is at most 255 + 100h + 100h, 480 <1> ; which is 2FFh. As such, the bm_literal array's 481 <1> ; entries are arrays of 300h bit_model each. 482 00000317 57 <1> push di 483 00000318 50 <1> push ax 484 <1> %if bit_model_size != 2 485 <1> %error Assuming word size for bit_model_size 486 <1> %endif 487 00000319 01D2 <1> add dx, dx 488 <1> ; As dx was < 300h before this addition, it cannot carry. 489 0000031B 01D7 <1> add di, dx 490 <1> ; We assume that this does not carry. 491 0000031D E83DFF <1> call Range_decoder.decode_bit 492 00000320 91 <1> xchg ax, cx ; cl = result (1 or 0) 493 00000321 58 <1> pop ax ; = symbol 494 00000322 5F <1> pop di 495 00000323 5A <1> pop dx ; = match_bit << 8 496 00000324 D1D0 <1> rcl ax, 1 ; shift symbol, OR in the bit 497 <1> ; As the loop counter is initialised to 8, 498 <1> ; the symbol variable stays below 256. 499 00000326 38F1 <1> cmp cl, dh ; if( match_bit != bit ) ...- 500 00000328 59 <1> pop cx ; = loop counter 501 00000329 5A <1> pop dx ; = dh = match_byte 502 0000032A 7519 <1> jne .inner_next ; -... do the following --> 503 <1> .next: 504 0000032C E2DB <1> loop .loop 505 <1> .end: 506 0000032E 30E4 <1> xor ah, ah ; return ax = symbol & 0FFh 507 00000330 C3 <1> retn 508 <1> 509 <1> .error_pop_2: 510 <1> .error: 511 00000331 E98205 <1> jmp depack.error 512 <1> 513 <1> 514 <1> .inner_loop: 515 00000334 50 <1> push ax 516 <1> %if bit_model_size != 2 517 <1> %error Assuming word size for bit_model_size 518 <1> %endif 519 00000335 01C0 <1> add ax, ax 520 00000337 57 <1> push di 521 00000338 01C7 <1> add di, ax 522 0000033A 72F5 <1> jc .error_pop_2 523 0000033C E81EFF <1> call Range_decoder.decode_bit 524 0000033F 5F <1> pop di 525 00000340 58 <1> pop ax 526 00000341 D1D0 <1> rcl ax, 1 527 00000343 72EC <1> jc .error 528 <1> 529 <1> .inner_next: 530 00000345 3D0001 <1> cmp ax, 100h 531 00000348 72EA <1> jb .inner_loop 532 0000034A EBE2 <1> jmp .end 533 <1> 534 <1> 535 <1> ; INP: ds:bx -> range_decoder structure 536 <1> ; es:di -> len_model structure 537 <1> ; ax = pos_state 538 <1> ; ss:bp -> depack stack frame 539 <1> ; OUT: ! If an error occurs, jumps to depack.error 540 <1> ; If success, 541 <1> ; dx:ax = return 542 <1> ; CHG: cx, si 543 <1> Range_decoder.decode_len: 544 0000034C 89C6 <1> mov si, ax ; = pos_state 545 0000034E 57 <1> push di ; = len_model_struc (on stack) 546 <1> 547 0000034F 8D3D <1> lea di, [di + len_model.choice1] 548 00000351 E809FF <1> call Range_decoder.decode_bit 549 00000354 5F <1> pop di ; reset to ?len_model_struc 550 00000355 57 <1> push di 551 00000356 7218 <1> jc .not_decode_bit_choice1_equals_zero 552 <1> 553 00000358 8D7D04 <1> lea di, [di + len_model.bm_low] 554 0000035B B81000 <1> mov ax, len_low_symbols * bit_model_size 555 0000035E F7E6 <1> mul si 556 00000360 85D2 <1> test dx, dx 557 00000362 7546 <1> jnz .error 558 00000364 01C7 <1> add di, ax 559 00000366 7242 <1> jc .error 560 00000368 B90300 <1> mov cx, len_low_bits 561 0000036B E854FF <1> call Range_decoder.decode_tree 562 0000036E EB38 <1> jmp .ret 563 <1> 564 <1> .not_decode_bit_choice1_equals_zero: 565 00000370 8D7D02 <1> lea di, [di + len_model.choice2] 566 00000373 E8E7FE <1> call Range_decoder.decode_bit 567 00000376 5F <1> pop di ; reset to ?len_model_struc 568 00000377 57 <1> push di 569 00000378 721E <1> jc .not_decode_bit_choice2_equals_zero 570 <1> 571 0000037A 8D7D44 <1> lea di, [di + len_model.bm_mid] 572 0000037D B81000 <1> mov ax, len_mid_symbols * bit_model_size 573 00000380 F7E6 <1> mul si 574 00000382 85D2 <1> test dx, dx 575 00000384 7524 <1> jnz .error 576 00000386 01C7 <1> add di, ax 577 00000388 7220 <1> jc .error 578 0000038A B90300 <1> mov cx, len_mid_bits 579 0000038D E832FF <1> call Range_decoder.decode_tree 580 00000390 83C008 <1> add ax, len_low_symbols & 0FFFFh 581 00000393 83D200 <1> adc dx, len_low_symbols >> 16 582 00000396 EB10 <1> jmp .ret 583 <1> 584 <1> .not_decode_bit_choice2_equals_zero: 585 00000398 8DBD8400 <1> lea di, [di + len_model.bm_high] 586 0000039C B90800 <1> mov cx, len_high_bits 587 0000039F E820FF <1> call Range_decoder.decode_tree 588 000003A2 83C010 <1> add ax, (len_low_symbols + len_mid_symbols) & 0FFFFh 589 000003A5 83D200 <1> adc dx, (len_low_symbols + len_mid_symbols) >> 16 590 <1> .ret: 591 000003A8 5F <1> pop di 592 000003A9 C3 <1> retn 593 <1> 594 <1> .error: 595 000003AA E90905 <1> jmp depack.error 596 <1> 597 <1> 598 <1> struc lz_decoder 599 00000000 <1> .range_decoder: resb range_decoder_size 600 0000000C ???????? <1> alignb 8 601 00000010 ???????? <1> .dictionary_size: resd 1 602 00000014 ???????? <1> .pos: resd 1 603 <1> endstruc 604 <1> 605 <1> 606 <1> ; INP: ds:bx -> lz_decoder structure, localvariables structure 607 <1> ; dx:ax = distance 608 <1> ; OUT: al = ax = byte from buffer 609 <1> ; CHG: dx, cx, di, si, es 610 <1> LZ_decoder.peek: 611 000003AD 395716 <1> cmp word [bx + lz_decoder.pos + 2], dx 612 000003B0 7503 <1> jne @F 613 000003B2 394714 <1> cmp word [bx + lz_decoder.pos], ax 614 <1> @@: 615 000003B5 760A <1> jna .not_pos_above_distance 616 <1> 617 000003B7 E80A00 <1> call calculate_peek_pointer_disi 618 <1> 619 000003BA 8EC7 <1> mov es, di ; es:si -> peek address 620 000003BC 31C0 <1> xor ax, ax 621 000003BE 26AC <1> es lodsb 622 000003C0 C3 <1> retn 623 <1> 624 <1> .not_pos_above_distance: 625 000003C1 31C0 <1> xor ax, ax 626 000003C3 C3 <1> retn 627 <1> 628 <1> 629 <1> ; INP: dx:ax = peek distance 630 <1> ; ds:bx -> local variables 631 <1> ; OUT: di:si -> peek address 632 <1> ; CHG: cx, dx, ax 633 <1> calculate_peek_pointer_disi: 634 000003C4 53 <1> push bx 635 000003C5 FF772E <1> push word [bx + destinationbuffer_constant + 2] 636 000003C8 FF772C <1> push word [bx + destinationbuffer_constant] 637 <1> 638 000003CB F7DA <1> neg dx 639 000003CD F7D8 <1> neg ax 640 000003CF 83DA00 <1> sbb dx, byte 0 ; neg dx:ax = - distance 641 000003D2 83E801 <1> sub ax, 1 642 000003D5 83DA00 <1> sbb dx, 0 ; - 1 643 000003D8 034714 <1> add ax, word [bx + lz_decoder.pos] 644 000003DB 135716 <1> adc dx, word [bx + lz_decoder.pos + 2] 645 <1> ; + pos 646 000003DE 91 <1> xchg cx, ax 647 000003DF 87DA <1> xchg bx, dx 648 <1> 649 000003E1 E88A06 <1> call normalise_pointer_with_displacement_bxcx 650 000003E4 5E <1> pop si 651 000003E5 5F <1> pop di ; di:si -> source 652 000003E6 5B <1> pop bx 653 000003E7 C3 <1> retn 654 <1> 655 <1> 656 <1> ; INP: ss:bp -> depack stack frame 657 <1> ; OUT: ! If an error occurs, jumps to depack.error 658 <1> ; If success, 659 <1> ; al = byte 660 <1> ; CHG: - 661 <1> LZ_decoder.get_byte: equ Range_decoder.get_byte 662 <1> 663 <1> 664 <1> struc localvariables 665 <1> lz_decoder_struc: 666 00000000 <1> resb lz_decoder_size 667 <1> alignb 4 668 <1> zeros_start: 669 00000018 ???????? <1> rep0: resd 1 670 0000001C ???????? <1> rep1: resd 1 671 00000020 ???????? <1> rep2: resd 1 672 00000024 ???????? <1> rep3: resd 1 673 00000028 ???? <1> state.st: resw 1 ; initialise to zero 674 0000002A ???? <1> alignb 4 675 <1> zeros_end: 676 0000002C ???????? <1> destinationbuffer_constant: resd 1 ; stays constant 677 <1> alignb 16 678 <1> bit_models_start: 679 00000030 <1> bm_match: resb bit_model_size * amount_states * pos_states 680 00000090 <1> bm_rep: resb bit_model_size * amount_states 681 000000A8 <1> bm_rep0: resb bit_model_size * amount_states 682 000000C0 <1> bm_rep1: resb bit_model_size * amount_states 683 000000D8 <1> bm_rep2: resb bit_model_size * amount_states 684 000000F0 <1> bm_literal: resb bit_model_size * (1 << literal_context_bits) * 300h 685 000030F0 <1> bm_len: resb bit_model_size * amount_states * pos_states 686 00003150 <1> bm_dis_slot: resb bit_model_size * len_states * (1 << dis_slot_bits) 687 00003350 <1> bm_dis: resb bit_model_size * (modeled_distances - end_dis_model + 1) 688 00003436 <1> bm_align: resb bit_model_size * dis_align_size 689 00003456 <1> match_len_model:resb len_model_size 690 000036DA <1> rep_len_model: resb len_model_size 691 <1> bit_models_end: 692 0000395E ???? <1> alignb 16 693 <1> endstruc 694 <1> %if lz_decoder_struc != 0 695 <1> %error Expecting lz_decoder structure at start of localvariables structure 696 <1> %endif 697 <1> %assign STRUCSIZE localvariables_size 698 <1> %warning localvariables has STRUCSIZE bytes 698 ****************** <1> warning: localvariables has 14688 bytes [-w+user] 699 <1> 700 <1> 701 <1> align 4 702 <1> lzip_header_bytes: 703 <1> .: 704 000003E8 4C5A495001 <1> db "LZIP",1 705 <1> .length: equ $ - . 706 <1> 707 <1> 708 <1> ; INP: ds:si -> source 709 <1> ; dx:cx = length of source 710 <1> ; es:di -> destination (below source) 711 <1> ; if _IMAGE_EXE: 712 <1> ; bx = EXE mode flag (bit 0) 713 <1> ; else: 714 <1> ; bx = 0 715 <1> ; if _PAYLOAD_KERNEL_MAX_PARAS: 716 <1> ; ax = maximum amount in paragraphs of destination needed 717 <1> ; (-1 if full source should be decompressed) 718 <1> ; else: 719 <1> ; ax = -1 720 <1> ; OUT: NC if success 721 <1> ; CY if error, 722 <1> ; bx = ?errordata (if _DEBUG0) 723 <1> ; CHG: ax, (bx), cx, dx, es, ds, si, di 724 <1> ; STT: UP 725 <1> ; 726 <1> ; Note: The destination reaches up to below the source. 727 <1> ; Note: The input pointers need not be normalised yet. 728 <1> ; Normalised means that the offset part is below 16. 729 <1> depack: 730 <1> lframe near 731 <1> %if _IMAGE_EXE || _COUNTER || _DEBUG0 732 000003ED 5589E5 <1> lenter early 733 <1> %if _IMAGE_EXE 734 <1> lvar word, exemode ; must be bp - 2! 735 <1> push bx 736 <1> %if ?exemode != -2 737 <1> %error exemode variable must be directly below bp 738 <1> %endif 739 <1> %endif 740 <1> %if _COUNTER || _DEBUG0 741 000003F0 31DB <1> xor bx, bx 742 <1> %endif 743 <1> %endif 744 <1> %if _COUNTER 745 <1> lvar word, counter 746 000003F2 53 <1> push bx ; initialise counter to zero 747 <1> %endif 748 <1> d0 lvar word, errordata 749 <1> d0 push bx 750 <1> lvar dword, distance 751 <1> lvar dword, len 752 <1> lvar dword, dis_slot 753 <1> lvar word, len_state 754 <1> lvar word, pos_state 755 000003F3 8D66EE <1> lenter 756 <1> 757 000003F6 E84406 <1> call normalise_both_pointers 758 <1> 759 <1> ; ! di < 16, so dih == 0 760 <1> lvar dword, src 761 000003F9 1E <1> push ds 762 000003FA 56 <1> push si 763 <1> lvar dword, final_dst 764 000003FB 06 <1> push es 765 000003FC 57 <1> push di 766 <1> lequ ?final_dst, localvariables 767 <1> ; ! offset of ?localvariables is always < 16 768 <1> ; required for State.set_char with _XLATBSEQ == 5 769 <1> lvar dword, length_of_source 770 000003FD 52 <1> push dx 771 000003FE 51 <1> push cx 772 <1> 773 <1> %if _PAYLOAD_KERNEL_MAX_PARAS 774 <1> cmp ax, -1 ; no maximum specified ? 775 <1> je @FF ; retain -1 in ax --> 776 <1> test di, di ; do we need an additional paragraph ? 777 <1> jz @F ; no --> 778 <1> inc ax ; es + ax => paragraph after necessary part 779 <1> @@: 780 <1> mov dx, es 781 <1> add ax, dx ; => paragraph after necessary part 782 <1> ; If the normalised destination pointer's segment grows 783 <1> ; to this segment then enough has been decompressed. 784 <1> d0 mov byte [bp + ?errordata], 40h 785 <1> jc .error_CY_a1 ; should not carry 786 <1> @@: 787 <1> lvar word, dst_max_segment 788 <1> push ax 789 <1> %endif 790 <1> 791 000003FF 1E <1> push ds 792 00000400 56 <1> push si 793 00000401 E89906 <1> call pointer_to_linear 794 <1> 795 00000404 87DA <1> xchg bx, dx 796 00000406 91 <1> xchg cx, ax ; bx:cx = source linear, clobber dx:ax 797 <1> 798 00000407 06 <1> push es 799 00000408 57 <1> push di 800 00000409 E89106 <1> call pointer_to_linear 801 <1> 802 <1> %if _ALLOW_OVERLAPPING 803 0000040C 034EE2 <1> add cx, word [bp + ?length_of_source] 804 0000040F 135EE4 <1> adc bx, word [bp + ?length_of_source + 2] 805 <1> ; In case of allowing overlapping source and destination, 806 <1> ; the ?length_of_destination variable is set to 807 <1> ; ?src + ?length_of_source - ?dst, allowing to write to 808 <1> ; all of the source buffer (with the checks already in place 809 <1> ; from the default handling). Additional checks are done by 810 <1> ; calling check_pointers_not_overlapping. This is done after 811 <1> ; every change of ?dst to verify that the write pointer stays 812 <1> ; below-or-equal the read pointer. 813 <1> ; This means the remaining source data may be corrupted by a 814 <1> ; write, but nothing after the source data is written to, 815 <1> ; so the error handling (in INIT1 after the data) still works. 816 <1> %endif 817 <1> 818 00000412 29C1 <1> sub cx, ax 819 00000414 19D3 <1> sbb bx, dx ; bx:cx = source linear - destination linear 820 <1> 821 00000416 81E96039 <1> sub cx, localvariables_size & 0FFFFh 822 0000041A 83DB00 <1> sbb bx, localvariables_size >> 16 823 0000041D 7703E99404 <1> jbe .error ; make variables buffer available 824 <1> 825 <1> lvar dword, length_of_destination 826 00000422 53 <1> push bx ; push into [bp + ?length_of_destination + 2] 827 00000423 51 <1> push cx ; push into [bp + ?length_of_destination] 828 <1> 829 00000424 06 <1> push es 830 00000425 57 <1> push di 831 <1> %if localvariables_size >> 16 832 <1> mov bx, localvariables_size >> 16 833 <1> %else 834 00000426 31DB <1> xor bx, bx 835 <1> %endif 836 00000428 B96039 <1> mov cx, localvariables_size & 0FFFFh 837 0000042B E84006 <1> call normalise_pointer_with_displacement_bxcx 838 0000042E 5F <1> pop di 839 0000042F 07 <1> pop es 840 <1> 841 <1> lvar dword, original_dst 842 00000430 06 <1> push es 843 00000431 57 <1> push di 844 <1> lvar dword, dst 845 00000432 06 <1> push es 846 00000433 57 <1> push di 847 <1> 848 <1> %if _ALLOW_OVERLAPPING 849 00000434 E8EA05 <1> call check_pointers_not_overlapping 850 <1> ; Note: We initially check here that the write pointer is 851 <1> ; low enough, ie below-or-equal the read pointer. 852 <1> ; Unlike the other decompressors, this check is done 853 <1> ; after any copied match or literal too, because 854 <1> ; literals can presumably be encoded with less than 855 <1> ; one byte of source data to the range decoder. 856 <1> d0 mov byte [bp + ?errordata], 1Bh 857 <1> .error_CY_a1: 858 00000437 7243 <1> jc short .error_CY_a 859 <1> %else 860 <1> .error_CY_a1 equ .error_CY_a 861 <1> %endif 862 <1> 863 <1> 864 <1> member_min_size equ lzip_header_size + lzip_trailer_size 865 <1> 866 <1> .loop_member: 867 00000439 837EE400 <1> cmp word [bp + ?length_of_source + 2], 0 868 0000043D 7504 <1> jne @F 869 0000043F 837EE21A <1> cmp word [bp + ?length_of_source], member_min_size 870 <1> @@: 871 00000443 770F <1> ja .got_member 872 <1> 873 00000445 837EE400 <1> cmp word [bp + ?length_of_source + 2], 0 874 00000449 7504 <1> jne @F 875 0000044B 837EE20F <1> cmp word [bp + ?length_of_source], 15 876 <1> @@: 877 0000044F 7710 <1> ja short .error_NZ_a ; (NZ if jumping) 878 00000451 E92E04 <1> jmp .end 879 <1> 880 <1> .got_member: 881 00000454 C576EA <1> lds si, [bp + ?src] ; ds:si -> lzip_header.magic, .version 882 00000457 0E <1> push cs 883 00000458 07 <1> pop es 884 00000459 BF[E803] <1> mov di, lzip_header_bytes 885 0000045C B90500 <1> mov cx, lzip_header_bytes.length 886 0000045F F3A6 <1> repe cmpsb 887 <1> .error_NZ_a: 888 00000461 7403E95004 <1> jne .error 889 <1> %if _COUNTER && !_PROGRESS 890 <1> mov al, '#' 891 <1> call disp_al 892 <1> %endif 893 00000466 31C0 <1> xor ax, ax 894 00000468 AC <1> lodsb ; ax = lzip_header.coded_dict_size 895 <1> 896 00000469 1E <1> push ds 897 0000046A 56 <1> push si 898 0000046B E8DE05 <1> call normalise_pointer 899 0000046E 8F46EA <1> pop word [bp + ?src] 900 00000471 8F46EC <1> pop word [bp + ?src + 2] 901 00000474 836EE206 <1> sub word [bp + ?length_of_source], 6 902 00000478 835EE400 <1> sbb word [bp + ?length_of_source + 2], 0 903 <1> .error_CY_a: 904 0000047C 7235 <1> jc short .error_CY_b 905 <1> 906 0000047E 50 <1> push ax 907 0000047F 241F <1> and al, 1Fh 908 00000481 91 <1> xchg cx, ax ; cx = coded dict size & 1Fh, clobber ax 909 00000482 B80100 <1> mov ax, 1 910 00000485 31D2 <1> xor dx, dx 911 <1> @@: 912 00000487 D1E0 <1> shl ax, 1 913 00000489 D1D2 <1> rcl dx, 1 914 0000048B E2FA <1> loop @B 915 <1> 916 0000048D 89D3 <1> mov bx, dx 917 0000048F 89C7 <1> mov di, ax ; bx:di = dict_size 918 00000491 B104 <1> mov cl, 4 919 <1> @@: 920 00000493 D1EB <1> shr bx, 1 921 00000495 D1DF <1> rcr di, 1 922 00000497 E2FA <1> loop @B ; bx:di = dict_size / 16 923 00000499 59 <1> pop cx 924 0000049A 88CD <1> mov ch, cl 925 0000049C B105 <1> mov cl, 5 926 0000049E D2ED <1> shr ch, cl 927 000004A0 88E9 <1> mov cl, ch 928 000004A2 B500 <1> mov ch, 0 929 000004A4 E331 <1> jcxz @FF 930 <1> 931 000004A6 52 <1> push dx 932 000004A7 50 <1> push ax 933 <1> 934 000004A8 89F8 <1> mov ax, di ; ax = low word of input 935 000004AA F7E1 <1> mul cx 936 000004AC 93 <1> xchg ax, bx ; ax = high word of input 937 000004AD 89D7 <1> mov di, dx ; di:bx = low word + first high word 938 000004AF F7E1 <1> mul cx ; = high word 939 000004B1 01C7 <1> add di, ax ; add into sum 940 <1> .error_CY_b: 941 000004B3 7217 <1> jc short .error_CY_c 942 000004B5 85D2 <1> test dx, dx ; overflows ? 943 000004B7 7403E9FA03 <1> jnz .error 944 <1> ; bx:di = dict_size / 16 * fraction 945 000004BC 58 <1> pop ax 946 000004BD 5A <1> pop dx 947 000004BE 29D8 <1> sub ax, bx 948 000004C0 19FA <1> sbb dx, di 949 000004C2 7208 <1> jc short .error_CY_c 950 <1> 951 000004C4 83FA00 <1> cmp dx, min_dictionary_size >> 16 952 000004C7 7503 <1> jne @F 953 000004C9 3D0010 <1> cmp ax, min_dictionary_size & 0FFFFh 954 <1> @@: 955 <1> .error_CY_c: 956 000004CC 7273 <1> jb short .error_CY_d 957 <1> 958 000004CE 81FA0020 <1> cmp dx, max_dictionary_size >> 16 959 000004D2 7503 <1> jne @F 960 000004D4 83F800 <1> cmp ax, max_dictionary_size & 0FFFFh 961 <1> @@: 962 000004D7 7603E9DA03 <1> ja .error 963 <1> 964 000004DC C55EE6 <1> lds bx, [bp + ?final_dst] 965 000004DF FF76D8 <1> push word [bp + ?dst + 2] 966 000004E2 FF76D6 <1> push word [bp + ?dst] 967 000004E5 8F472C <1> pop word [bx + destinationbuffer_constant] 968 000004E8 8F472E <1> pop word [bx + destinationbuffer_constant + 2] 969 <1> 970 <1> 971 <1> ; decode_member start (inlined) 972 <1> ; INP: ?localvariables = ds:bx -> localvariables structure, 973 <1> ; destinationbuffer_constant pre-initialised 974 <1> ; dx:ax = dictionary size 975 <1> ; Following variables of depack frame initialised: 976 <1> ; dword [ss:bp + ?src] -> source buffer 977 <1> ; dword [ss:bp + ?length_of_source] = remaining length 978 <1> ; dword [ss:bp + ?dst] -> destination buffer 979 <1> ; dword [ss:bp + ?length_of_destination] = remaining 980 <1> ; OUT: NC if success 981 <1> ; CY if error 982 <1> ; CHG: all 983 <1> ; LZ_decoder.decode_member: 984 <1> 985 000004EB 52 <1> push dx 986 000004EC 50 <1> push ax ; preserve dictionary size 987 000004ED 1E <1> push ds 988 000004EE 07 <1> pop es 989 000004EF 89DF <1> mov di, bx 990 000004F1 B90C00 <1> mov cx, fromdwords(dwords(lz_decoder_size)) / 2 991 000004F4 31C0 <1> xor ax, ax 992 000004F6 F3AB <1> rep stosw ; initialise lz_decoder structure 993 <1> 994 000004F8 E8EEFC <1> call Range_decoder.init ; initialise embedded range_decoder 995 <1> 996 000004FB 8F4710 <1> pop word [bx + lz_decoder.dictionary_size] 997 000004FE 8F4712 <1> pop word [bx + lz_decoder.dictionary_size + 2] 998 <1> ; set dictionary size 999 <1> 1000 00000501 8D7F30 <1> lea di, [bx + bit_models_start] 1001 00000504 B9971C <1> mov cx, (bit_models_end - bit_models_start) / bit_model_size 1002 00000507 B80004 <1> mov ax, bit_model_total / 2 ; initial value for bit_model 1003 <1> %if bit_model_size != 2 1004 <1> %error Assuming word size for bit_model_size 1005 <1> %endif 1006 0000050A F3AB <1> rep stosw ; initialise this bit_model 1007 <1> ; loop for all bit_model and len_model 1008 <1> 1009 0000050C 8D7F18 <1> lea di, [bx + zeros_start] 1010 0000050F 31C0 <1> xor ax, ax 1011 00000511 B10A <1> mov cl, (zeros_end - zeros_start) / 2 1012 00000513 F3AB <1> rep stosw 1013 <1> 1014 <1> .loop: 1015 <1> %if _COUNTER 1016 00000515 FE46FE <1> inc byte [bp + ?counter] 1017 00000518 F646FEFF <1> test byte [bp + ?counter], _COUNTER - 1 1018 0000051C 7505 <1> jnz @F 1019 0000051E B02E <1> mov al, '.' 1020 00000520 E80DFB <1> call disp_al_counter 1021 <1> @@: 1022 <1> %endif 1023 00000523 8B5EE6 <1> mov bx, word [bp + ?localvariables] 1024 00000526 8B4714 <1> mov ax, word [bx + lz_decoder.pos] 1025 00000529 83E003 <1> and ax, pos_state_mask 1026 0000052C 91 <1> xchg cx, ax ; cx = pos_state, ax clobbered 1027 0000052D 894EEE <1> mov word [bp + ?pos_state], cx 1028 <1> 1029 00000530 1E <1> push ds 1030 00000531 07 <1> pop es 1031 00000532 8D7F30 <1> lea di, [bx + bm_match] ; es:di -> bm_match 2D array 1032 00000535 B80800 <1> mov ax, bit_model_size * pos_states 1033 00000538 F76728 <1> mul word [bx + state.st] ; dx:ax = first index is state 1034 <1> ; bit_model_size = 2 1035 <1> ; pos_states = 4 1036 <1> ; state.st < 12 1037 <1> ; multiplication 2 * 4 * 11 = 88 1038 <1> %if bit_model_size != 2 1039 <1> %error Assuming word size for bit_model_size 1040 <1> %endif 1041 0000053B 01C9 <1> add cx, cx ; = second index (from pos_state) 1042 <1> ; pos_state < 4 1043 <1> ; cx < 8 1044 <1> ; ax <= 88 1045 0000053D 01C8 <1> add ax, cx ; = second index is pos_state 1046 0000053F 01C7 <1> add di, ax ; es:di -> bm_match[state()][pos_state] 1047 <1> .error_CY_d: 1048 00000541 7222 <1> jc short .error_CY_1 1049 00000543 E817FD <1> call Range_decoder.decode_bit 1050 00000546 7244 <1> jc .1st_bit_not_zero 1051 <1> 1052 <1> .1st_bit_zero: ; literal byte 1053 00000548 31C0 <1> xor ax, ax 1054 0000054A 31D2 <1> xor dx, dx 1055 0000054C E85EFE <1> call LZ_decoder.peek ; al = prev_byte 1056 <1> 1057 0000054F B105 <1> mov cl, 8 - literal_context_bits 1058 00000551 D2E8 <1> shr al, cl ; = literal_state 1059 00000553 1E <1> push ds 1060 00000554 07 <1> pop es 1061 00000555 8DBFF000 <1> lea di, [bx + bm_literal] ; -> 2D array bm_literal 1062 00000559 B90006 <1> mov cx, bit_model_size * 300h 1063 0000055C F7E1 <1> mul cx ; first index is literal_state 1064 0000055E 85D2 <1> test dx, dx 1065 00000560 F9 <1> stc 1066 00000561 7502 <1> jnz short .error_CY_1 1067 00000563 01C7 <1> add di, ax ; es:di -> bm_literal[literal_state] 1068 <1> .error_CY_1: 1069 00000565 7232 <1> jc short .error_CY_2 1070 <1> 1071 00000567 E85DFC <1> call State.is_char 1072 0000056A 7308 <1> jnc .not_is_char 1073 <1> .is_char: 1074 0000056C B90800 <1> mov cx, 8 1075 0000056F E850FD <1> call Range_decoder.decode_tree 1076 00000572 EB10 <1> jmp @F 1077 <1> 1078 <1> .not_is_char: 1079 00000574 8B4718 <1> mov ax, word [bx + rep0] 1080 00000577 8B571A <1> mov dx, word [bx + rep0 + 2] 1081 0000057A 06 <1> push es 1082 0000057B 57 <1> push di 1083 0000057C E82EFE <1> call LZ_decoder.peek 1084 0000057F 5F <1> pop di 1085 00000580 07 <1> pop es 1086 00000581 E87DFD <1> call Range_decoder.decode_matched 1087 <1> @@: 1088 00000584 E86703 <1> call LZ_decoder.put_byte 1089 00000587 E842FC <1> call State.set_char 1090 0000058A EB89 <1> jmp .loop 1091 <1> 1092 <1> 1093 <1> .1st_bit_not_zero: ; match or repeated match 1094 0000058C 1E <1> push ds 1095 0000058D 07 <1> pop es 1096 0000058E 8DBF9000 <1> lea di, [bx + bm_rep] ; es:di -> bm_rep array 1097 <1> %if bit_model_size != 2 1098 <1> %error Assuming word size for bit_model_size 1099 <1> %endif 1100 00000592 8B4728 <1> mov ax, word [bx + state.st] 1101 00000595 01C0 <1> add ax, ax ; ax = index is state 1102 <1> ; jc short .error_CY_2 ; (state.st is always < 12) 1103 00000597 01C7 <1> add di, ax ; es:di -> bm_rep[state()] 1104 <1> .error_CY_2: 1105 00000599 7230 <1> jc short .error_CY_3 1106 0000059B E8BFFC <1> call Range_decoder.decode_bit 1107 0000059E 7203E9EA00 <1> jnc .2nd_bit_zero 1108 <1> 1109 <1> .2nd_bit_not_zero: 1110 000005A3 1E <1> push ds 1111 000005A4 07 <1> pop es 1112 000005A5 8DBFA800 <1> lea di, [bx + bm_rep0] ; es:di -> bm_rep0 array 1113 <1> %if bit_model_size != 2 1114 <1> %error Assuming word size for bit_model_size 1115 <1> %endif 1116 000005A9 8B4728 <1> mov ax, word [bx + state.st] 1117 000005AC 01C0 <1> add ax, ax ; ax = index is state 1118 <1> ; jc short .error_CY_3 ; (state.st is always < 12) 1119 000005AE 01C7 <1> add di, ax ; es:di -> bm_rep0[state()] 1120 000005B0 7219 <1> jc short .error_CY_3 1121 000005B2 E8A8FC <1> call Range_decoder.decode_bit 1122 000005B5 7233 <1> jc .3rd_bit_not_zero 1123 <1> 1124 <1> .3rd_bit_zero: 1125 000005B7 1E <1> push ds 1126 000005B8 07 <1> pop es 1127 000005B9 8DBFF030 <1> lea di, [bx + bm_len] ; es:di -> bm_len 2D array 1128 000005BD B80800 <1> mov ax, bit_model_size * pos_states 1129 <1> ; (2 * 4 = 8) 1130 000005C0 F76728 <1> mul word [bx + state.st]; (< 12) 1131 <1> ; dx:ax = first index is state 1132 <1> ; test dx, dx 1133 <1> ; stc 1134 <1> ; jnz short .error_CY_3 ; (dx:ax is always < 12 * 8) 1135 <1> %if bit_model_size != 2 1136 <1> %error Assuming word size for bit_model_size 1137 <1> %endif 1138 <1> %rep bit_model_size 1139 <1> add ax, word [bp + ?pos_state] 1140 <1> ; jc short .error_CY_3 ; (pos_state is always < 4 1141 <1> ; and state_st is always < 12 1142 <1> ; and ax is < 12 * 8 prior to adding) 1143 <1> %endrep 1139 000005C3 0346EE <2> add ax, word [bp + ?pos_state] 1140 <2> 1141 <2> 1142 <2> 1139 000005C6 0346EE <2> add ax, word [bp + ?pos_state] 1140 <2> 1141 <2> 1142 <2> 1144 000005C9 01C7 <1> add di, ax ; es:di -> bm_len[state()] 1145 <1> .error_CY_3: 1146 000005CB 722A <1> jc short .error_CY_4 1147 000005CD E88DFC <1> call Range_decoder.decode_bit 1148 000005D0 7303E99500 <1> jc .4th_bit_not_zero 1149 <1> 1150 <1> .4th_bit_zero: 1151 <1> ; State.set_short_rep 1152 000005D5 B8090B <1> mov ax, 9 | (11 << 8) 1153 000005D8 E805FC <1> call State.select 1154 <1> 1155 000005DB 8B4718 <1> mov ax, word [bx + rep0] 1156 000005DE 8B571A <1> mov dx, word [bx + rep0 + 2] 1157 000005E1 E8C9FD <1> call LZ_decoder.peek 1158 000005E4 E80703 <1> call LZ_decoder.put_byte 1159 000005E7 E92BFF <1> jmp .loop 1160 <1> 1161 <1> .3rd_bit_not_zero: 1162 000005EA 1E <1> push ds 1163 000005EB 07 <1> pop es 1164 000005EC 8DBFC000 <1> lea di, [bx + bm_rep1] ; es:di -> bm_rep1 array 1165 <1> %if bit_model_size != 2 1166 <1> %error Assuming word size for bit_model_size 1167 <1> %endif 1168 000005F0 8B4728 <1> mov ax, word [bx + state.st] 1169 000005F3 01C0 <1> add ax, ax ; ax = index is state 1170 <1> ; jc short .error_CY_4 ; (state.st is always < 12) 1171 000005F5 01C7 <1> add di, ax ; es:di -> bm_rep1[state()] 1172 <1> .error_CY_4: 1173 000005F7 7220 <1> jc short .error_CY_4a 1174 000005F9 E861FC <1> call Range_decoder.decode_bit 1175 000005FC 720E <1> jc .3rd_bit_not_zero.4th_bit_not_zero 1176 <1> 1177 <1> .3rd_bit_not_zero.4th_bit_zero: 1178 000005FE FF771E <1> push word [bx + rep1 + 2] 1179 00000601 FF771C <1> push word [bx + rep1] 1180 00000604 8F46FA <1> pop word [bp + ?distance] 1181 00000607 8F46FC <1> pop word [bp + ?distance + 2] 1182 0000060A EB46 <1> jmp .3rd_bit_not_zero.common 1183 <1> 1184 <1> .3rd_bit_not_zero.4th_bit_not_zero: 1185 0000060C 1E <1> push ds 1186 0000060D 07 <1> pop es 1187 0000060E 8DBFD800 <1> lea di, [bx + bm_rep2] ; es:di -> bm_rep2 array 1188 <1> %if bit_model_size != 2 1189 <1> %error Assuming word size for bit_model_size 1190 <1> %endif 1191 00000612 8B4728 <1> mov ax, word [bx + state.st] 1192 00000615 01C0 <1> add ax, ax ; ax = index is state 1193 <1> ; jc short .error_CY_5 ; (state.st is always < 12) 1194 00000617 01C7 <1> add di, ax ; es:di -> bm_rep2[state()] 1195 <1> .error_CY_4a: 1196 00000619 7267 <1> jc short .error_CY_5 1197 0000061B E83FFC <1> call Range_decoder.decode_bit 1198 0000061E 720E <1> jc .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero 1199 <1> 1200 <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_zero: 1201 00000620 FF7722 <1> push word [bx + rep2 + 2] 1202 00000623 FF7720 <1> push word [bx + rep2] 1203 00000626 8F46FA <1> pop word [bp + ?distance] 1204 00000629 8F46FC <1> pop word [bp + ?distance + 2] 1205 0000062C EB18 <1> jmp .3rd_bit_not_zero.4th_bit_not_zero.common 1206 <1> 1207 <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero: 1208 0000062E FF7726 <1> push word [bx + rep3 + 2] 1209 00000631 FF7724 <1> push word [bx + rep3] 1210 00000634 8F46FA <1> pop word [bp + ?distance] 1211 00000637 8F46FC <1> pop word [bp + ?distance + 2] ; distance = rep3 1212 0000063A FF7722 <1> push word [bx + rep2 + 2] 1213 0000063D FF7720 <1> push word [bx + rep2] 1214 00000640 8F4724 <1> pop word [bx + rep3] 1215 00000643 8F4726 <1> pop word [bx + rep3 + 2] ; rep3 = rep2 1216 <1> 1217 <1> .3rd_bit_not_zero.4th_bit_not_zero.common: 1218 00000646 FF771E <1> push word [bx + rep1 + 2] 1219 00000649 FF771C <1> push word [bx + rep1] 1220 0000064C 8F4720 <1> pop word [bx + rep2] 1221 0000064F 8F4722 <1> pop word [bx + rep2 + 2] ; rep2 = rep1 1222 <1> 1223 <1> .3rd_bit_not_zero.common: 1224 00000652 FF771A <1> push word [bx + rep0 + 2] 1225 00000655 FF7718 <1> push word [bx + rep0] 1226 00000658 8F471C <1> pop word [bx + rep1] 1227 0000065B 8F471E <1> pop word [bx + rep1 + 2] ; rep1 = rep0 1228 0000065E FF76FC <1> push word [bp + ?distance + 2] 1229 00000661 FF76FA <1> push word [bp + ?distance] 1230 00000664 8F4718 <1> pop word [bx + rep0] 1231 00000667 8F471A <1> pop word [bx + rep0 + 2] ; rep0 = distance 1232 <1> 1233 <1> .4th_bit_not_zero: 1234 <1> ; State.set_rep 1235 0000066A B8080B <1> mov ax, 8 | (11 << 8) 1236 0000066D E870FB <1> call State.select 1237 <1> 1238 00000670 8B46EE <1> mov ax, word [bp + ?pos_state] ; ax = pos_state variable 1239 00000673 1E <1> push ds 1240 00000674 07 <1> pop es 1241 00000675 8DBFDA36 <1> lea di, [bx + rep_len_model] ; -> len_model to use 1242 00000679 E8D0FC <1> call Range_decoder.decode_len ; dx:ax = length 1243 0000067C 83C002 <1> add ax, min_match_len 1244 0000067F 83D200 <1> adc dx, 0 1245 <1> .error_CY_5: 1246 00000682 7250 <1> jc short .error_CY_6 1247 00000684 8946F6 <1> mov word [bp + ?len], ax 1248 00000687 8956F8 <1> mov word [bp + ?len + 2], dx 1249 0000068A E93001 <1> jmp .handle_match 1250 <1> 1251 <1> .2nd_bit_zero: ; match 1252 0000068D FF7722 <1> push word [bx + rep2 + 2] 1253 00000690 FF7720 <1> push word [bx + rep2] 1254 00000693 8F4724 <1> pop word [bx + rep3] 1255 00000696 8F4726 <1> pop word [bx + rep3 + 2] ; rep3 = rep2 1256 <1> 1257 00000699 FF771E <1> push word [bx + rep1 + 2] 1258 0000069C FF771C <1> push word [bx + rep1] 1259 0000069F 8F4720 <1> pop word [bx + rep2] 1260 000006A2 8F4722 <1> pop word [bx + rep2 + 2] ; rep2 = rep1 1261 <1> 1262 000006A5 FF771A <1> push word [bx + rep0 + 2] 1263 000006A8 FF7718 <1> push word [bx + rep0] 1264 000006AB 8F471C <1> pop word [bx + rep1] 1265 000006AE 8F471E <1> pop word [bx + rep1 + 2] ; rep1 = rep0 1266 <1> 1267 000006B1 8B46EE <1> mov ax, word [bp + ?pos_state] ; ax = pos_state variable 1268 000006B4 1E <1> push ds 1269 000006B5 07 <1> pop es 1270 000006B6 8DBF5634 <1> lea di, [bx + match_len_model] ; -> len_model to use 1271 000006BA E88FFC <1> call Range_decoder.decode_len ; dx:ax = length 1272 <1> 1273 000006BD 8946F0 <1> mov word [bp + ?len_state], ax 1274 000006C0 85D2 <1> test dx, dx 1275 000006C2 7505 <1> jnz @F 1276 000006C4 83F803 <1> cmp ax, len_states - 1 1277 000006C7 7205 <1> jb @FF 1278 <1> @@: 1279 000006C9 C746F00300 <1> mov word [bp + ?len_state], len_states - 1 1280 <1> @@: 1281 <1> 1282 000006CE 83C002 <1> add ax, min_match_len 1283 000006D1 83D200 <1> adc dx, 0 1284 <1> .error_CY_6: 1285 000006D4 723C <1> jc short .error_CY_7 1286 <1> 1287 000006D6 8946F6 <1> mov word [bp + ?len], ax 1288 000006D9 8956F8 <1> mov word [bp + ?len + 2], dx 1289 <1> 1290 000006DC 1E <1> push ds 1291 000006DD 07 <1> pop es 1292 000006DE 8DBF5031 <1> lea di, [bx + bm_dis_slot] ; -> 2D array bm_dis_slot 1293 <1> 1294 000006E2 B88000 <1> mov ax, bit_model_size * (1 << dis_slot_bits) 1295 000006E5 F766F0 <1> mul word [bp + ?len_state] ; first index is len_state 1296 <1> ; bit_model_size = 2 1297 <1> ; 1 << dis_slot_bits = 1 << 6 = 64 1298 <1> ; ?len_state < 4 1299 <1> ; multiplication 2 * 64 * 3 = 384 1300 <1> ; dx:ax = first index into array 1301 000006E8 01C7 <1> add di, ax ; -> 1D array at bm_dis_slot[len_state] 1302 000006EA B90600 <1> mov cx, dis_slot_bits 1303 000006ED E8D2FB <1> call Range_decoder.decode_tree 1304 000006F0 894718 <1> mov word [bx + rep0], ax 1305 000006F3 89571A <1> mov word [bx + rep0 + 2], dx 1306 <1> 1307 000006F6 85D2 <1> test dx, dx ; (same flags as cmp dx, 0) 1308 000006F8 7503 <1> jne @F 1309 000006FA 83F804 <1> cmp ax, start_dis_model 1310 <1> @@: 1311 000006FD 7303E99B00 <1> jnae .not_rep0_ae_start_dis_model 1312 <1> 1313 <1> .rep0_ae_start_dis_model: 1314 00000702 8946F2 <1> mov word [bp + ?dis_slot], ax 1315 00000705 8956F4 <1> mov word [bp + ?dis_slot + 2], dx 1316 <1> 1317 00000708 D1EA <1> shr dx, 1 1318 0000070A D1D8 <1> rcr ax, 1 ; dis_slot >> 1 1319 0000070C 83E801 <1> sub ax, 1 1320 0000070F 83DA00 <1> sbb dx, 0 ; - 1 1321 <1> .error_CY_7: 1322 <1> .error_CY_8: 1323 00000712 7230 <1> jc short .error_CY_9 1324 00000714 F9 <1> stc 1325 00000715 752D <1> jnz short .error_CY_9 1326 00000717 91 <1> xchg cx, ax ; cx = direct_bits, clobber ax 1327 00000718 31D2 <1> xor dx, dx 1328 0000071A B80100 <1> mov ax, 1 1329 0000071D 2246F2 <1> and al, byte [bp + ?dis_slot] 1330 00000720 0C02 <1> or al, 2 1331 00000722 51 <1> push cx 1332 00000723 E306 <1> jcxz @FF 1333 <1> @@: 1334 00000725 D1E0 <1> shl ax, 1 1335 00000727 D1D2 <1> rcl dx, 1 1336 00000729 E2FA <1> loop @B 1337 <1> @@: 1338 0000072B 59 <1> pop cx 1339 0000072C 894718 <1> mov word [bx + rep0], ax 1340 0000072F 89571A <1> mov word [bx + rep0 + 2], dx 1341 <1> 1342 00000732 837EF400 <1> cmp word [bp + ?dis_slot + 2], 0 1343 00000736 7504 <1> jne @F 1344 00000738 837EF20E <1> cmp word [bp + ?dis_slot], end_dis_model 1345 <1> @@: 1346 0000073C 7328 <1> jnb .not_dis_slot_below_end_dis_model 1347 <1> 1348 <1> .dis_slot_below_end_dis_model: 1349 0000073E 2B46F2 <1> sub ax, word [bp + ?dis_slot] 1350 00000741 1B56F4 <1> sbb dx, word [bp + ?dis_slot + 2] 1351 <1> ; dx:ax = index into bm_dis array 1352 <1> ; = rep0 - dis_slot 1353 <1> .error_CY_9: 1354 00000744 722D <1> jc short .error_CY_10 1355 <1> 1356 <1> %if bit_model_size != 2 1357 <1> %error Assuming word size for bit_model_size 1358 <1> %endif 1359 00000746 01C0 <1> add ax, ax 1360 00000748 11D2 <1> adc dx, dx ; dx:ax *= 2 1361 0000074A 7227 <1> jc short .error_CY_10 1362 0000074C F9 <1> stc 1363 0000074D 7524 <1> jnz short .error_CY_10 ; if dx != 0 --> 1364 0000074F 1E <1> push ds 1365 00000750 07 <1> pop es 1366 00000751 8DBF5033 <1> lea di, [bx + bm_dis] ; es:di -> bm_dis array 1367 00000755 01C7 <1> add di, ax ; index into the array 1368 00000757 721A <1> jc short .error_CY_10 1369 00000759 E892FB <1> call Range_decoder.decode_tree_reversed 1370 0000075C 014718 <1> add word [bx + rep0], ax 1371 0000075F 11571A <1> adc word [bx + rep0 + 2], dx 1372 00000762 720F <1> jc short .error_CY_10 1373 00000764 EB37 <1> jmp .after_dis_slot_below 1374 <1> 1375 <1> .not_dis_slot_below_end_dis_model: 1376 00000766 83E904 <1> sub cx, dis_align_bits 1377 00000769 E8BEFA <1> call Range_decoder.decode 1378 0000076C B90400 <1> mov cx, dis_align_bits 1379 <1> @@: 1380 0000076F D1E0 <1> shl ax, 1 1381 00000771 D1D2 <1> rcl dx, 1 1382 <1> .error_CY_10: 1383 00000773 721A <1> jc short .error_CY_11 1384 00000775 E2F8 <1> loop @B 1385 00000777 014718 <1> add word [bx + rep0], ax 1386 0000077A 11571A <1> adc word [bx + rep0 + 2], dx 1387 <1> 1388 0000077D B90400 <1> mov cx, dis_align_bits 1389 00000780 1E <1> push ds 1390 00000781 07 <1> pop es 1391 00000782 8DBF3634 <1> lea di, [bx + bm_align] 1392 00000786 E865FB <1> call Range_decoder.decode_tree_reversed 1393 00000789 014718 <1> add word [bx + rep0], ax 1394 0000078C 11571A <1> adc word [bx + rep0 + 2], dx 1395 <1> .error_CY_11: 1396 0000078F 727D <1> jc .error_CY_12 1397 <1> 1398 00000791 837F1AFF <1> cmp word [bx + rep0 + 2], -1 ; rep0 = 0FFFF_FFFFh ? 1399 00000795 7504 <1> jne @F 1400 00000797 837F18FF <1> cmp word [bx + rep0], -1 1401 <1> @@: 1402 0000079B 7479 <1> je .end_member ; yes, end (marker found) --> 1403 <1> 1404 <1> .after_dis_slot_below: 1405 <1> 1406 <1> .not_rep0_ae_start_dis_model: 1407 <1> 1408 <1> ; State.set_match 1409 0000079D B8070A <1> mov ax, 7 | (10 << 8) 1410 000007A0 E83DFA <1> call State.select 1411 <1> 1412 000007A3 8B571A <1> mov dx, word [bx + rep0 + 2] 1413 000007A6 8B4718 <1> mov ax, word [bx + rep0] 1414 <1> 1415 000007A9 3B5712 <1> cmp dx, word [bx + lz_decoder.dictionary_size + 2] 1416 000007AC 7503 <1> jne @F 1417 000007AE 3B4710 <1> cmp ax, word [bx + lz_decoder.dictionary_size] 1418 <1> @@: 1419 000007B1 7308 <1> jae short .error_AE_1 1420 <1> 1421 <1> ; check for (rep0 >= pos && !pos_wrapped) 1422 <1> ; (pos_wrapped is always false for us) 1423 000007B3 3B5716 <1> cmp dx, word [bx + lz_decoder.pos + 2] 1424 000007B6 7503 <1> jne @F 1425 000007B8 3B4714 <1> cmp ax, word [bx + lz_decoder.pos] 1426 <1> @@: 1427 <1> .error_AE_1: 1428 000007BB 7356 <1> jae short .error_1 1429 <1> 1430 <1> .handle_match: 1431 000007BD 8B571A <1> mov dx, word [bx + rep0 + 2] 1432 000007C0 8B4718 <1> mov ax, word [bx + rep0] 1433 <1> 1434 000007C3 E8FEFB <1> call calculate_peek_pointer_disi 1435 <1> 1436 000007C6 8B46F6 <1> mov ax, word [bp + ?len] 1437 000007C9 8B56F8 <1> mov dx, word [bp + ?len + 2] ; dx:ax = length 1438 <1> 1439 <1> 1440 <1> ; INP: dx:ax = length of match 1441 <1> ; di:si -> source (normalised) 1442 <1> ; ds:bx -> local variables structure 1443 <1> ; ss:bp -> depack stack frame, 1444 <1> ; with ?length_of_destination, ?dst 1445 <1> ; OUT: NC if success, 1446 <1> ; ?length_of_destination and ?dst updated 1447 <1> ; CY if error 1448 <1> ; (destination buffer too small or overlap error) 1449 <1> ; ! may jump to depack.end if ?dst_max_segment reached 1450 <1> ; CHG: ax, cx, dx, di, si, es 1451 <1> ; handle_match: 1452 000007CC 014714 <1> add word [bx + lz_decoder.pos], ax 1453 000007CF 115716 <1> adc word [bx + lz_decoder.pos + 2], dx 1454 000007D2 723A <1> jc short .error_CY_12 ; (CY) --> 1455 <1> 1456 000007D4 2946DE <1> sub word [bp + ?length_of_destination], ax 1457 000007D7 1956E0 <1> sbb word [bp + ?length_of_destination + 2], dx 1458 <1> ; enough space left ? 1459 000007DA 7232 <1> jb short .error_CY_12 ; no --> (below == CY) 1460 <1> 1461 000007DC 1E <1> push ds 1462 <1> 1463 000007DD 8EDF <1> mov ds, di ; ds:si -> source 1464 000007DF C47ED6 <1> les di, [bp + ?dst] ; es:di -> destination 1465 <1> .hm_loop: 1466 000007E2 B9F0FF <1> mov cx, 64 * 1024 - 16 ; block size 1467 <1> ; If both pointers are normalised, moving 0FFF0h bytes is 1468 <1> ; valid and results in a maximum offset of 0FFFFh in either. 1469 <1> 1470 000007E5 85D2 <1> test dx, dx ; >= 1_0000h ? 1471 000007E7 7508 <1> jnz @F ; yes, full block --> 1472 000007E9 85C0 <1> test ax, ax ; == 0 ? 1473 000007EB 7415 <1> jz .hm_end ; yes, done --> 1474 000007ED 39C8 <1> cmp ax, cx ; can move in one (last) block ? 1475 000007EF 7607 <1> jbe .hm_last ; yes --> 1476 <1> @@: 1477 <1> ; no, move one block and continue 1478 000007F1 29C8 <1> sub ax, cx 1479 000007F3 83DA00 <1> sbb dx, 0 ; left over remaining 1480 000007F6 EB03 <1> jmp .hm_copy 1481 <1> 1482 <1> .hm_last: 1483 000007F8 91 <1> xchg cx, ax ; cx = remaining length 1484 000007F9 31C0 <1> xor ax, ax ; no more remaining 1485 <1> 1486 <1> .hm_copy: 1487 000007FB F3A4 <1> rep movsb ; move one block (full or partial) 1488 <1> 1489 000007FD E83D02 <1> call normalise_both_pointers 1490 00000800 EBE0 <1> jmp .hm_loop 1491 <1> 1492 <1> .hm_end: 1493 00000802 897ED6 <1> mov word [bp + ?dst], di 1494 00000805 8C46D8 <1> mov word [bp + ?dst + 2], es 1495 <1> %if _PAYLOAD_KERNEL_MAX_PARAS 1496 <1> mov ax, es 1497 <1> cmp ax, word [bp + ?dst_max_segment] 1498 <1> jae depack.end 1499 <1> ; note that we have the depack stack frame pointed to by 1500 <1> ; ss:bp here, which is needed for running depack.end 1501 <1> %endif 1502 00000808 1F <1> pop ds 1503 <1> %if _ALLOW_OVERLAPPING 1504 00000809 53 <1> push bx 1505 0000080A E81402 <1> call check_pointers_not_overlapping 1506 0000080D 5B <1> pop bx ; returns CF 1507 <1> .error_CY_12: 1508 0000080E 7203 <1> jc short .error_1 1509 <1> %endif 1510 00000810 E902FD <1> jmp .loop 1511 <1> 1512 <1> %if ! _ALLOW_OVERLAPPING 1513 <1> .error_CY_12: 1514 <1> %endif 1515 <1> .error_1: 1516 00000813 E9A000 <1> jmp .error 1517 <1> 1518 <1> 1519 <1> .end_member: ; End Of Stream marker 1520 00000816 837EF800 <1> cmp word [bp + ?len + 2], min_match_len >> 16 1521 0000081A 7504 <1> jne @F 1522 0000081C 837EF602 <1> cmp word [bp + ?len], min_match_len & 0FFFFh 1523 <1> @@: 1524 00000820 75F1 <1> jne short .error_1 1525 <1> 1526 <1> ; decode_member succeeded 1527 <1> 1528 00000822 C55EE6 <1> lds bx, [bp + ?final_dst] ; -> localvariables 1529 <1> 1530 00000825 836EE214 <1> sub word [bp + ?length_of_source], lzip_trailer_size 1531 00000829 835EE400 <1> sbb word [bp + ?length_of_source + 2], 0 1532 0000082D 7303E98400 <1> jc .error 1533 <1> 1534 00000832 C476EA <1> les si, [bp + ?src] ; es:si -> lzip_trailer.uncompressed_checksum 1535 00000835 83C604 <1> add si, 4 ; skip CRC 1536 <1> 1537 <1> ; es:si -> lzip_trailer.uncompressed_size 1538 00000838 26AD <1> es lodsw ; does the destination length match ? 1539 0000083A 3B4714 <1> cmp ax, word [bx + lz_decoder.pos] 1540 0000083D 7577 <1> jne .error 1541 0000083F 26AD <1> es lodsw 1542 00000841 3B4716 <1> cmp ax, word [bx + lz_decoder.pos + 2] 1543 00000844 7570 <1> jne .error ; if no --> 1544 00000846 26AD <1> es lodsw 1545 00000848 85C0 <1> test ax, ax 1546 0000084A 756A <1> jnz .error 1547 0000084C 26AD <1> es lodsw 1548 0000084E 85C0 <1> test ax, ax 1549 00000850 7564 <1> jnz .error 1550 <1> 1551 00000852 830714 <1> add word [bx + lz_decoder.range_decoder + range_decoder.member_pos], lzip_trailer_size 1552 00000855 83570200 <1> adc word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2], 0 1553 00000859 725B <1> jc .error 1554 <1> 1555 <1> ; es:si -> lzip_trailer.member_size 1556 0000085B 26AD <1> es lodsw ; does the source length match ? 1557 0000085D 3B07 <1> cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos] 1558 0000085F 7555 <1> jne .error 1559 00000861 26AD <1> es lodsw 1560 00000863 3B4702 <1> cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2] 1561 00000866 754E <1> jne .error 1562 00000868 26AD <1> es lodsw 1563 0000086A 85C0 <1> test ax, ax 1564 0000086C 7548 <1> jnz .error 1565 0000086E 26AD <1> es lodsw 1566 00000870 85C0 <1> test ax, ax 1567 00000872 7542 <1> jnz .error 1568 <1> 1569 <1> ; es:si -> behind lzip_trailer 1570 00000874 06 <1> push es 1571 00000875 56 <1> push si 1572 00000876 E8D301 <1> call normalise_pointer 1573 00000879 8F46EA <1> pop word [bp + ?src] 1574 0000087C 8F46EC <1> pop word [bp + ?src + 2] 1575 <1> 1576 0000087F E9B7FB <1> jmp .loop_member 1577 <1> 1578 <1> .end: 1579 <1> 1580 <1> .final: 1581 <1> %if _COUNTER && !_PROGRESS 1582 <1> mov al, '%' 1583 <1> call disp_al 1584 <1> %endif 1585 00000882 C47EE6 <1> les di, [bp + ?final_dst] 1586 <1> ; -> destination 1587 00000885 C576DA <1> lds si, [bp + ?original_dst] 1588 <1> ; -> source 1589 00000888 1E <1> push ds 1590 00000889 56 <1> push si 1591 0000088A E81002 <1> call pointer_to_linear ; dx:ax = linear ?original_dst 1592 0000088D 91 <1> xchg cx, ax 1593 0000088E 87DA <1> xchg bx, dx ; bx:cx = linear ?original_dst, clobber dx:ax 1594 00000890 FF76D8 <1> push word [bp + ?dst + 2] 1595 00000893 FF76D6 <1> push word [bp + ?dst] 1596 00000896 E80402 <1> call pointer_to_linear 1597 00000899 29C8 <1> sub ax, cx 1598 0000089B 19DA <1> sbb dx, bx ; = linear dst minus linear original_dst 1599 <1> 1600 0000089D B90400 <1> mov cx, 4 1601 000008A0 83C00F <1> add ax, 15 1602 000008A3 83D200 <1> adc dx, 0 1603 <1> @@: 1604 000008A6 D1EA <1> shr dx, 1 1605 000008A8 D1D8 <1> rcr ax, 1 1606 000008AA E2FA <1> loop @B 1607 000008AC 89C1 <1> mov cx, ax 1608 000008AE 85D2 <1> test dx, dx 1609 <1> d0 mov byte [bp + ?errordata], 84h 1610 000008B0 7504 <1> jnz .error 1611 <1> 1612 000008B2 E8D400 <1> call x_mov_p 1613 <1> 1614 000008B5 A8 <1> db __TEST_IMM8 ; (NC) 1615 <1> .error: 1616 000008B6 F9 <1> stc 1617 <1> 1618 <1> %if _COUNTER 1619 000008B7 9F <1> lahf 1620 000008B8 B00D <1> mov al, 13 1621 000008BA E8CFF8 <1> call disp_al_for_progress 1622 000008BD B00A <1> mov al, 10 1623 000008BF E8CAF8 <1> call disp_al_for_progress 1624 000008C2 9E <1> sahf 1625 <1> %endif 1626 <1> d0 mov bx, word [bp + ?errordata] 1627 000008C3 89EC5D <1> lleave code 1628 000008C6 C3 <1> lret 1629 <1> 1630 <1> 1631 <1> ; INP: ds:bx -> range_decoder structure 1632 <1> ; ss:bp -> depack stack frame 1633 <1> ; OUT: ! If an error occurs, jumps to depack.error 1634 <1> ; If success, 1635 <1> ; al = byte read 1636 <1> ; CHG: - 1637 <1> Range_decoder.get_byte: 1638 000008C7 830701 <1> add word [bx + range_decoder.member_pos], 1 1639 000008CA 83570200 <1> adc word [bx + range_decoder.member_pos + 2], 0 1640 000008CE 72E6 <1> jc short .error 1641 <1> 1642 <1> ; INP: ds:bx -> range_decoder structure 1643 <1> ; ss:bp -> depack stack frame 1644 <1> ; OUT: ! If an error occurs, jumps to depack.error 1645 <1> ; If success, 1646 <1> ; al = value read 1647 <1> ; CHG: - 1648 <1> ; get_byte: 1649 000008D0 1E <1> push ds 1650 000008D1 56 <1> push si 1651 <1> 1652 000008D2 836EE201 <1> sub word [bp + ?length_of_source], 1 1653 000008D6 835EE400 <1> sbb word [bp + ?length_of_source + 2], 0 1654 000008DA 72DA <1> jc short .error 1655 <1> 1656 000008DC C576EA <1> lds si, [bp + ?src] 1657 000008DF AC <1> lodsb 1658 000008E0 1E <1> push ds 1659 000008E1 56 <1> push si 1660 000008E2 E86701 <1> call normalise_pointer 1661 000008E5 8F46EA <1> pop word [bp + ?src] 1662 000008E8 8F46EC <1> pop word [bp + ?src + 2] 1663 000008EB 5E <1> pop si 1664 000008EC 1F <1> pop ds 1665 000008ED C3 <1> retn 1666 <1> 1667 <1> .error: equ depack.error 1668 <1> 1669 <1> 1670 <1> ; INP: ds:bx -> lz_decoder structure 1671 <1> ; al = byte to write to buffer 1672 <1> ; ss:bp -> depack stack frame 1673 <1> ; OUT: ! If an error occurs, jumps to depack.error 1674 <1> ; CHG: cx, dx, ax, di, es 1675 <1> LZ_decoder.put_byte: 1676 000008EE C47ED6 <1> les di, [bp + ?dst] 1677 <1> 1678 000008F1 83471401 <1> add word [bx + lz_decoder.pos], 1 1679 000008F5 83571600 <1> adc word [bx + lz_decoder.pos + 2], 0 1680 000008F9 72BB <1> jc short .error 1681 <1> 1682 000008FB 836EDE01 <1> sub word [bp + ?length_of_destination], 1 1683 000008FF 835EE000 <1> sbb word [bp + ?length_of_destination + 2], 0 1684 00000903 72B1 <1> jb short .error 1685 <1> 1686 00000905 AA <1> stosb 1687 00000906 06 <1> push es 1688 00000907 57 <1> push di 1689 00000908 E84101 <1> call normalise_pointer 1690 0000090B 8F46D6 <1> pop word [bp + ?dst] 1691 0000090E 8F46D8 <1> pop word [bp + ?dst + 2] 1692 <1> 1693 <1> %if _ALLOW_OVERLAPPING 1694 00000911 53 <1> push bx 1695 00000912 E80C01 <1> call check_pointers_not_overlapping 1696 00000915 5B <1> pop bx ; returns CF 1697 00000916 729E <1> jc short .error 1698 <1> %endif 1699 00000918 C3 <1> retn 1700 <1> 1701 <1> .error: equ depack.error 1702 <1> 1703 <1> 1704 <1> ; INP: ds:si = pointer 1705 <1> ; es:di = pointer 1706 <1> ; OUT: ds:si anti normalised 1707 <1> ; es:di anti normalised 1708 <1> anti_normalise_both_pointers: 1709 00000919 1E <1> push ds 1710 0000091A 56 <1> push si 1711 0000091B E80A00 <1> call anti_normalise_pointer 1712 0000091E 5E <1> pop si 1713 0000091F 1F <1> pop ds 1714 <1> 1715 00000920 06 <1> push es 1716 00000921 57 <1> push di 1717 00000922 E80300 <1> call anti_normalise_pointer 1718 00000925 5F <1> pop di 1719 00000926 07 <1> pop es 1720 00000927 C3 <1> retn 1721 <1> 1722 <1> 1723 <1> ; INP: word [ss:sp + 2] = segment 1724 <1> ; word [ss:sp] = offset 1725 <1> ; 1726 <1> ; Note: Does not work correctly with pointers that point to 1727 <1> ; a HMA location. Do not use then! 1728 <1> anti_normalise_pointer: 1729 <1> lframe near, nested 1730 <1> lpar word, segment 1731 <1> lpar word, offset 1732 <1> lpar_return 1733 00000928 5589E5 <1> lenter 1734 0000092B 53 <1> push bx 1735 0000092C 51 <1> push cx 1736 <1> 1737 0000092D 31DB <1> xor bx, bx 1738 0000092F 31C9 <1> xor cx, cx 1739 00000931 FF7606 <1> push word [bp + ?segment] 1740 00000934 FF7604 <1> push word [bp + ?offset] 1741 00000937 E80A00 <1> call anti_normalise_pointer_with_displacement_bxcx 1742 0000093A 8F4604 <1> pop word [bp + ?offset] 1743 0000093D 8F4606 <1> pop word [bp + ?segment] 1744 <1> 1745 00000940 59 <1> pop cx 1746 00000941 5B <1> pop bx 1747 00000942 5D <1> lleave 1748 00000943 C3 <1> lret 1749 <1> 1750 <1> 1751 <1> ; INP: word [ss:sp + 2] = segment 1752 <1> ; word [ss:sp] = offset 1753 <1> ; bx:cx = add/sub displacement 1754 <1> ; OUT: dword [ss:sp] = anti-normalised address 1755 <1> ; 1756 <1> ; An anti-normalised pointer has an offset as high as possible, 1757 <1> ; which is in the range 0FFF0h to 0FFFFh unless the pointed-to 1758 <1> ; location is in the first 64 KiB of memory. 1759 <1> anti_normalise_pointer_with_displacement_bxcx: 1760 <1> lframe near, nested 1761 <1> lpar word, segment 1762 <1> lpar word, offset 1763 <1> lpar_return 1764 00000944 5589E5 <1> lenter 1765 00000947 50 <1> push ax 1766 00000948 52 <1> push dx 1767 <1> 1768 00000949 FF7606 <1> push word [bp + ?segment] 1769 0000094C FF7604 <1> push word [bp + ?offset] 1770 0000094F E84B01 <1> call pointer_to_linear 1771 <1> 1772 00000952 01C8 <1> add ax, cx 1773 00000954 11DA <1> adc dx, bx ; dx:ax += bx:cx 1774 <1> 1775 00000956 83FA01 <1> cmp dx, 1 1776 00000959 7223 <1> jb @F 1777 <1> 1778 0000095B 50 <1> push ax 1779 0000095C 83C8F0 <1> or ax, 0FFF0h 1780 0000095F 894604 <1> mov word [bp + ?offset], ax 1781 00000962 58 <1> pop ax 1782 <1> 1783 00000963 83E8F0 <1> sub ax, 0FFF0h 1784 00000966 83DA00 <1> sbb dx, 0 1785 <1> 1786 <1> %rep 4 1787 <1> shr dx, 1 1788 <1> rcr ax, 1 1789 <1> %endrep 1787 00000969 D1EA <2> shr dx, 1 1788 0000096B D1D8 <2> rcr ax, 1 1787 0000096D D1EA <2> shr dx, 1 1788 0000096F D1D8 <2> rcr ax, 1 1787 00000971 D1EA <2> shr dx, 1 1788 00000973 D1D8 <2> rcr ax, 1 1787 00000975 D1EA <2> shr dx, 1 1788 00000977 D1D8 <2> rcr ax, 1 1790 00000979 894606 <1> mov word [bp + ?segment], ax 1791 <1> 1792 0000097C EB07 <1> jmp .return 1793 <1> 1794 <1> ; dx:ax = 0000:offset 1795 <1> @@: 1796 0000097E 894604 <1> mov word [bp + ?offset], ax 1797 00000981 83660600 <1> and word [bp + ?segment], 0 1798 <1> 1799 <1> .return: 1800 00000985 5A <1> pop dx 1801 00000986 58 <1> pop ax 1802 00000987 5D <1> lleave 1803 00000988 C3 <1> lret 1804 <1> 1805 <1> 1806 <1> ; Move paragraphs 1807 <1> ; 1808 <1> ; INP: ds:si -> source 1809 <1> ; es:di -> destination 1810 <1> ; cx = number of paragraphs 1811 <1> ; CHG: ax, bx, cx, dx 1812 <1> ; OUT: ds:si -> after source (normalised) 1813 <1> ; es:di -> after destination (normalised) 1814 <1> ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 1815 <1> ; Do not provide a wrapped/HMA source or destination! 1816 <1> x_mov_p: 1817 00000989 E8B100 <1> call normalise_both_pointers 1818 0000098C 8CD8 <1> mov ax, ds 1819 0000098E 8CC2 <1> mov dx, es 1820 <1> 1821 00000990 85C9 <1> test cx, cx 1822 00000992 7503E98800 <1> jz .return 1823 <1> 1824 00000997 39D0 <1> cmp ax, dx ; source above destination ? 1825 00000999 7716 <1> ja .up ; yes, move up (forwards) --> 1826 0000099B 7206 <1> jb .check_down 1827 <1> 1828 0000099D 39FE <1> cmp si, di 1829 0000099F 7710 <1> ja .up 1830 000009A1 747C <1> je .return ; pointers are the same, no need to move --> 1831 <1> .check_down: 1832 000009A3 50 <1> push ax 1833 000009A4 01C8 <1> add ax, cx ; (expected not to carry) 1834 000009A6 39D0 <1> cmp ax, dx ; end of source is above destination ? 1835 000009A8 58 <1> pop ax 1836 000009A9 7726 <1> ja .down ; yes, move from top down --> 1837 000009AB 7204 <1> jb .up 1838 000009AD 39FE <1> cmp si, di 1839 000009AF 7720 <1> ja .down 1840 <1> 1841 <1> ; Here, the end of source is below-or-equal the destination, 1842 <1> ; so they do not overlap. In this case we prefer moving up. 1843 <1> .up: 1844 <1> .uploop: 1845 000009B1 81E9FF0F <1> sub cx, 0FFFh ; 64 KiB - 16 B left ? 1846 000009B5 760C <1> jbe .uplast ; no --> 1847 000009B7 51 <1> push cx 1848 000009B8 B9F87F <1> mov cx, 0FFF0h /2 1849 000009BB F3A5 <1> rep movsw ; move 64 KiB - 16 B 1850 000009BD 59 <1> pop cx 1851 000009BE E87C00 <1> call normalise_both_pointers 1852 000009C1 EBEE <1> jmp short .uploop ; proceed for more --> 1853 <1> .uplast: 1854 000009C3 81C1FF0F <1> add cx, 0FFFh ; restore counter 1855 000009C7 D1E1 <1> shl cx, 1 1856 000009C9 D1E1 <1> shl cx, 1 1857 000009CB D1E1 <1> shl cx, 1 ; *8, paragraphs to words 1858 000009CD F3A5 <1> rep movsw ; move last part 1859 000009CF EB4E <1> jmp short .return 1860 <1> 1861 <1> .down: 1862 000009D1 FD <1> std ; _AMD_ERRATUM_109_WORKAROUND as below 1863 <1> 1864 000009D2 89C8 <1> mov ax, cx 1865 000009D4 31DB <1> xor bx, bx 1866 000009D6 51 <1> push cx 1867 000009D7 B90400 <1> mov cx, 4 1868 <1> @@: 1869 000009DA D1E0 <1> shl ax, 1 1870 000009DC D1D3 <1> rcl bx, 1 1871 000009DE E2FA <1> loop @B 1872 000009E0 83E802 <1> sub ax, 2 1873 000009E3 83DB00 <1> sbb bx, 0 ; -> point at last word 1874 <1> ; (Cannot borrow here because we checked that cx 1875 <1> ; was nonzero at the intro to this function, so 1876 <1> ; bx:ax is at least 16 prior to this subtraction.) 1877 000009E6 91 <1> xchg ax, cx ; bx:cx = displacement to point to last word 1878 000009E7 1E <1> push ds 1879 000009E8 56 <1> push si 1880 000009E9 E858FF <1> call anti_normalise_pointer_with_displacement_bxcx 1881 000009EC 5E <1> pop si 1882 000009ED 1F <1> pop ds ; -> last word of source 1883 000009EE 06 <1> push es 1884 000009EF 57 <1> push di 1885 000009F0 E851FF <1> call anti_normalise_pointer_with_displacement_bxcx 1886 000009F3 5F <1> pop di 1887 000009F4 07 <1> pop es ; -> last word of destination 1888 000009F5 59 <1> pop cx 1889 <1> 1890 <1> .dnloop: 1891 000009F6 81E9FF0F <1> sub cx, 0FFFh ; 64 KiB - 16 B left ? 1892 000009FA 760C <1> jbe .dnlast ; no --> 1893 000009FC 51 <1> push cx 1894 000009FD B9F87F <1> mov cx, 0FFF0h /2 1895 00000A00 F3A5 <1> rep movsw ; move 64 KiB - 16 B 1896 00000A02 59 <1> pop cx 1897 00000A03 E813FF <1> call anti_normalise_both_pointers 1898 00000A06 EBEE <1> jmp short .dnloop ; proceed for more --> 1899 <1> .dnlast: 1900 00000A08 81C1FF0F <1> add cx, 0FFFh ; restore counter 1901 00000A0C D1E1 <1> shl cx, 1 1902 00000A0E D1E1 <1> shl cx, 1 1903 00000A10 D1E1 <1> shl cx, 1 ; *8, paragraphs to words 1904 <1> 1905 <1> 1906 <1> numdef AMD_ERRATUM_109_WORKAROUND, 1 1907 <1> %if 0 1908 <1> 1909 <1> Jack R. Ellis pointed out this erratum: 1910 <1> 1911 <1> Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69: 1912 <1> 1913 <1> 109 Certain Reverse REP MOVS May Produce Unpredictable Behavior 1914 <1> 1915 <1> Description 1916 <1> 1917 <1> In certain situations a REP MOVS instruction may lead to 1918 <1> incorrect results. An incorrect address size, data size 1919 <1> or source operand segment may be used or a succeeding 1920 <1> instruction may be skipped. This may occur under the 1921 <1> following conditions: 1922 <1> 1923 <1> * EFLAGS.DF=1 (the string is being moved in the reverse direction). 1924 <1> 1925 <1> * The number of items being moved (RCX) is between 1 and 20. 1926 <1> 1927 <1> * The REP MOVS instruction is preceded by some microcoded instruction 1928 <1> that has not completely retired by the time the REP MOVS begins 1929 <1> execution. The set of such instructions includes BOUND, CLI, LDS, 1930 <1> LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions. 1931 <1> 1932 <1> Potential Effect on System 1933 <1> 1934 <1> Incorrect results may be produced or the system may hang. 1935 <1> 1936 <1> Suggested Workaround 1937 <1> 1938 <1> Contact your AMD representative for information on a BIOS update. 1939 <1> 1940 <1> %endif 1941 <1> 1942 <1> %if _AMD_ERRATUM_109_WORKAROUND 1943 00000A12 E308 <1> jcxz @FF 1944 00000A14 83F914 <1> cmp cx, 20 1945 00000A17 7703 <1> ja @FF 1946 <1> @@: 1947 00000A19 A5 <1> movsw 1948 00000A1A E2FD <1> loop @B 1949 <1> @@: 1950 <1> %endif 1951 00000A1C F3A5 <1> rep movsw ; move first part 1952 00000A1E FC <1> cld 1953 <1> .return: 1954 00000A1F EB1C <1> jmp normalise_both_pointers 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 00000A21 FF76D8 push word [bp + ?dst + 2] 1851 00000A24 FF76D6 push word [bp + ?dst] 1852 %else 1853 push es 1854 push di 1855 %endif 1856 00000A27 E87300 call pointer_to_linear 1857 1858 00000A2A 91 xchg cx, ax 1859 00000A2B 87DA xchg bx, dx ; bx:cx = linear ?dst after write 1860 1861 %if CHECK_POINTERS_VARIABLE_SRC 1862 00000A2D FF76EC push word [bp + ?src + 2] 1863 00000A30 FF76EA push word [bp + ?src] 1864 %else 1865 push ds 1866 push si 1867 %endif 1868 00000A33 E86700 call pointer_to_linear ; dx:ax = linear ?src before next read 1869 1870 00000A36 39DA cmp dx, bx ; ?src >= ?dst ? 1871 00000A38 7502 jne @F 1872 00000A3A 39C8 cmp ax, cx 1873 @@: 1874 ; (CY) if error (src < dst) 1875 ; (NC) if no error 1876 00000A3C 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 00000A3D 06 push es 1892 00000A3E 57 push di 1893 00000A3F E80A00 call normalise_pointer 1894 00000A42 5F pop di 1895 00000A43 07 pop es 1896 %endif 1897 1898 normalise_dssi_pointer: 1899 00000A44 1E push ds 1900 00000A45 56 push si 1901 00000A46 E80300 call normalise_pointer 1902 00000A49 5E pop si 1903 00000A4A 1F pop ds 1904 00000A4B 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 00000A4C 5589E5 lenter 1919 1920 00000A4F 837E040F cmp word [bp + ?offset], 15 1921 00000A53 7617 jbe .ret 1922 1923 00000A55 53 push bx 1924 00000A56 51 push cx 1925 1926 00000A57 31DB xor bx, bx 1927 00000A59 31C9 xor cx, cx 1928 00000A5B FF7606 push word [bp + ?segment] 1929 00000A5E FF7604 push word [bp + ?offset] 1930 00000A61 E80A00 call normalise_pointer_with_displacement_bxcx 1931 00000A64 8F4604 pop word [bp + ?offset] 1932 00000A67 8F4606 pop word [bp + ?segment] 1933 1934 00000A6A 59 pop cx 1935 00000A6B 5B pop bx 1936 .ret: 1937 00000A6C 5D lleave 1938 00000A6D 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 00000A6E 5589E5 lenter 1953 1954 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1955 cmp word [bp + ?offset], 15 1956 jbe .ret 1957 %endif 1958 1959 00000A71 50 push ax 1960 00000A72 51 push cx 1961 00000A73 52 push dx 1962 1963 00000A74 FF7606 push word [bp + ?segment] 1964 00000A77 FF7604 push word [bp + ?offset] 1965 00000A7A 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 00000A7D 01C1 add cx, ax 1975 00000A7F 11DA adc dx, bx ; dx:cx = dx:ax + bx:cx 1976 ; pop bx 1977 00000A81 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 00000A82 53 push bx 1997 00000A83 89CB mov bx, cx 1998 00000A85 83E10F and cx, 15 1999 00000A88 894E04 mov word [bp + ?offset], cx 2000 2001 00000A8B B104 mov cl, 4 2002 @@: 2003 00000A8D D1EA shr dx, 1 2004 00000A8F D1DB rcr bx, 1 2005 00000A91 E2FA loop @B 2006 2007 00000A93 895E06 mov word [bp + ?segment], bx 2008 00000A96 5B pop bx 2009 2010 ; test dx, dx 2011 ; jnz .error 2012 2013 .return: 2014 2015 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2016 00000A97 9E sahf ; restore flags from ah 2017 %endif 2018 00000A98 5A pop dx 2019 00000A99 59 pop cx 2020 00000A9A 58 pop ax 2021 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2022 .ret: 2023 %endif 2024 00000A9B 5D lleave 2025 00000A9C 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 00000A9D 5589E5 lenter 2036 2037 00000AA0 8B4606 mov ax, word [bp + ?segment] 2038 00000AA3 31D2 xor dx, dx 2039 00000AA5 51 push cx 2040 00000AA6 B90400 mov cx, 4 2041 @@: 2042 00000AA9 D1E0 shl ax, 1 2043 00000AAB D1D2 rcl dx, 1 2044 00000AAD E2FA loop @B 2045 2046 00000AAF 034604 add ax, word [bp + ?offset] 2047 00000AB2 11CA adc dx, cx ; cx = 0 here 2048 00000AB4 59 pop cx 2049 2050 00000AB5 5D lleave 2051 00000AB6 C20400 lret 2052 2053 2054 %if _PASSLCFG 2055 align 16 2056 transfer_lcfg_block: 2057 times lcfg.size nop 2058 %endif 2059 00000AB9 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 .error_stderr: db "Error: Not enough memory allocated.",13,10 2071 .error_stderr.length: equ $ - .error_stderr 2072 .error_c_stdout: 2073 .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 db 13,10 2082 .error_c_stdout.length: equ $ - .error_c_stdout 2083 .error_stdout.length: equ $ - .error_stdout 2084 2085 align 1024 2086 %if ($ - $$) != 1024 2087 %error Wrong INIT0 size 2088 %endif 2089 %endif 2090 2091 000000D2 90 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: inilz: 2976 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 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 lenter 2162 2163 %if _RELOAD_FILE && _RELOAD_XMS 2164 or word [bp + ?xmshandle], -1 2165 %endif 2166 2167 mov dx, word [bp + ?repetitions] 2168 cmp dx, -1 2169 jne @F 2170 2171 .cmdline_error: 2172 %if _DEBUG0 2173 mov bx, -1 2174 %endif 2175 mov dx, init2_msg.cmdline_error 2176 mov cx, init2_msg.cmdline_error.length 2177 jmp init2_error 2178 2179 2180 @@: 2181 testopt [bp + ?whichtest], 4000h 2182 jnz .a_or_c 2183 testopt [bp + ?whichtest], 8000h 2184 jz .a_or_c 2185 .b: 2186 test dx, dx 2187 jz .cmdline_error 2188 jmp @F 2189 2190 .a_or_c: 2191 test dx, dx 2192 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 mov dx, cs 2253 add dx, (init2_end - init2_start) >> 4 2254 ; => payload saving area 2255 mov ax, cs 2256 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2259 mov cx, (payload_end - payload) >> 4 2260 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 mov dx, ax ; dx => payload source to use 2267 mov ax, cs 2268 sub ax, (init1_end - init1_start) >> 4 2269 ; ax => INIT1 2270 mov bx, 1 ; say we're in EXE mode 2271 push dx 2272 push ax 2273 push si ; si => target 2274 push cs 2275 call .transfer ; call decompression 2276 pop si 2277 pop ax 2278 pop dx 2279 ; Returns here after decompression. 2280 ; CY if error. 2281 jnc @F 2282 2283 mov dx, init2_msg.initial_error 2284 mov cx, init2_msg.initial_error.length 2285 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 call checkdecompressed 2295 je @F 2296 2297 %if _WRITE_WRONG_FILE 2298 call writefiles 2299 %endif 2300 2301 %if _DEBUG0 2302 mov bx, -1 2303 %endif 2304 mov dx, init2_msg.initial_error_2 2305 mov cx, init2_msg.initial_error_2.length 2306 jmp init2_error_free 2307 2308 @@: 2309 %endif 2310 2311 testopt [bp + ?whichtest], 4000h 2312 jz @F 2313 mov ax, cs 2314 sub ax, (init1_end - init1_start) >> 4 2315 ; ax => INIT1 2316 mov es, ax 2317 mov ax, word [es:init1_c_mode_counter] 2318 call init2_disp_ax_dec 2319 mov al, 13 2320 call init2_disp_al 2321 mov al, 10 2322 call init2_disp_al 2323 %if _RELOAD_XMS 2324 call freexms 2325 %endif 2326 mov ax, 4C00h 2327 int 21h 2328 2329 @@: 2330 lvar word, upperbound 2331 push dx 2332 lvar word, lowerbound 2333 push si 2334 lvar word, current_init1 2335 push ax 2336 2337 %if _TEST_PROGRESS 2338 mov dx, init2_msg.progress.1 2339 mov cx, init2_msg.progress.1.length 2340 .loop: 2341 push cs 2342 pop ds 2343 mov bx, 2 2344 mov ah, 40h 2345 int 21h 2346 %else 2347 .loop: 2348 %endif 2349 2350 mov dx, [bp + ?upperbound] 2351 2352 testopt [bp + ?whichtest], 8000h 2353 jz @F 2354 2355 dec word [bp + ?repetitions] 2356 jnz .test_b_skip_bound 2357 2358 %if _TEST_PROGRESS 2359 push cs 2360 pop ds 2361 mov dx, init2_msg.progress.linebreak 2362 mov cx, init2_msg.progress.linebreak.length 2363 mov bx, 2 2364 mov ah, 40h 2365 int 21h 2366 %endif 2367 %if _RELOAD_XMS 2368 call freexms 2369 %endif 2370 mov ax, 4C00h 2371 int 21h 2372 2373 2374 @@: 2375 sub dx, [bp + ?lowerbound] 2376 jz .found 2377 shr dx, 1 2378 ; Rounding down, so that we never retry upper bound. 2379 ; The upper bound is known to be working. 2380 add dx, [bp + ?lowerbound] 2381 2382 .test_b_skip_bound: 2383 push dx 2384 add dx, (payload_end - payload) >> 4 2385 mov ax, [bp + ?current_init1] 2386 mov cx, (init1_end - init1_start) >> 4 2387 call init2_movp 2388 mov [bp + ?current_init1], dx 2389 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 mov ax, cs 2456 add ax, (init2_end - init2_start) >> 4 2457 ; => payload in saving area 2458 mov cx, (payload_end - payload) >> 4 2459 call init2_movp ; copy payload from payload saving area 2460 %endif 2461 ; dx => source 2462 mov ax, [bp + ?current_init1] 2463 mov bx, 1 2464 push dx 2465 push si 2466 push cs 2467 call .transfer 2468 pop si 2469 pop dx 2470 ; Returns here after decompression. 2471 ; CY if error. 2472 jnc @F 2473 2474 testopt [bp + ?whichtest], 8000h 2475 jnz .test_b_fail 2476 2477 ; error: this attempt is one below the new lower bound 2478 inc dx 2479 mov word [bp + ?lowerbound], dx 2480 2481 %if _TEST_PROGRESS 2482 mov dx, init2_msg.progress.fail 2483 mov cx, init2_msg.progress.fail.length 2484 %endif 2485 jmp .loop 2486 2487 @@: 2488 %if _INCLUDE_UNCOMPRESSED 2489 call checkdecompressed 2490 je @F 2491 2492 %if _WRITE_WRONG_FILE 2493 call writefiles 2494 %endif 2495 2496 .test_b_fail: 2497 %if _TEST_PROGRESS 2498 push cs 2499 pop ds 2500 mov dx, init2_msg.progress.linebreak 2501 mov cx, init2_msg.progress.linebreak.length 2502 mov bx, 2 2503 mov ah, 40h 2504 int 21h 2505 %endif 2506 %if _DEBUG0 2507 mov bx, -2 2508 %endif 2509 mov dx, init2_msg.subsequent_error_2 2510 mov cx, init2_msg.subsequent_error_2.length 2511 jmp init2_error_free 2512 2513 @@: 2514 %endif 2515 ; success: this attempt is the new upper bound 2516 mov word [bp + ?upperbound], dx 2517 %if _TEST_PROGRESS 2518 mov dx, init2_msg.progress.success 2519 mov cx, init2_msg.progress.success.length 2520 %endif 2521 jmp .loop 2522 2523 .found: 2524 %if _TEST_PROGRESS 2525 push cs 2526 pop ds 2527 mov dx, init2_msg.progress.linebreak 2528 mov cx, init2_msg.progress.linebreak.length 2529 mov bx, 2 2530 mov ah, 40h 2531 int 21h 2532 %endif 2533 mov ax, word [bp + ?upperbound] 2534 sub ax, si ; = how many paragraphs in buffer before source 2535 add ax, paras( (init1_end - init1_start) + (payload_end - payload) ) 2537 ; = how many paragraphs needed for process 2538 call init2_disp_ax_dec 2539 mov al, 13 2540 call init2_disp_al 2541 mov al, 10 2542 call init2_disp_al 2543 %if _RELOAD_XMS 2544 call freexms 2545 %endif 2546 mov ax, 4C00h 2547 int 21h 2548 2549 2550 .transfer: 2551 xor di, di 2552 push di ; placeholder ax value on stack 2553 push ax ; INIT1 segment 2554 push di ; zero = init1_start 2555 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 push ax 2726 push dx 2727 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 mov cx, payload_uncompressed_size >> 4 2734 mov bx, payload_uncompressed_size & 15 2735 %endif 2736 mov di, cs 2737 add di, (payload_uncompressed - init2_start) >> 4 2738 jcxz .end 2739 .loop: 2740 push cx 2741 mov cx, 8 2742 mov ds, si 2743 mov es, di 2744 inc si 2745 inc di 2746 push si 2747 push di 2748 xor si, si 2749 xor di, di 2750 repe cmpsw 2751 pop di 2752 pop si 2753 pop cx 2754 jne .ret 2755 loop .loop 2756 .end: 2757 mov ds, si 2758 mov es, di 2759 xor si, si 2760 xor di, di ; (ZR) 2761 mov cx, bx 2762 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 pop si 2800 pop dx 2801 pop ax 2802 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 push cs 2890 pop ds 2891 mov bx, 2 2892 mov ah, 40h 2893 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 testopt [bp + ?whichtest], 4000h 2911 jz @F 2912 mov dx, init2_msg.error_c_stdout 2913 mov cx, init2_msg.error_c_stdout.length 2914 jmp @FF 2915 @@: 2916 testopt [bp + ?whichtest], 8000h 2917 jnz @FF 2918 mov dx, init2_msg.error_stdout 2919 mov cx, init2_msg.error_stdout.length 2920 @@: 2921 mov bx, 1 2922 mov ah, 40h 2923 int 21h 2924 @@: 2925 mov ax, 4CFFh 2926 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 push dx 2982 push ax 2983 mov dl, al 2984 mov ah, 2 2985 int 21h 2986 pop ax 2987 pop dx 2988 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 push bx 2998 xor bx, bx 2999 .pushax: 3000 push dx 3001 push ax 3002 or bl, bl 3003 jz .nobl 3004 sub bl, 5 3005 neg bl 3006 .nobl: 3007 push cx 3008 mov cx, 10000 3009 call .divide_out 3010 mov cx, 1000 3011 call .divide_out 3012 mov cx, 100 3013 call .divide_out 3014 mov cl, 10 3015 call .divide_out 3016 ; (Divisor 1 is useless) 3017 add al, '0' 3018 call init2_disp_al 3019 pop cx 3020 pop ax 3021 pop dx 3022 pop bx ; Caller's register 3023 retn 3024 3025 3026 ; INP: ax = number 3027 ; cx = divisor 3028 ; OUT: ax = remainder of operation 3029 ; result displayed 3030 .divide_out: 3031 push dx 3032 xor dx, dx 3033 div cx ; 0:ax / cx 3034 push dx ; remainder 3035 dec bl 3036 jnz .nobl2 3037 or bh, 1 3038 .nobl2: 3039 or bh, al 3040 jz .leadingzero 3041 add al, '0' 3042 call init2_disp_al ; display result 3043 .leadingzero: 3044 pop ax ; remainder 3045 pop dx 3046 retn 3047 3048 3049 init2_msg: 3050 %if _TEST_PROGRESS 3051 .progress.1: db "Info: 1" 3052 .progress.1.length: equ $ - .progress.1 3053 .progress.fail: db "F" 3054 .progress.fail.length: equ $ - .progress.fail 3055 .progress.success: db "S" 3056 .progress.success.length: equ $ - .progress.success 3057 .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 .initial_error: db "Error: Test program failed to decompress with full buffer." 3065 .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 .initial_error_2: db "Error: Test program decompressed wrongly with full buffer.",13,10 3074 .initial_error_2.length: equ $ - .initial_error_2 3075 .subsequent_error_2: db "Error: Test program decompressed wrongly during test.",13,10 3076 .subsequent_error_2.length: equ $ - .subsequent_error_2 3077 %endif 3078 .cmdline_error: db "Error: Invalid command line input.",13,10 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 .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 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 push cx 3114 push ds 3115 push si 3116 push es 3117 push di 3118 3119 cmp ax, dx ; source above destination ? 3120 ja .up ; yes, move up (forwards) --> 3121 je .return ; same, no need to move --> 3122 push ax 3123 add ax, cx ; (expected not to carry) 3124 cmp ax, dx ; end of source is above destination ? 3125 pop ax 3126 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 push ax 3132 push dx 3133 .uploop: 3134 mov ds, ax 3135 mov es, dx 3136 xor di, di 3137 xor si, si ; -> start of segment 3138 sub cx, 1000h ; 64 KiB left ? 3139 jbe .uplast ; no --> 3140 push cx 3141 mov cx, 10000h /2 3142 rep movsw ; move 64 KiB 3143 pop cx 3144 add ax, 1000h 3145 add dx, 1000h ; -> next segment 3146 jmp short .uploop ; proceed for more --> 3147 .uplast: 3148 add cx, 1000h ; restore counter 3149 shl cx, 1 3150 shl cx, 1 3151 shl cx, 1 ; *8, paragraphs to words 3152 rep movsw ; move last part 3153 pop dx 3154 pop ax 3155 jmp short .return 3156 3157 .down: 3158 std ; _AMD_ERRATUM_109_WORKAROUND as below 3159 .dnloop: 3160 sub cx, 1000h ; 64 KiB left ? 3161 jbe .dnlast ; no --> 3162 push ax 3163 push dx 3164 add ax, cx 3165 add dx, cx 3166 mov ds, ax ; -> 64 KiB not yet moved 3167 mov es, dx 3168 pop dx 3169 pop ax 3170 mov di, -2 3171 mov si, di ; moved from last word down 3172 push cx 3173 mov cx, 10000h /2 3174 rep movsw ; move 64 KiB 3175 pop cx 3176 jmp short .dnloop ; proceed for more --> 3177 .dnlast: 3178 add cx, 1000h ; restore counter 3179 shl cx, 1 3180 shl cx, 1 3181 shl cx, 1 ; *8, paragraphs to words 3182 mov di, cx 3183 dec di 3184 shl di, 1 ; words to offset, -> last word 3185 mov si, di 3186 mov ds, ax 3187 mov es, dx ; first segment correct 3188 3189 ; Refer to comment in init0_movp. 3190 %if _AMD_ERRATUM_109_WORKAROUND 3191 jcxz @FF 3192 cmp cx, 20 3193 ja @FF 3194 @@: 3195 movsw 3196 loop @B 3197 @@: 3198 %endif 3199 rep movsw ; move first part 3200 cld 3201 .return: 3202 pop di 3203 pop es 3204 pop si 3205 pop ds 3206 pop cx 3207 retn 3208 3209 3210 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 align 16 3223 3224 %if _INCLUDE_UNCOMPRESSED && _INCLUDE_UNCOMPRESSED_IN_IMAGE 3225 strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN" 3226 payload_uncompressed: 3227 incbin _UNCOMPRESSED_FILE 3228 .end: 3229 db 38 3230 align 16, db 38 3231 %endif 3232 init2_end: 3233 %endif 3234