1 2 %if 0 3 4 lDOS iniload packed payload 5 by E. C. Masloch, 2018-2020 6 7 Usage of the works is permitted provided that this 8 instrument is retained with the works, so that any entity 9 that uses the works is notified of this instrument. 10 11 DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY. 12 13 14 Includes one of several depackers, some of which are under 15 separate usage conditions. Refer to the individual depacker 16 source files for the applicable usage conditions. 17 18 %endif 19 20 %include "lmacros3.mac" 1 <1> [list -] 14 <2> [list -] 14 <1> [list -] 21 22 struc LOADSTACKVARS, -10h 23 FFFFFFF0 ???????? lsvFirstCluster: resd 1 24 FFFFFFF4 ???????? lsvFATSector: resd 1 25 FFFFFFF8 ???? lsvFATSeg: resw 1 26 FFFFFFFA ???? lsvLoadSeg: resw 1 27 FFFFFFFC ???????? lsvDataStart: resd 1 28 endstruc 29 30 struc LOADDATA, LOADSTACKVARS - 10h 31 FFFFFFE0 ???? ldMemoryTop: resw 1 32 FFFFFFE2 ???? ldLoadTop: resw 1 33 FFFFFFE4 ???? ldSectorSeg: resw 1 34 FFFFFFE6 ?? ldFATType: resb 1 35 FFFFFFE7 ?? ldHasLBA: resb 1 36 FFFFFFE8 ???? ldClusterSize: resw 1 37 FFFFFFEA ???? ldParaPerSector:resw 1 38 FFFFFFEC ???? ldLoadingSeg: resw 1 39 FFFFFFEE ???? ldLoadUntilSeg: resw 1 40 endstruc 41 42 43 %ifndef _MAP 44 %elifempty _MAP 45 %else ; defined non-empty, str or non-str 46 [map all _MAP] 47 %endif 48 49 defaulting 50 51 numdef DEBUG0 ; use errordata to generate an error code 52 numdef DEBUG1 ; dump_stack_frame after an error occurred 53 numdef DEBUG2 ; dump_stack_frame before blz_depack_safe call 54 numdef DEBUG3 ; dump_stack_frame at start of blz_depack_safe 55 56 numdef OPTIMISE_INPUT_SMALL, 0 57 numdef OPTIMISE_OUYPUT_SMALL, 0 58 numdef ALLOW_OVERLAPPING, 1 ; allow overlapping src and dst 59 numdef TEST_PROGRAM, 0 60 numdef TEST_PROGRAM_DECOMPRESSED_SIZE, 0,0 61 %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE 62 %error Test program has to learn of decompressed size. 63 %endif 64 numdef TEST_PROGRESS, 0 65 66 numdef INCLUDE_UNCOMPRESSED 67 numdef INCLUDE_UNCOMPRESSED_IN_IMAGE, 1 68 numdef WRITE_WRONG_FILE 69 numdef RELOAD_XMS, 0 70 numdef RELOAD_FILE, 0 71 72 numdef EXEC_OFFSET, 0 73 numdef EXEC_SEGMENT, 0 74 numdef IMAGE_EXE, 0 75 %if ! _IMAGE_EXE && _TEST_PROGRAM 76 %error Test program can only be used as EXE. 77 %endif 78 numdef IMAGE_EXE_CS, -16 ; relative-segment for CS 79 numdef IMAGE_EXE_IP, 256 +64 ; value for IP 80 ; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0. 81 numdef IMAGE_EXE_SS, -16 ; relative-segment for SS 82 numdef IMAGE_EXE_SP, 0FFFEh ; value for SP (0 underflows) 83 numdef IMAGE_EXE_AUTO_STACK, 0, 2048 ; use stack behind image 84 ; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of 85 ; the same name. This one is only used as a flag; if non-zero, 86 ; keep the stack given to us by iniload; if zero, set up the 87 ; stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP. 88 numdef IMAGE_EXE_GET_COM_STACK, 0 89 ; set up stack for flat .COM style entry 90 numdef DEVICE, 0 91 gendef DEVICE_NAME, "" 92 numdef DEVICE_ATTRIBUTE, 8000h 93 numdef DEVICE_ZERO_ENTRYPOINT, 0 94 numdef BOOTLDR, 1 ; support boot loaded entrypoint 95 96 numdef BRIEFLZ, 0 97 numdef LZ4, 0 98 numdef SNAPPY, 0 99 numdef EXODECR, 0 100 numdef X, 0 101 numdef HEATSHRINK, 0 102 numdef LZD, 0 103 numdef LZO, 0 104 numdef LZSA2, 0 105 numdef APL, 0 106 numdef BZP, 0 107 numdef ZEROCOMP, 0 108 numdef MVCOMP, 0 109 numdef LZEXEDAT, 0 110 %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK + !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP + !!_ZEROCOMP + !!_MVCOMP + !!_LZEXEDAT) != 1 113 %fatal Exactly one compression method must be selected. 114 %endif 115 %assign ADDITIONAL_MEMORY 0 116 %if _BRIEFLZ 117 strdef PAYLOAD_FILE, "lDOSLOAD.BLZ" 118 %elif _LZ4 119 strdef PAYLOAD_FILE, "lDOSLOAD.LZ4" 120 %elif _SNAPPY 121 strdef PAYLOAD_FILE, "lDOSLOAD.SZ" 122 %elif _EXODECR 123 strdef PAYLOAD_FILE, "lDOSLOAD.EXO" 124 %elif _X 125 strdef PAYLOAD_FILE, "lDOSLOAD.X" 126 %elif _HEATSHRINK 127 strdef PAYLOAD_FILE, "lDOSLOAD.HS" 128 %elif _LZD 129 strdef PAYLOAD_FILE, "lDOSLOAD.LZ" 130 %elif _LZO 131 strdef PAYLOAD_FILE, "lDOSLOAD.LZO" 132 %elif _LZSA2 133 strdef PAYLOAD_FILE, "lDOSLOAD.SA2" 134 %elif _APL 135 strdef PAYLOAD_FILE, "lDOSLOAD.APL" 136 %elif _BZP 137 strdef PAYLOAD_FILE, "lDOSLOAD.BZP" 138 %elif _ZEROCOMP 139 strdef PAYLOAD_FILE, "lDOSLOAD.ZER" 140 %elif _MVCOMP 141 strdef PAYLOAD_FILE, "lDOSLOAD.MV" 142 %elif _LZEXEDAT 143 strdef PAYLOAD_FILE, "lDOSLOAD.LZE" 144 %endif 145 numdef PAYLOAD_KERNEL_MAX_PARAS, 0, 0 146 %if _PAYLOAD_KERNEL_MAX_PARAS && ! (_IMAGE_EXE || _DEVICE) 147 %error Kernel mode max paras requires building dual-mode or triple-mode executable 148 %endif 149 numdef COUNTER, 0, 32 150 %if (_COUNTER - 1) & _COUNTER 151 %error COUNTER must be a power of two 152 %endif 153 numdef PROGRESS, 0, 1 154 numdef PROGRESSAMOUNT, 0, 0 155 numdef PROGRESSMULTI, 1 156 numdef PROGRESSVAR, 1 157 numdef PROGRESSVARNAME, "" 158 numdef PROGRESSDEFAULT, 0 159 numdef PROGRESSDEFAULTAPP, _PROGRESSDEFAULT 160 numdef PROGRESSDEFAULTDEVICE, _PROGRESSDEFAULT 161 numdef PROGRESSDEFAULTBOOT,1 162 numdef PASSLCFG, 0 163 numdef LCFG, (_PROGRESS && _PROGRESSMULTI) || _PASSLCFG 164 165 166 %define MODULE inicomp 167 strdef INILOAD_CFG, "" 168 %ifnidn _INILOAD_CFG, "" 169 %include _INILOAD_CFG 1 <1> ; File auto-generated, do not edit. 2 <1> strdef INILOAD_SIGNATURE, "FD" 3 <1> %assign _DEVICE 0 4 <1> %ifidni MODULE, fdkernpl 5 <1> %define _PAYLOAD_FILE "kernel.sys" 6 <1> %endif 7 <1> %ifn _TEST_PROGRAM 8 <1> numdef IMAGE_EXE, 0 9 <1> numdef SECOND_PAYLOAD_EXE, 0 10 <1> %endif 170 %endif 171 strdef LCFG_CFG, "" 172 173 %if _DEVICE 174 %ifidn _DEVICE_NAME, "" 175 %error Device name must be set 176 %endif 177 %endif 178 179 struc XMSM 180 00000000 ???????? .size_: resd 1 181 00000004 ???? .srchdl: resw 1 182 00000006 ???????? .srcadr: resd 1 183 0000000A ???? .dsthdl: resw 1 184 0000000C ???????? .dstadr: resd 1 185 endstruc 186 187 188 cpu 8086 189 addsection INIT0, start=0 vstart=0 190 init0_start: 191 %if _DEVICE 192 ; The device header is of a fixed format. 193 ; For our purposes, the 4-byte code for 194 ; each the strategy entry and the 195 ; interrupt entry is part of this format. 196 ; (DOS may read the attributes or entrypoint 197 ; offsets before calling either, so in the inicomp 198 ; stage we need to recreate in the entrypoints part 199 ; exactly what the application has here.) 200 ; _PASSLCFG: The lCFG block is passed in the dword 201 ; behind the interrupt entry. 202 device_header: 203 .next: 204 %if _DEVICE_ZERO_ENTRYPOINT 205 fill 2, -1, jmp strict short j_zero_entrypoint 206 dw -1 207 %else 208 dd -1 ; link to next device 209 %endif 210 .attributes: 211 dw _DEVICE_ATTRIBUTE ; attributes 212 .strategy: 213 dw .strategy_entry ; -> strategy entry 214 .interrupt: 215 dw .interrupt_entry ; -> interrupt entry 216 .name: 217 fill 8, 32, db _DEVICE_NAME ; character device name, 218 ; or block device number of units 219 ; + optional name 220 .strategy_entry: 221 fill 4, 90h, jmp device_entrypoint 222 .interrupt_entry: 223 fill 4, 90h, retf 224 .pass_lcfg: 225 %endif 226 227 228 %if _IMAGE_EXE || _DEVICE 229 00000000 90 nop 230 00000001 90 align 32, nop 231 init0_kernel_entry: 232 ; cs:ip = load seg : 32 here 233 %if ($ - $$) != 32 234 %error Wrong kernel mode entrypoint 235 %endif 236 %if _TEST_PROGRAM 237 @@: 238 00000020 CC int3 239 00000021 FB sti 240 00000022 F4 hlt 241 00000023 EBFB jmp @B 242 %endif 243 %if _BOOTLDR 244 %if ! _IMAGE_EXE 245 j_zero_entrypoint: 246 %endif 247 00000025 31DB xor bx, bx ; 0 = kernel mode 248 00000027 50 push ax 249 00000028 8CC8 mov ax, cs 250 0000002A 83C040 add ax, (init0_end - init0_start) >> 4 251 0000002D 8B56E2 mov dx, word [ bp + ldLoadTop ] ; => after end of available space 252 00000030 BE6000 mov si, 60h ; => destination 253 00000033 EB7E jmp init0_common 254 %endif 255 256 %if _IMAGE_EXE 257 00000035 90 align 64, nop 258 j_zero_entrypoint: 259 init0_exe_entry: 260 ; NOTE: This part is called with ip = 256 + 64, cs = PSP. 261 %if ($ - $$) != 64 262 %error Wrong EXE mode entrypoint 263 %endif 264 %if _IMAGE_EXE_GET_COM_STACK 265 mov bx, ds ; => PSP 266 dec bx ; => MCB 267 mov ds, bx 268 add bx, word [3] ; add size of memory block 269 sub bx, -1 + paras(512) ; add one, then subtract enough paragraphs 270 cli 271 mov ss, bx 272 mov sp, 512 ; -> new stack 273 sti 274 %endif 275 00000040 BB0100 mov bx, 1 ; EXE mode 276 00000043 50 push ax 277 %if _TEST_PROGRAM 278 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 279 push ds 280 mov ax, word [2Ch] ; => environment 281 test ax, ax 282 jnz @F 283 .errorfile: 284 jmp init0_error_file 285 @@: 286 mov ds, ax 287 mov cx, 8000h 288 xor si, si ; -> environment 289 @@: 290 lodsb 291 test al, al 292 loopnz @B ; si -> past one NUL 293 jcxz .errorfile 294 cmp byte [si], 0 ; -> another NUL ? 295 loopne @B ; no, skip next variable --> 296 jcxz .errorfile 297 inc si ; skip double NUL 298 lodsw ; load amount strings after environment 299 cmp ax, 1 ; 1 ? 300 jne .errorfile ; no --> 301 mov dx, si ; ds:dx -> executable pathname 302 mov ax, 3D00h + 0_010_0_000b ; deny write, read only 303 int 21h ; open 304 jc .errorfile 305 pop ds ; restore => PSP 306 push ax ; push into ?handle 307 %endif 308 309 00000044 BE8100 mov si, 81h 310 00000047 31D2 xor dx, dx 311 00000049 31C0 xor ax, ax 312 cmdline: 313 .: 314 0000004B AC lodsb 315 0000004C 3C09 cmp al, 9 316 0000004E 74FB je . 317 00000050 3C20 cmp al, 32 318 00000052 74F7 je . 319 00000054 3C0D cmp al, 13 320 00000056 744E je .end 321 00000058 3C30 cmp al, '0' 322 0000005A 721E jb .notdigit 323 0000005C 3C39 cmp al, '9' 324 0000005E 771A ja .notdigit 325 .digit: 326 00000060 2C30 sub al, '0' 327 00000062 89D1 mov cx, dx ; times 1 328 00000064 01D2 add dx, dx 329 00000066 722A jc .invalid 330 00000068 01D2 add dx, dx ; times 4 331 0000006A 7226 jc .invalid 332 0000006C 01CA add dx, cx ; times 5 333 0000006E 7222 jc .invalid 334 00000070 01D2 add dx, dx ; times 10 335 00000072 721E jc .invalid 336 00000074 01C2 add dx, ax ; add in low digit 337 00000076 721A jc .invalid 338 00000078 EBD1 jmp . 339 340 .notdigit: 341 0000007A 3C41 cmp al, 'A' 342 0000007C 7419 je .a 343 0000007E 3C61 cmp al, 'a' 344 00000080 7415 je .a 345 00000082 3C42 cmp al, 'B' 346 00000084 7416 je .b 347 00000086 3C62 cmp al, 'b' 348 00000088 7412 je .b 349 0000008A 3C43 cmp al, 'C' 350 0000008C 7413 je .c 351 0000008E 3C63 cmp al, 'c' 352 00000090 740F je .c 353 .invalid: 354 00000092 BAFFFF mov dx, -1 ; invalid 355 00000095 EB0F jmp .end 356 357 .a: 358 00000097 80E77F and bh, ~ 80h ; A mode. determine min alloc size 359 0000009A EBAF jmp . 360 361 .b: 362 0000009C 80CF80 or bh, 80h ; B mode. repeat depack, counter in command line 363 0000009F EBAA jmp . 364 365 .c: 366 000000A1 80CF40 or bh, 40h ; C mode. how often would the counter be called 367 000000A4 EBA5 jmp . 368 369 .end: 370 ; bx for ?whichtest 371 000000A6 52 push dx ; for ?repetitions 372 %endif 373 000000A7 8CD2 mov dx, ss ; => after end of available space 374 000000A9 8CC8 mov ax, cs 375 000000AB 83C050 add ax, (256 + (init0_end - init0_start)) >> 4 ; => source 376 000000AE 8CCE mov si, cs 377 000000B0 83C610 add si, 256 >> 4 ; => destination 378 %endif 379 380 init0_common: 381 ; REM: This part must be position-independent, as it is 382 ; called either with ip = init0_common (kernel mode 383 ; or device mode) 384 ; or ip = init0_common + 256 (application mode). 385 ; INP: si => depack destination 386 ; ax => source of payload + INIT1 387 ; dx => behind available memory 388 ; OUT: cs:ip -> init1_start: 389 ; ax => INIT1 390 ; dx => payload source 391 ; si => depack destination 392 ; bx = mode 393 000000B3 FC cld 394 %if _TEST_PROGRAM 395 %ifn _RELOAD_XMS || _RELOAD_FILE 396 000000B4 81EA0F0C sub dx, ( (payload_end - payload) ) >> 4 397 000000B8 721A jc .error 398 %endif 399 000000BA B90721 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) + (init2_end - init2_start) ) >> 4 405 000000BD 29CA sub dx, cx 406 000000BF 7213 jc .error 407 000000C1 39C2 cmp dx, ax 408 000000C3 720F jb .error 409 %else 410 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 415 ; cx = amount paragraphs in INIT0B + payload + INIT1 416 sub dx, cx ; => destination for INIT0B + payload + INIT1 417 ; (highest possible spot in available memory) 418 %endif 419 000000C5 56 push si ; preserve destination 420 000000C6 E86700 call init0_movp ; move up payload + INIT1 421 000000C9 5E pop si 422 %else 423 cld 424 mov ax, cs 425 add ax, (init0_end - init0_start) >> 4 426 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 431 mov dx, word [ bp + ldLoadTop ] 432 sub dx, cx 433 call init0_movp 434 %endif 435 436 %if _LCFG && ! _TEST_PROGRAM 437 push cs 438 call @F ; position-independent far pointer 439 @@: 440 pop ax 441 add ax, lcfg - @B ; -> lCFG block 442 push ax 443 %endif 444 445 000000CA 89D0 mov ax, dx ; => INIT0B 446 ; (same as => payload if INIT0B is empty) 447 %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM 448 add dx, ( + (init0b_end - init0b_start) ) >> 4 ; => payload 451 %else 452 %if _TEST_PROGRAM 453 000000CC 05CE0C add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 ; => INIT2 458 %else 459 add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) ) >> 4 ; => INIT1 463 %endif 464 %endif 465 000000CF 31C9 xor cx, cx 466 000000D1 50 push ax 467 000000D2 51 push cx 468 000000D3 CB retf ; jump to relocated 469 ; INIT0B:init0b_start 470 ; or INIT1:init1_start 471 ; or INIT2:init2_start 472 473 474 %if _TEST_PROGRAM 475 .error: 476 000000D4 89DF mov di, bx ; whichtest 477 478 000000D6 0E push cs 479 000000D7 1F pop ds 480 000000D8 BA[B202] mov dx, init0_msg.error_stderr + 256 481 000000DB B92500 mov cx, init0_msg.error_stderr.length 482 000000DE BB0200 mov bx, 2 483 000000E1 B440 mov ah, 40h 484 000000E3 CD21 int 21h 485 486 000000E5 F7C70040 test di, 4000h ; whichtest 487 000000E9 7408 jz @F 488 000000EB BA[D702] mov dx, init0_msg.error_c_stdout + 256 489 000000EE B90300 mov cx, init0_msg.error_c_stdout.length 490 000000F1 EB0A jmp @FF 491 @@: 492 000000F3 85FF test di, di ; whichtest 493 000000F5 780D js @FF 494 000000F7 BA[D702] mov dx, init0_msg.error_stdout + 256 495 000000FA B90300 mov cx, init0_msg.error_stdout.length 496 @@: 497 000000FD BB0100 mov bx, 1 498 00000100 B440 mov ah, 40h 499 00000102 CD21 int 21h 500 @@: 501 00000104 B8FF4C mov ax, 4CFFh 502 00000107 CD21 int 21h 503 504 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 505 init0_error_file: 506 mov dx, init0_msg.error_stderr_file + 256 507 mov cx, init0_msg.error_stderr_file.length 508 push cs 509 pop ds 510 mov bx, 2 511 mov ah, 40h 512 int 21h 513 514 mov dx, init0_msg.error_stdout + 256 515 mov cx, init0_msg.error_stdout.length 516 mov bx, 1 517 mov ah, 40h 518 int 21h 519 mov ax, 4CFFh 520 int 21h 521 %endif 522 523 %endif 524 525 526 %if _LCFG 527 %imacro lcfgoption 3+.nolist 528 _fill %1, 0, lcfg 529 %%start: 530 %2 531 %3 532 %%end: 533 %assign %%index %%start - lcfg 534 %rep %%end - %%start 535 %assign LCFGINUSE LCFGINUSE | (1 << %%index) 536 %assign %%index %%index + 1 537 %endrep 538 %endmacro 539 %assign LCFGINUSE 0 540 541 00000109 90 align 16 542 lcfg: 543 00000110 EB1E .: jmp strict short .end 544 00000112 6C434647 lcfgoption 2,, db "lCFG" 545 00000116 3030 lcfgoption 6,, db "00" 546 00000118 FCFF050000000000 lcfgoption 8,, dq .inuse 547 %if _PROGRESS && _PROGRESSMULTI 548 %if _IMAGE_EXE 549 00000120 00 lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP 550 %endif 551 %if _DEVICE 552 lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE 553 %endif 554 %if _BOOTLDR 555 00000121 0001 lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT 556 %endif 557 %endif 558 559 %ifnidn _LCFG_CFG, "" 560 %include _LCFG_CFG 1 <1> ; File auto-generated, do not edit. 561 %endif 562 563 00000123 00 lcfgoption 32,, 564 .end: 565 .size: equ .end - . 566 .inuse equ LCFGINUSE 567 %endif 568 569 570 %if _DEVICE 571 device_entrypoint: 572 %if _TEST_PROGRAM 573 @@: 574 int3 575 sti 576 hlt 577 jmp @B 578 %endif 579 cmp byte [es:bx + 2], 0 ; command code 0 (init) ? 580 je @F 581 582 mov word [es:bx + 3], 8103h ; error, done, code: unknown command 583 retf 584 585 @@: 586 or word [cs:device_header.next], -1 587 push cs 588 push word [cs:device_header.strategy] 589 ; -> far return to payload's strategy 590 push bp 591 push ds 592 push si 593 push di 594 push dx 595 push cx 596 push ax 597 push bx 598 push es 599 600 mov dx, word [es:bx + 14] 601 mov cl, 4 602 shr dx, cl ; = how many full paragraphs (rounded down) 603 add dx, word [es:bx + 14 + 2] 604 ; ax => behind end 605 606 mov di, cs 607 image_size: equ ( + (init0_end - init0_start) + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) 613 add di, image_size >> 4 ; di => end of image 614 615 cmp dx, di ; enough memory to hold all of us ? 616 jb @F ; no --> 617 ; yes 618 .have_some_memory: 619 ; dx => after end of memory 620 mov bx, 2 ; device mode 621 push ax 622 mov ax, cs 623 add ax, (init0_end - init0_start) >> 4 624 mov si, cs ; => destination 625 jmp init0_common 626 627 628 @@: 629 push cs 630 pop ds 631 mov dx, .msg_no_memory 632 mov ah, 09h 633 int 21h 634 635 mov ax, 3000h 636 int 21h 637 cmp al, 5 638 jae @F 639 mov dx, .msg_dos_below_5 640 mov ah, 09h 641 int 21h 642 @@: 643 644 mov dx, .msg_linebreak 645 mov ah, 09h 646 int 21h 647 648 ; tear down the stack frame and modify the request header 649 pop es 650 pop bx 651 mov word [es:bx + 3], 8103h ; set error, done, invalid command 652 mov byte [es:bx + 13], 0 ; set number of units = 0 653 mov word [es:bx + 14 + 2], cs 654 and word [es:bx + 14], 0 ; -> after end of memory to allocate 655 pop ax 656 pop cx 657 pop dx 658 pop di 659 pop si 660 pop ds 661 pop bp 662 add sp, 4 ; discard far return to payload's strategy 663 retf ; return to DOS 664 665 666 .msg_no_memory: ascic "Load error: Not enough memory." 667 .msg_dos_below_5: ascic " Note: DOS must be at least version 5." 668 .msg_linebreak: ascic 13,10 669 %endif 670 671 672 ; Move paragraphs 673 ; 674 ; INP: ax => source 675 ; dx => destination 676 ; cx = number of paragraphs 677 ; CHG: cx, ds, si, es, di 678 ; OUT: ax and dx unchanged 679 ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 680 ; Do not provide a wrapped/HMA source or destination! 681 init0_movp: 682 00000130 39D0 cmp ax, dx ; source above destination ? 683 00000132 770A ja .up ; yes, move up (forwards) --> 684 00000134 747B je .return ; same, no need to move --> 685 00000136 50 push ax 686 00000137 01C8 add ax, cx ; (expected not to carry) 687 00000139 39D0 cmp ax, dx ; end of source is above destination ? 688 0000013B 58 pop ax 689 0000013C 7730 ja .down ; yes, move from top down --> 690 ; Here, the end of source is below-or-equal the destination, 691 ; so they do not overlap. In this case we prefer moving up. 692 693 .up: 694 0000013E 50 push ax 695 0000013F 52 push dx 696 .uploop: 697 00000140 8ED8 mov ds, ax 698 00000142 8EC2 mov es, dx 699 00000144 31FF xor di, di 700 00000146 31F6 xor si, si ; -> start of segment 701 00000148 81E90010 sub cx, 1000h ; 64 KiB left ? 702 0000014C 7610 jbe .uplast ; no --> 703 0000014E 51 push cx 704 0000014F B90080 mov cx, 10000h /2 705 00000152 F3A5 rep movsw ; move 64 KiB 706 00000154 59 pop cx 707 00000155 050010 add ax, 1000h 708 00000158 81C20010 add dx, 1000h ; -> next segment 709 0000015C EBE2 jmp short .uploop ; proceed for more --> 710 .uplast: 711 0000015E 81C10010 add cx, 1000h ; restore counter 712 00000162 D1E1 shl cx, 1 713 00000164 D1E1 shl cx, 1 714 00000166 D1E1 shl cx, 1 ; *8, paragraphs to words 715 00000168 F3A5 rep movsw ; move last part 716 0000016A 5A pop dx 717 0000016B 58 pop ax 718 0000016C EB43 jmp short .return 719 720 .down: 721 0000016E FD std ; _AMD_ERRATUM_109_WORKAROUND as below 722 .dnloop: 723 0000016F 81E90010 sub cx, 1000h ; 64 KiB left ? 724 00000173 761A jbe .dnlast ; no --> 725 00000175 50 push ax 726 00000176 52 push dx 727 00000177 01C8 add ax, cx 728 00000179 01CA add dx, cx 729 0000017B 8ED8 mov ds, ax ; -> 64 KiB not yet moved 730 0000017D 8EC2 mov es, dx 731 0000017F 5A pop dx 732 00000180 58 pop ax 733 00000181 BFFEFF mov di, -2 734 00000184 89FE mov si, di ; moved from last word down 735 00000186 51 push cx 736 00000187 B90080 mov cx, 10000h /2 737 0000018A F3A5 rep movsw ; move 64 KiB 738 0000018C 59 pop cx 739 0000018D EBE0 jmp short .dnloop ; proceed for more --> 740 .dnlast: 741 0000018F 81C10010 add cx, 1000h ; restore counter 742 00000193 D1E1 shl cx, 1 743 00000195 D1E1 shl cx, 1 744 00000197 D1E1 shl cx, 1 ; *8, paragraphs to words 745 00000199 89CF mov di, cx 746 0000019B 4F dec di 747 0000019C D1E7 shl di, 1 ; words to offset, -> last word 748 0000019E 89FE mov si, di 749 000001A0 8ED8 mov ds, ax 750 000001A2 8EC2 mov es, dx ; first segment correct 751 752 753 numdef AMD_ERRATUM_109_WORKAROUND, 1 754 %if 0 755 756 Jack R. Ellis pointed out this erratum: 757 758 Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69: 759 760 109 Certain Reverse REP MOVS May Produce Unpredictable Behavior 761 762 Description 763 764 In certain situations a REP MOVS instruction may lead to 765 incorrect results. An incorrect address size, data size 766 or source operand segment may be used or a succeeding 767 instruction may be skipped. This may occur under the 768 following conditions: 769 770 * EFLAGS.DF=1 (the string is being moved in the reverse direction). 771 772 * The number of items being moved (RCX) is between 1 and 20. 773 774 * The REP MOVS instruction is preceded by some microcoded instruction 775 that has not completely retired by the time the REP MOVS begins 776 execution. The set of such instructions includes BOUND, CLI, LDS, 777 LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions. 778 779 Potential Effect on System 780 781 Incorrect results may be produced or the system may hang. 782 783 Suggested Workaround 784 785 Contact your AMD representative for information on a BIOS update. 786 787 %endif 788 789 %if _AMD_ERRATUM_109_WORKAROUND 790 000001A4 E308 jcxz @FF 791 000001A6 83F914 cmp cx, 20 792 000001A9 7703 ja @FF 793 @@: 794 000001AB A5 movsw 795 000001AC E2FD loop @B 796 @@: 797 %endif 798 000001AE F3A5 rep movsw ; move first part 799 000001B0 FC cld 800 .return: 801 000001B1 C3 retn 802 803 804 addsection INIT0B, align=16 vstart=0 follows=INIT0 805 ; INP: ax:cx = cs:ip = cs:0 806 ; ax => INIT0B 807 ; dx => payload source 808 ; ss:sp -> (dword pointer to lCFG block) 809 ; if app/device mode supported: 810 ; si => depack destination 811 ; bx = mode 812 init0b_start: 813 %if _LCFG || _PROGRESS 814 815 00000000 051F0C add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) ) >> 4 ; => INIT1 819 820 %if _LCFG && _PASSLCFG 821 %if (_IMAGE_EXE || _DEVICE) 822 mov cx, si ; preserve si 823 %endif 824 pop si 825 pop ds ; -> lCFG block 826 mov es, ax 827 mov di, transfer_lcfg_block 828 ; -> destination 829 %if (_IMAGE_EXE || _DEVICE) 830 push cx 831 %endif 832 push di 833 mov cx, words(lcfg.size) 834 rep movsw ; cx = 0 835 pop di ; es:di -> relocated lCFG block, same difference 836 %if (_IMAGE_EXE || _DEVICE) 837 pop si ; preserve si 838 %endif 839 %elif _LCFG 840 00000003 5F pop di 841 00000004 07 pop es ; es:di -> (original) lCFG block 842 %endif 843 844 00000005 50 push ax 845 00000006 51 push cx ; -> far return address to init1_start 846 847 %if _PROGRESS && _PROGRESSMULTI 848 %if (_IMAGE_EXE || _DEVICE) 849 00000007 56 push si 850 00000008 53 push bx 851 %endif 852 %if _BOOTLDR 853 %if _LCFG 854 00000009 31C0 xor ax, ax 855 0000000B 268A4512 mov al, byte [es:di + lcfg.progress_boot - lcfg] 856 0000000F 97 xchg di, ax ; di = boot default progress 857 ; es:ax -> lCFG block 858 %else ; _LCFG 859 mov di, _PROGRESSDEFAULTBOOT 860 %endif ; _LCFG 861 %endif ; _BOOTLDR 862 %if (_IMAGE_EXE || _DEVICE) 863 %if _BOOTLDR 864 00000010 85DB test bx, bx 865 00000012 7503E9A700 jz .default 866 %endif ; _BOOTLDR 867 %if _LCFG 868 00000017 06 push es 869 %if _BOOTLDR 870 00000018 50 push ax ; -> lCFG block 871 %else ; _BOOTLDR 872 push di 873 %endif ; _BOOTLDR 874 %endif ; _LCFG 875 %if _PROGRESSVAR 876 00000019 B451 mov ah, 51h 877 0000001B CD21 int 21h 878 @@: 879 0000001D 8EDB mov ds, bx 880 0000001F A12C00 mov ax, word [2Ch] 881 00000022 85C0 test ax, ax 882 00000024 7510 jnz .gotenv 883 00000026 A11600 mov ax, word [16h] 884 00000029 40 inc ax 885 0000002A 7469 jz .default_nonboot 886 0000002C 48 dec ax 887 0000002D 7466 jz .default_nonboot 888 0000002F 39C3 cmp bx, ax 889 00000031 7462 je .default_nonboot 890 00000033 93 xchg bx, ax 891 00000034 EBE7 jmp @B 892 893 .gotenv: 894 00000036 0E push cs 895 00000037 1F pop ds ; => cs 896 00000038 8EC0 mov es, ax ; => environment 897 %ifnidni _PROGRESSVARNAME, "" 898 0000003A BB[EA00] mov bx, progressvarname1 899 0000003D E80C00 call .findenv 900 00000040 732E jnc .foundenv ; match --> 901 00000042 BB[ED00] mov bx, progressvarname2 902 %endif 903 00000045 E80400 call .findenv 904 00000048 7326 jnc .foundenv ; match --> 905 0000004A EB49 jmp .default_nonboot 906 907 .findenv: 908 0000004C 31FF xor di, di 909 @@: 910 %ifnidni _PROGRESSVARNAME, "" 911 0000004E 89DE mov si, bx ; -> variable name 912 %else 913 mov si, progressvarname2 ; -> variable name 914 %endif 915 00000050 31C0 xor ax, ax 916 00000052 AC lodsb ; get length 917 00000053 91 xchg cx, ax ; cx = length 918 00000054 57 push di 919 00000055 F3A6 repe cmpsb ; match ? 920 00000057 7415 je .findret_pop ; (NC) yes --> 921 00000059 5F pop di 922 0000005A B90080 mov cx, 8000h ; maximum env size 923 0000005D 29F9 sub cx, di ; any left ? 924 0000005F 760B jbe .findret_CY ; no --> 925 00000061 B000 mov al, 0 926 00000063 F2AE repne scasb ; find next NUL 927 00000065 7505 jne .findret_CY 928 00000067 263805 cmp byte [es:di], al ; double NUL ? 929 0000006A 75E2 jne @B ; no, loop --> 930 .findret_CY: 931 0000006C F9 stc ; not found 932 0000006D C3 retn 933 934 .findret_pop: 935 0000006E 59 pop cx 936 0000006F C3 retn 937 938 .foundenv: 939 %if _LCFG 940 00000070 5E pop si 941 00000071 5E pop si ; discard far pointer to lCFG 942 %endif 943 00000072 89FE mov si, di ; es:si -> var content 944 00000074 31FF xor di, di ; = 0 945 00000076 31C0 xor ax, ax ; ah = 0 946 @@: 947 00000078 26AC es lodsb ; next candidate digit 948 0000007A 2C30 sub al, '0' ; digit ? 949 0000007C 7212 jb @F ; no --> 950 0000007E 3C09 cmp al, 9 951 00000080 770E ja @F ; no --> 952 00000082 01FF add di, di ; times 2 953 00000084 89FB mov bx, di 954 00000086 01FF add di, di ; times 4 955 00000088 01FF add di, di ; times 8 956 0000008A 01DF add di, bx ; times 8 + times 2 = times 10 957 0000008C 01C7 add di, ax ; add in next digit 958 0000008E EBE8 jmp @B ; and loop 959 960 @@: 961 00000090 83E71F and di, 31 ; mask to low 5 bits 962 00000093 EB0B jmp @F 963 %endif ; _PROGRESSVAR 964 965 .default_nonboot: 966 %if _LCFG 967 00000095 5F pop di 968 00000096 07 pop es ; -> lCFG block 969 00000097 5B pop bx ; = 1 if app, = 2 if device 970 00000098 53 push bx 971 00000099 268B4510 mov ax, word [es:di + lcfg.progress_app - lcfg] 972 %if _DEVICE 973 %if lcfg.progress_app + 1 != lcfg.progress_dev 974 %error Unexpected layout 975 %endif 976 ; al = app, ah = device 977 dec bx 978 jz .default_app 979 xchg al, ah ; al = device 980 .default_app: 981 %endif ; _DEVICE 982 0000009D B400 mov ah, 0 ; ax = default 983 0000009F 97 xchg di, ax ; di = default 984 %else ; _LCFG 985 mov di, _PROGRESSDEFAULT 986 %endif ; _LCFG 987 @@: 988 000000A0 F7C71000 test di, 16 989 000000A4 7405 jz @F 990 000000A6 83E7EF and di, ~16 991 000000A9 EB13 jmp .outputdevice ; if 16 set skip device check 992 @@: 993 000000AB 52 push dx 994 000000AC B80044 mov ax, 4400h ; IOCTL get device information 995 000000AF BB0100 mov bx, 1 ; StdOut 996 000000B2 B283 mov dl, 83h ; default if 21.4400 fails 997 000000B4 CD21 int 21h 998 000000B6 F6C280 test dl, 80h 999 000000B9 5A pop dx 1000 000000BA 7502 jnz .outputdevice 1001 000000BC 31FF xor di, di ; stdout is a file: force no progress marker 1002 .outputdevice: 1003 %endif ; (_IMAGE_EXE || _DEVICE) 1004 1005 .default: 1006 %if (_IMAGE_EXE || _DEVICE) 1007 000000BE 5B pop bx 1008 000000BF 5E pop si 1009 %endif 1010 000000C0 83FF05 cmp di, step_progress_table.amount 1011 ; valid ? 1012 000000C3 7202 jb @F ; yes --> 1013 000000C5 31FF xor di, di ; disable 1014 @@: 1015 000000C7 D1E7 shl di, 1 ; = word index 1016 000000C9 59 pop cx ; = 0 1017 000000CA 1F pop ds ; ds => INIT1 1018 1019 000000CB 2E8B85[E000] mov ax, word [cs:step_progress_table + di] 1020 ; ax = rel16 for step progress handler 1021 000000D0 1E push ds 1022 000000D1 51 push cx ; -> init1_start 1023 000000D2 A3[6800] mov word [step_progress.handler], ax 1024 ; patch it 1025 1026 000000D5 83FF04 cmp di, 2 * 2 ; none or dots ? 1027 000000D8 7305 jae @F ; no, skip --> 1028 000000DA C606[0600]A9 mov byte [..@empty_step_progress], __TEST_IMM16 1029 ; for none and dots do not call here 1030 @@: 1031 %endif ; _PROGRESS && _PROGRESSMULTI 1032 000000DF CB retf 1033 %endif 1034 1035 %if _PROGRESS && _PROGRESSMULTI 1036 align 2, db 0 1037 step_progress_table: 1038 .: 1039 000000E0 1600 dw step_progress.0_step - step_progress.base 1040 000000E2 3B00 dw step_progress.1_step - step_progress.base 1041 000000E4 0000 dw step_progress.2_step - step_progress.base 1042 000000E6 4100 dw step_progress.3_step - step_progress.base 1043 000000E8 8600 dw step_progress.4_step - step_progress.base 1044 .amount equ ($ - .) / 2 1045 1046 %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE) 1047 %ifnidni _PROGRESSVARNAME, "" 1048 000000EA 02003D progressvarname1: counted _PROGRESSVARNAME, '=' 1049 %endif 1050 000000ED 0D4C444F5350524F47- progressvarname2: counted "LDOSPROGRESS=" 1050 000000F6 524553533D 1051 %endif 1052 %endif 1053 1054 000000FB 90 align 16 1055 init0b_end: 1056 1057 1058 addsection PAYLOAD, align=16 follows=INIT0B 1059 payload: 1060 00000000 incbin _PAYLOAD_FILE 1061 .end: 1062 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 00000000 5589E5 lenter 1105 lvar word, exemode ; must be bp - 2! 1106 00000003 53 push bx 1107 %if ?exemode != -2 1108 %error exemode variable must be directly below bp 1109 %endif 1110 00000004 56 push si 1111 %if _PROGRESS 1112 00000005 F8 clc ; NC 1113 %endif 1114 %else 1115 xor bx, bx ; always tell them it is kernel mode (NC) 1116 %endif 1117 1118 %if _PROGRESS 1119 ; clc 1120 ..@empty_step_progress: ; SMC, byte patched to __TEST_IMM16 if none or dots 1121 %if _TEST_PROGRAM 1122 00000006 90 times 3 nop 1123 %else 1124 call step_progress.CF ; display empty / 0.0% 1125 %endif 1126 @@: 1127 %endif 1128 1129 %if _IMAGE_EXE || _DEVICE 1130 00000009 8EC6 mov es, si ; es => destination 1131 %else 1132 mov ax, 60h 1133 mov es, ax ; es => destination 1134 %endif 1135 0000000B 31FF xor di, di ; -> destination 1136 1137 0000000D 8EDA mov ds, dx 1138 0000000F 31F6 xor si, si ; -> source 1139 1140 00000011 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 00000014 31D2 xor dx, dx 1145 %endif 1146 %if _PAYLOAD_KERNEL_MAX_PARAS 1147 mov ax, _PAYLOAD_KERNEL_MAX_PARAS 1148 test bx, bx 1149 jz @F 1150 %endif 1151 00000016 B8FFFF mov ax, -1 1152 @@: 1153 1154 ; INP: ds:si -> source 1155 ; dx:cx = length of source 1156 ; es:di -> destination (below source) 1157 ; bx = EXE mode flag 1158 ; (1 if EXE mode, 0 if kernel mode) 1159 ; (always 0 if this is a build without EXE mode) 1160 ; if _PAYLOAD_KERNEL_MAX_PARAS: 1161 ; ax = maximum amount in paragraphs of destination needed 1162 ; (-1 if full source should be decompressed) 1163 ; else: 1164 ; ax = -1 1165 ; Note: The destination reaches up to below the source. 1166 00000019 E80504 call depack 1167 %ifn _TEST_PROGRAM 1168 jc strict short error ; -2 (replaced by retf \ nop) 1169 %endif 1170 %if _IMAGE_EXE || _DEVICE 1171 0000001C 5E pop si ; si 1172 %if _TEST_PROGRAM 1173 0000001D 58 pop ax ; (discard ?exemode, leave bx as returned) 1174 %else 1175 pop bx ; ?exemode 1176 %endif 1177 0000001E 5D pop bp ; bp 1178 0000001F 58 pop ax ; ax 1179 lleave ctx 1180 %endif 1181 %if _TEST_PROGRAM 1182 00000020 CB retf ; +1 (replace jc error) 1183 00000021 90 nop ; +1 1184 %endif 1185 1186 %if _DEVICE 1187 test bl, 2 1188 jz .jmp_exe_or_kernel_mode 1189 1190 .jmp_device_mode: 1191 mov ds, si 1192 or word [device_header.next], -1 1193 %if _LCFG && _PASSLCFG 1194 mov word [device_header.pass_lcfg], transfer_lcfg_block 1195 mov word [device_header.pass_lcfg + 2], cs 1196 %endif 1197 pop es 1198 pop bx 1199 pop ax 1200 pop cx 1201 pop dx 1202 pop di 1203 pop si 1204 pop ds 1205 pop bp 1206 retf ; transfer to payload strategy entrypoint 1207 ; still on stack: far return address to DOS 1208 1209 .jmp_exe_or_kernel_mode: 1210 %endif 1211 1212 %if _IMAGE_EXE 1213 00000022 F6C301 test bl, 1 1214 00000025 7410 jz .jmp_kernel_mode 1215 1216 .jmp_exe_mode: 1217 %if ! _IMAGE_EXE_AUTO_STACK 1218 mov cx, cs 1219 lea dx, [si + _IMAGE_EXE_SS] 1220 push dx ; stack = relocated ss value 1221 add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4 1222 cmp cx, dx ; INIT1 code is above intended stack ? 1223 jae @F ; yes --> 1224 1225 lframe 1226 lenter 1227 lvar word, exemode 1228 push bx 1229 %if ?exemode != -2 1230 %error exemode variable must be directly below bp 1231 %endif 1232 mov bx, -1 ; unimplemented, return error 1233 jmp error 1234 lleave ctx 1235 @@: 1236 cli 1237 pop ss ; = relocated ss value 1238 mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh ; change stack 1239 sti 1240 %endif 1241 1242 00000027 31C9 xor cx, cx 1243 00000029 51 push cx ; put zero on top of stack 1244 1245 %if _IMAGE_EXE_IP < 256 1246 mov cl, _IMAGE_EXE_IP 1247 %elif (_IMAGE_EXE_IP & 255) == 0 1248 mov ch, _IMAGE_EXE_IP >> 8 1249 %else 1250 0000002A B94001 mov cx, _IMAGE_EXE_IP 1251 %endif 1252 1253 %if _IMAGE_EXE_CS == -16 1254 0000002D 83C6F0 add si, -16 1255 00000030 8EDE mov ds, si 1256 00000032 8EC6 mov es, si 1257 %else 1258 lea dx, [si - 10h] ; => PSP 1259 mov ds, dx 1260 mov es, dx ; ds = es => PSP 1261 %if _IMAGE_EXE_CS 1262 add si, _IMAGE_EXE_CS ; = relocated cs value 1263 %endif 1264 %endif 1265 00000034 56 push si 1266 00000035 51 push cx 1267 %if _LCFG && _PASSLCFG 1268 mov di, transfer_lcfg_block 1269 mov cx, cs 1270 %endif 1271 00000036 CB retf ; jump to EXE mode of image 1272 1273 %endif 1274 .jmp_kernel_mode: 1275 %if _LCFG && _PASSLCFG 1276 mov di, transfer_lcfg_block 1277 mov cx, cs 1278 %endif 1279 00000037 EA00006000 jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET 1280 1281 1282 %if _TEST_PROGRAM 1283 disp_al_counter: 1284 0000003C 2EFF06[4200] inc word [cs:init1_c_mode_counter] ; 5 bytes 1285 00000041 C3 retn ; 1 byte 1286 1287 00000042 0000 init1_c_mode_counter: dw 0 ; 2 bytes, total 8 1288 %else 1289 %if _PROGRESS 1290 disp_al_counter equ step_progress 1291 %else 1292 disp_al_counter equ disp_al 1293 %endif 1294 %endif 1295 1296 1297 error: 1298 %ifn _TEST_PROGRAM ; 2 bytes 1299 push cs 1300 pop ds 1301 %endif 1302 %if _DEBUG0 1303 mov si, msg.error_begin 1304 call disp_error 1305 xchg ax, bx ; ax = error code 1306 call disp_ax_hex 1307 %ifn _TEST_PROGRAM ; 3 bytes 1308 mov si, msg.error_end 1309 %endif 1310 %else 1311 %ifn _TEST_PROGRAM ; 3 bytes 1312 mov si, msg.error 1313 %endif 1314 %endif 1315 %ifn _TEST_PROGRAM ; 3 bytes, total 2 + 3 + 3 = 8 1316 call disp_error 1317 %endif 1318 %if _DEVICE 1319 test byte [bp - 2], 2 1320 jz .exit_app_or_kernel 1321 1322 pop si ; => device segment 1323 pop bx ; mode word 1324 pop bp 1325 pop ax 1326 mov es, si 1327 xor di, di ; -> device header 1328 push cs 1329 pop ds 1330 mov si, device_header_copy ; -> to reset header 1331 mov cx, words(device_header_copy.length) 1332 rep movsw ; overwrite device header with default 1333 ; (reset to a valid state after unsuccessful 1334 ; decompression, which may have partially 1335 ; written the header already) 1336 push es 1337 pop ds ; -> device segment 1338 pop es 1339 pop bx 1340 mov word [es:bx + 3], 8103h ; set error, done, invalid command 1341 mov byte [es:bx + 13], 0 ; set number of units = 0 1342 mov word [es:bx + 14 + 2], ds 1343 and word [es:bx + 14], 0 ; -> after end of memory to allocate 1344 pop ax 1345 pop cx 1346 pop dx 1347 pop di 1348 pop si 1349 pop ds 1350 pop bp 1351 add sp, 4 ; discard far return to payload's strategy 1352 retf ; return to DOS 1353 1354 1355 .exit_app_or_kernel: 1356 %endif 1357 1358 %if _IMAGE_EXE 1359 %if _BOOTLDR 1360 00000044 F646FE01 test byte [bp - 2], 1 1361 00000048 7405 jz .exit_kernel_mode 1362 %endif 1363 1364 0000004A B87F4C mov ax, 4C7Fh 1365 0000004D CD21 int 21h 1366 1367 .exit_kernel_mode: 1368 %endif 1369 %if _BOOTLDR 1370 0000004F 31C0 xor ax, ax 1371 00000051 CD16 int 16h 1372 00000053 CD19 int 19h 1373 %endif 1374 1375 1376 %if _PROGRESS 1377 step_progress: 1378 00000055 F9 stc 1379 .CF: 1380 00000056 53 push bx 1381 00000057 51 push cx 1382 00000058 52 push dx 1383 00000059 1E push ds 1384 0000005A 56 push si 1385 0000005B 57 push di 1386 0000005C 50 push ax 1387 1388 0000005D 0E push cs 1389 0000005E 1F pop ds 1390 1391 0000005F 8316[9001]00 adc word [.counter], 0 1392 00000064 A1[9001] mov ax, word [.counter] 1393 1394 %if _PROGRESSMULTI 1395 %if _IMAGE_EXE || _DEVICE 1396 %assign defaultprogresshandler _PROGRESSDEFAULT 1397 %else 1398 %assign defaultprogresshandler _PROGRESSDEFAULTBOOT 1399 %endif 1400 00000067 E91600 jmp strict near . %+ defaultprogresshandler %+ _step 1401 .handler: equ $ - 2 ; SMC, patched to dispatch to handler 1402 .base: 1403 %endif 1404 1405 .2_step: 1406 0000006A BAE803 mov dx, 1000 1407 0000006D F7E2 mul dx ; dx:ax = counter times 1000 1408 %if _PROGRESSAMOUNT 1409 0000006F B90100 mov cx, _PROGRESSAMOUNT 1410 00000072 F7F1 div cx ; ax = 0..1000 1411 %else 1412 %warning Progress amount is zero 1413 mov ax, 1 1414 %endif 1415 1416 %if 0 1417 cmp word [.display], ax 1418 je .ret 1419 mov word [.display], ax 1420 %endif 1421 00000074 BE[9901] mov si, .message_number_end - 1 1422 00000077 E80E00 call .format_percentage 1423 1424 0000007A BE[9201] mov si, .message 1425 0000007D E82A01 call disp_error 1426 1427 .ret: 1428 00000080 58 pop ax 1429 .ret_ax: 1430 00000081 5F pop di 1431 00000082 5E pop si 1432 00000083 1F pop ds 1433 00000084 5A pop dx 1434 00000085 59 pop cx 1435 00000086 5B pop bx 1436 .retn: 1437 00000087 C3 retn 1438 1439 1440 .format_percentage: 1441 00000088 BB0200 mov bx, 2 ; skip dot 1442 1443 0000008B B90A00 mov cx, 10 ; base 1444 @@: 1445 0000008E 31D2 xor dx, dx ; dx:ax = current number 1446 00000090 F7F1 div cx ; dl = remainder, ax = next number 1447 00000092 80C230 add dl, '0' ; make decit 1448 00000095 8814 mov byte [si], dl ; store 1449 00000097 29DE sub si, bx ; -> next digit slot 1450 00000099 80FB02 cmp bl, 2 ; did we just store fractional ? 1451 0000009C B301 mov bl, 1 ; ! next iteration do not skip dot 1452 0000009E 74EE je @B ; yes, loop always --> 1453 000000A0 85C0 test ax, ax ; nonzero left ? 1454 000000A2 75EA jnz @B ; yes, loop if so --> 1455 000000A4 C3 retn 1456 1457 1458 %if _PROGRESSMULTI 1459 .0_step: equ .ret 1460 1461 .1_step: 1462 000000A5 58 pop ax 1463 000000A6 E80F01 call disp_al 1464 000000A9 EBD6 jmp .ret_ax 1465 1466 .3_step: 1467 000000AB BB4B00 mov bx, 80 - 1 - 4 1468 000000AE F7E3 mul bx ; dx:ax = counter times 75 1469 %if _PROGRESSAMOUNT 1470 000000B0 B90100 mov cx, _PROGRESSAMOUNT 1471 000000B3 F7F1 div cx ; ax = 0..75 1472 %else 1473 %warning Progress amount is zero 1474 mov ax, 1 1475 %endif 1476 1477 000000B5 3906[8E01] cmp word [.display], ax 1478 000000B9 74C5 je .ret 1479 000000BB A3[8E01] mov word [.display], ax 1480 1481 000000BE 50 push ax 1482 000000BF 91 xchg cx, ax 1483 000000C0 B00D mov al, 13 1484 000000C2 E8F300 call disp_al 1485 000000C5 B05B mov al, '[' 1486 000000C7 E8EE00 call disp_al 1487 000000CA B020 mov al, 32 1488 000000CC E8E900 call disp_al 1489 1490 000000CF B023 mov al, '#' 1491 000000D1 E305 jcxz @FF 1492 @@: 1493 000000D3 E8E200 call disp_al 1494 000000D6 E2FB loop @B 1495 @@: 1496 1497 000000D8 B020 mov al, 32 1498 000000DA 59 pop cx 1499 000000DB 29CB sub bx, cx 1500 000000DD 7607 jbe @FF 1501 000000DF 89D9 mov cx, bx 1502 @@: 1503 000000E1 E8D400 call disp_al 1504 000000E4 E2FB loop @B 1505 @@: 1506 1507 .m4done: 1508 000000E6 E8CF00 call disp_al 1509 000000E9 B05D mov al, ']' 1510 000000EB E8CA00 call disp_al 1511 000000EE EB90 jmp .ret 1512 1513 1514 .4_step: 1515 000000F0 50 push ax 1516 1517 000000F1 BAE803 mov dx, 1000 1518 000000F4 F7E2 mul dx ; dx:ax = counter times 1000 1519 %if _PROGRESSAMOUNT 1520 000000F6 B90100 mov cx, _PROGRESSAMOUNT 1521 000000F9 F7F1 div cx ; ax = 0..1000 1522 %else 1523 %warning Progress amount is zero 1524 mov ax, 1 1525 %endif 1526 1527 000000FB BE[A301] mov si, .message_4_number_end - 1 1528 000000FE E887FF call .format_percentage 1529 1530 00000101 58 pop ax 1531 00000102 BB4B00 mov bx, 80 - 1 - 4 1532 00000105 F7E3 mul bx ; dx:ax = counter times 75 1533 %if _PROGRESSAMOUNT 1534 00000107 B90100 mov cx, _PROGRESSAMOUNT 1535 0000010A F7F1 div cx ; ax = 0..75 1536 %else 1537 %warning Progress amount is zero 1538 mov ax, 1 1539 %endif 1540 1541 0000010C 50 push ax 1542 0000010D 91 xchg cx, ax 1543 0000010E B00D mov al, 13 1544 00000110 E8A500 call disp_al 1545 00000113 B05B mov al, '[' 1546 00000115 E8A000 call disp_al 1547 00000118 B020 mov al, 32 1548 0000011A E89B00 call disp_al 1549 1550 0000011D 31FF xor di, di 1551 0000011F BA2200 mov dx, (80 - 1 - 4 - .message_4_length) / 2 1552 00000122 803E[9F01]20 cmp byte [.message_4_number], 32 1553 00000127 7401 je @F 1554 00000129 47 inc di 1555 @@: 1556 0000012A 29FA sub dx, di 1557 1558 0000012C B023 mov al, '#' 1559 0000012E E306 jcxz @FF 1560 @@: 1561 00000130 E88500 call disp_al 1562 00000133 4A dec dx 1563 00000134 E0FA loopnz @B 1564 @@: 1565 1566 00000136 85D2 test dx, dx 1567 00000138 752E jnz .notyetm4 1568 1569 0000013A BE[9F01] mov si, .message_4 1570 0000013D 29FE sub si, di 1571 0000013F E86800 call disp_error 1572 1573 00000142 29F9 sub cx, di 1574 00000144 760E jbe @FF 1575 00000146 83E907 sub cx, .message_4_length 1576 00000149 7609 jbe @FF 1577 0000014B 89CA mov dx, cx 1578 0000014D B023 mov al, '#' 1579 @@: 1580 0000014F E86600 call disp_al 1581 00000152 E2FB loop @B 1582 @@: 1583 00000154 59 pop cx 1584 00000155 B020 mov al, 32 1585 00000157 83EB29 sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length 1586 0000015A 29D3 sub bx, dx 1587 0000015C 7607 jbe @FF 1588 0000015E 89D9 mov cx, bx 1589 @@: 1590 00000160 E85500 call disp_al 1591 00000163 E2FB loop @B 1592 @@: 1593 00000165 E97EFF jmp .m4done 1594 1595 .notyetm4: 1596 00000168 B020 mov al, 32 1597 0000016A 59 pop cx 1598 0000016B 29CB sub bx, cx 1599 0000016D 7608 jbe @FF 1600 0000016F 89D9 mov cx, bx 1601 @@: 1602 00000171 E84400 call disp_al 1603 00000174 4A dec dx 1604 00000175 E0FA loopnz @B 1605 @@: 1606 1607 00000177 BE[9F01] mov si, .message_4 1608 0000017A 29FE sub si, di 1609 0000017C E82B00 call disp_error 1610 1611 0000017F B020 mov al, 32 1612 00000181 29F9 sub cx, di 1613 00000183 83E907 sub cx, .message_4_length 1614 ; jbe @FF 1615 @@: 1616 00000186 E82F00 call disp_al 1617 00000189 E2FB loop @B 1618 @@: 1619 0000018B E958FF jmp .m4done 1620 %endif 1621 1622 align 2, db 0 1623 %if _PROGRESSMULTI 1624 0000018E FFFF .display: dw -1 1625 %endif 1626 00000190 0000 .counter: dw 0 1627 00000192 0D5B20 .message: db 13,"[ " 1628 00000195 2020312E30 .message_number:db " 1.0" ; enough digit slots for 100.0%, 1629 ; blanks are pre-init until written 1630 .message_number_end: 1631 0000019A 25205D00 db "% ]",0 1632 %if _PROGRESSMULTI 1633 0000019E 20 db " " 1634 .message_4: 1635 0000019F 2020312E30 .message_4_number:db " 1.0" ; enough digit slots for 100.0%, 1636 ; blanks are pre-init until written 1637 .message_4_number_end: 1638 000001A4 252000 db "% ",0 1639 .message_4_length: equ $ - 1 - .message_4 1640 %endif 1641 %endif 1642 1643 1644 %if _DEVICE 1645 align 16 1646 device_header_copy: 1647 .: 1648 .next: 1649 dd -1 ; already initialised 1650 .attributes: 1651 dw _DEVICE_ATTRIBUTE 1652 .strategy: 1653 dw .strategy_entry - . ; -> strategy entry 1654 .interrupt: 1655 dw .interrupt_entry - . ; -> interrupt entry 1656 .name: 1657 fill 8, 32, db _DEVICE_NAME 1658 1659 .strategy_entry: 1660 fill 4, 90h, jmp .set_error ; rel8 or rel16 jump, not minus . 1661 .interrupt_entry: 1662 fill 4, 90h, retf 1663 1664 .set_error: 1665 mov word [es:bx + 3], 8103h ; set error, done, invalid command 1666 retf 1667 .length: equ $ - . 1668 %endif 1669 1670 1671 disp_error.loop: 1672 000001A7 E80E00 call disp_al 1673 disp_error: 1674 000001AA AC lodsb 1675 000001AB 84C0 test al, al 1676 000001AD 75F8 jnz .loop 1677 000001AF C3 retn 1678 1679 %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3 1680 disp_ax_hex: ; ax 1681 xchg al,ah 1682 call disp_al_hex ; display former ah 1683 xchg al,ah ; and fall trough for al 1684 disp_al_hex: ; al 1685 push cx 1686 mov cl,4 1687 ror al,cl 1688 call disp_al_lownibble_hex ; display former high-nibble 1689 rol al,cl 1690 pop cx 1691 ; and fall trough for low-nibble 1692 disp_al_lownibble_hex: 1693 push ax ; save ax for call return 1694 and al,00001111b ; high nibble must be zero 1695 add al,'0' ; if number is 0-9, now it's the correct character 1696 cmp al,'9' 1697 jna .decimalnum ; if we get decimal number with this, ok --> 1698 add al,7 ; otherwise, add 7 and we are inside our alphabet 1699 .decimalnum: 1700 call disp_al 1701 pop ax 1702 retn 1703 %endif 1704 1705 1706 disp_al_for_progress: 1707 %if _PROGRESS && _PROGRESSMULTI 1708 000001B0 2E833E[6800]16 cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base 1709 000001B6 741B je disp_al.retn 1710 %endif 1711 disp_al: 1712 %if _TEST_PROGRAM 1713 000001B8 C3 retn 1714 %else 1715 push ax 1716 %endif 1717 %if _BOOTLDR 1718 000001B9 53 push bx 1719 000001BA 55 push bp 1720 000001BB B40E mov ah, 0Eh 1721 000001BD BB0700 mov bx, 7 1722 %endif 1723 %if _IMAGE_EXE || _DEVICE 1724 000001C0 52 push dx 1725 1726 %if _BOOTLDR 1727 000001C1 F646FE03 test byte [bp - 2], 1 | 2 1728 000001C5 7406 jz .display_kernel_mode 1729 %endif 1730 1731 000001C7 92 xchg dx, ax ; dl = input al 1732 000001C8 B402 mov ah, 02h 1733 000001CA CD21 int 21h 1734 %if _BOOTLDR 1735 000001CC A9 db __TEST_IMM16 ; (skip int) 1736 %endif 1737 1738 .display_kernel_mode: 1739 %endif 1740 %if _BOOTLDR 1741 000001CD CD10 int 10h 1742 %endif 1743 %if _IMAGE_EXE 1744 000001CF 5A pop dx 1745 %endif 1746 %if _BOOTLDR 1747 000001D0 5D pop bp 1748 000001D1 5B pop bx 1749 %endif 1750 000001D2 58 pop ax 1751 .retn: 1752 disp_error.ret: 1753 000001D3 C3 retn 1754 1755 1756 msg: 1757 %if _DEBUG0 1758 .error_begin: db "Load error: Decompression failure, code ",0 1759 .error_end: db "h.",13,10,0 1760 %else 1761 000001D4 4C6F6164206572726F- .error: db "Load error: Decompression failure.",13,10,0 1761 000001DD 723A204465636F6D70- 1761 000001E6 72657373696F6E2066- 1761 000001EF 61696C7572652E0D0A- 1761 000001F8 00 1762 %endif 1763 1764 1765 %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1 1766 %assign NEED_NORMALISE_BOTH_POINTERS 1 1767 %assign CHECK_POINTERS_VARIABLE_SRC 1 1768 %assign CHECK_POINTERS_VARIABLE_DST 1 1769 1770 ; Specific depacker's file is included within label msg. 1771 ; In the file, lframe is used and lleave ctx is not used. 1772 1773 %if _BRIEFLZ 1774 %include "brieflz.asm" 1775 %endif 1776 1777 1778 %if _LZ4 1779 %include "lz4.asm" 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 000001F9 807F2807 <1> cmp byte [bx + state.st], 7 62 000001FD 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 000001FE 8A4728 <1> mov al, byte [bx + state.st] 129 00000201 2C03 <1> sub al, 3 ; below 4 ? 130 00000203 7607 <1> jbe .zero ; yes --> 131 00000205 3C07 <1> cmp al, 10 - 3 ; 10 or 11 initially ? 132 00000207 7202 <1> jb .have ; no --> 133 00000209 2C03 <1> sub al, 3 ; convert 134 <1> .have: 135 0000020B A9 <1> db __TEST_IMM16 ; (skip mov) 136 <1> .zero: 137 0000020C 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 0000020E 884728 <1> mov byte [bx + state.st], al 147 00000211 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 00000212 E8E4FF <1> call .is_char 158 00000215 72F7 <1> jc .end 159 00000217 88E0 <1> mov al, ah 160 00000219 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 0000021B 1E <1> push ds 231 0000021C 07 <1> pop es 232 0000021D B80600 <1> mov ax, 6 233 00000220 89DF <1> mov di, bx ; -> .member_pos 234 00000222 AB <1> stosw ; low word of .member_pos 235 00000223 31C0 <1> xor ax, ax 236 00000225 AB <1> stosw ; high word of .member_pos 237 00000226 AB <1> stosw 238 00000227 AB <1> stosw ; .code 239 00000228 48 <1> dec ax 240 00000229 AB <1> stosw 241 0000022A AB <1> stosw ; .range 242 0000022B B90500 <1> mov cx, 5 243 <1> .loop: 244 0000022E E81900 <1> call getbyteshiftcode 245 00000231 E2FB <1> loop .loop 246 00000233 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 00000234 807F0B00 <1> cmp byte [bx + range_decoder.range + 3], 0 255 00000238 7521 <1> jnz @F ; (retn) 256 0000023A 50 <1> push ax 257 0000023B 8B4709 <1> mov ax, word [bx + range_decoder.range + 1] 258 0000023E 89470A <1> mov word [bx + range_decoder.range + 2], ax 259 00000241 8A6708 <1> mov ah, byte [bx + range_decoder.range] 260 00000244 B000 <1> mov al, 0 261 00000246 894708 <1> mov word [bx + range_decoder.range], ax 262 00000249 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 0000024A 50 <1> push ax 272 0000024B 8B4705 <1> mov ax, word [bx + range_decoder.code + 1] 273 0000024E 894706 <1> mov word [bx + range_decoder.code + 2], ax 274 00000251 8A6704 <1> mov ah, byte [bx + range_decoder.code] 275 00000254 E8A506 <1> call Range_decoder.get_byte 276 00000257 894704 <1> mov word [bx + range_decoder.code], ax 277 0000025A 58 <1> pop ax 278 <1> @@: 279 0000025B 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 0000025C 31D2 <1> xor dx, dx 291 0000025E 31C0 <1> xor ax, ax 292 00000260 E32C <1> jcxz .end 293 <1> .loop: 294 00000262 D16F0A <1> shr word [bx + range_decoder.range + 2], 1 295 00000265 D15F08 <1> rcr word [bx + range_decoder.range], 1 296 00000268 D1E0 <1> shl ax, 1 297 0000026A D1D2 <1> rcl dx, 1 298 0000026C 8B7F06 <1> mov di, word [bx + range_decoder.code + 2] 299 0000026F 3B7F0A <1> cmp di, word [bx + range_decoder.range + 2] 300 00000272 7506 <1> jne @F 301 00000274 8B7F04 <1> mov di, word [bx + range_decoder.code] 302 00000277 3B7F08 <1> cmp di, word [bx + range_decoder.range] 303 <1> @@: ; code >= range ? 304 0000027A 720D <1> jnae @F ; no, skip --> 305 0000027C 8B7F08 <1> mov di, word [bx + range_decoder.range] 306 0000027F 297F04 <1> sub word [bx + range_decoder.code], di 307 00000282 8B7F0A <1> mov di, word [bx + range_decoder.range + 2] 308 00000285 197F06 <1> sbb word [bx + range_decoder.code + 2], di 309 00000288 40 <1> inc ax ; symbol |= 1 (lowest bit always was zero) 310 <1> @@: 311 00000289 E8A8FF <1> call normaliserange 312 0000028C E2D4 <1> loop .loop 313 <1> .end: 314 0000028E 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 0000028F 8B570A <1> mov dx, word [bx + range_decoder.range + 2] 327 00000292 8B4708 <1> mov ax, word [bx + range_decoder.range] 328 00000295 B90B00 <1> mov cx, bit_model_total_bits 329 <1> @@: 330 00000298 D1EA <1> shr dx, 1 331 0000029A D1D8 <1> rcr ax, 1 332 0000029C E2FA <1> loop @B 333 <1> 334 0000029E 89D1 <1> mov cx, dx 335 000002A0 26F725 <1> mul word [es:di + bit_model.probability] 336 <1> ; dx:ax = low word + first high word 337 000002A3 52 <1> push dx 338 000002A4 50 <1> push ax ; on stack = low word + first high word 339 000002A5 91 <1> xchg ax, cx 340 000002A6 26F725 <1> mul word [es:di + bit_model.probability] 341 <1> ; ax = second high word (dx overflow) 342 000002A9 91 <1> xchg ax, cx ; cx 343 000002AA 58 <1> pop ax 344 000002AB 5A <1> pop dx 345 000002AC 01CA <1> add dx, cx ; = full uint32_t result 346 000002AE B90500 <1> mov cx, bit_model_move_bits 347 <1> 348 000002B1 395706 <1> cmp word [bx + range_decoder.code + 2], dx 349 000002B4 7503 <1> jne @F 350 000002B6 394704 <1> cmp word [bx + range_decoder.code], ax 351 <1> @@: 352 000002B9 7317 <1> jnb .not_code_below_bound 353 <1> 354 <1> .code_below_bound: 355 000002BB 894708 <1> mov word [bx + range_decoder.range], ax 356 000002BE 89570A <1> mov word [bx + range_decoder.range + 2], dx 357 000002C1 B80008 <1> mov ax, bit_model_total 358 000002C4 262B05 <1> sub ax, word [es:di + bit_model.probability] 359 000002C7 7228 <1> jc .error 360 000002C9 D3E8 <1> shr ax, cl 361 000002CB 260105 <1> add word [es:di + bit_model.probability], ax 362 000002CE B000 <1> mov al, 0 363 000002D0 EB18 <1> jmp .after_if 364 <1> 365 <1> .not_code_below_bound: 366 000002D2 294708 <1> sub word [bx + range_decoder.range], ax 367 000002D5 19570A <1> sbb word [bx + range_decoder.range + 2], dx 368 000002D8 294704 <1> sub word [bx + range_decoder.code], ax 369 000002DB 195706 <1> sbb word [bx + range_decoder.code + 2], dx 370 <1> 371 000002DE 268B05 <1> mov ax, word [es:di + bit_model.probability] 372 000002E1 D3E8 <1> shr ax, cl 373 000002E3 262905 <1> sub word [es:di + bit_model.probability], ax 374 000002E6 7209 <1> jc .error 375 000002E8 B001 <1> mov al, 1 376 <1> 377 <1> .after_if: 378 000002EA E847FF <1> call normaliserange 379 000002ED 3C01 <1> cmp al, 1 ; CY if 0, NC if 1 380 000002EF F5 <1> cmc ; NC if 0, CY if 1 381 000002F0 C3 <1> retn 382 <1> 383 <1> .error: 384 000002F1 E9F705 <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 000002F4 BE0100 <1> mov si, 1 ; symbol = 1 397 000002F7 83F90F <1> cmp cx, 15 398 000002FA 7721 <1> ja .error 399 000002FC 51 <1> push cx 400 000002FD E312 <1> jcxz .end 401 <1> .loop: 402 000002FF 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 00000300 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 00000302 01F7 <1> add di, si ; index into bit_model array 411 00000304 7217 <1> jc .error_pop_2 412 00000306 51 <1> push cx 413 00000307 E885FF <1> call Range_decoder.decode_bit 414 0000030A 59 <1> pop cx 415 0000030B 83D600 <1> adc si, 0 ; add in the decoded bit 416 0000030E 5F <1> pop di 417 0000030F E2EE <1> loop .loop 418 <1> .end: 419 00000311 59 <1> pop cx 420 00000312 B80100 <1> mov ax, 1 421 00000315 D3E0 <1> shl ax, cl ; = 1 << num_bits 422 00000317 29C6 <1> sub si, ax ; symbol - ( 1 << num_bits ) 423 00000319 96 <1> xchg ax, si 424 0000031A 31D2 <1> xor dx, dx ; return symbol 425 0000031C C3 <1> retn 426 <1> 427 <1> .error_pop_2: 428 <1> .error: 429 0000031D E9CB05 <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 00000320 51 <1> push cx 442 00000321 E8D0FF <1> call Range_decoder.decode_tree 443 00000324 59 <1> pop cx 444 00000325 92 <1> xchg dx, ax ; dx = symbol 445 00000326 31C0 <1> xor ax, ax ; = reversed_symbol 446 00000328 E306 <1> jcxz .end 447 <1> .loop: 448 0000032A D1EA <1> shr dx, 1 449 0000032C D1D0 <1> rcl ax, 1 450 0000032E E2FA <1> loop .loop 451 <1> .end: 452 00000330 31D2 <1> xor dx, dx 453 00000332 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 00000333 88C6 <1> mov dh, al ; = match_byte 466 <1> 467 00000335 B80100 <1> mov ax, 1 ; initialise symbol = 1 468 <1> 469 00000338 B90800 <1> mov cx, 8 470 <1> .loop: 471 0000033B 52 <1> push dx ; preserve dh = match_byte 472 0000033C 51 <1> push cx ; preserve loop counter 473 0000033D 49 <1> dec cx 474 0000033E D2EE <1> shr dh, cl ; match_byte >> i 475 00000340 81E20001 <1> and dx, 100h ; dh &= 1 = match_bit, dl = 0 476 00000344 52 <1> push dx 477 00000345 FEC6 <1> inc dh ; = (match_bit << 8) + 100h 478 00000347 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 00000349 57 <1> push di 483 0000034A 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 0000034B 01D2 <1> add dx, dx 488 <1> ; As dx was < 300h before this addition, it cannot carry. 489 0000034D 01D7 <1> add di, dx 490 <1> ; We assume that this does not carry. 491 0000034F E83DFF <1> call Range_decoder.decode_bit 492 00000352 91 <1> xchg ax, cx ; cl = result (1 or 0) 493 00000353 58 <1> pop ax ; = symbol 494 00000354 5F <1> pop di 495 00000355 5A <1> pop dx ; = match_bit << 8 496 00000356 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 00000358 38F1 <1> cmp cl, dh ; if( match_bit != bit ) ...- 500 0000035A 59 <1> pop cx ; = loop counter 501 0000035B 5A <1> pop dx ; = dh = match_byte 502 0000035C 7519 <1> jne .inner_next ; -... do the following --> 503 <1> .next: 504 0000035E E2DB <1> loop .loop 505 <1> .end: 506 00000360 30E4 <1> xor ah, ah ; return ax = symbol & 0FFh 507 00000362 C3 <1> retn 508 <1> 509 <1> .error_pop_2: 510 <1> .error: 511 00000363 E98505 <1> jmp depack.error 512 <1> 513 <1> 514 <1> .inner_loop: 515 00000366 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 00000367 01C0 <1> add ax, ax 520 00000369 57 <1> push di 521 0000036A 01C7 <1> add di, ax 522 0000036C 72F5 <1> jc .error_pop_2 523 0000036E E81EFF <1> call Range_decoder.decode_bit 524 00000371 5F <1> pop di 525 00000372 58 <1> pop ax 526 00000373 D1D0 <1> rcl ax, 1 527 00000375 72EC <1> jc .error 528 <1> 529 <1> .inner_next: 530 00000377 3D0001 <1> cmp ax, 100h 531 0000037A 72EA <1> jb .inner_loop 532 0000037C 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 0000037E 89C6 <1> mov si, ax ; = pos_state 545 00000380 57 <1> push di ; = len_model_struc (on stack) 546 <1> 547 00000381 8D3D <1> lea di, [di + len_model.choice1] 548 00000383 E809FF <1> call Range_decoder.decode_bit 549 00000386 5F <1> pop di ; reset to ?len_model_struc 550 00000387 57 <1> push di 551 00000388 7218 <1> jc .not_decode_bit_choice1_equals_zero 552 <1> 553 0000038A 8D7D04 <1> lea di, [di + len_model.bm_low] 554 0000038D B81000 <1> mov ax, len_low_symbols * bit_model_size 555 00000390 F7E6 <1> mul si 556 00000392 85D2 <1> test dx, dx 557 00000394 7546 <1> jnz .error 558 00000396 01C7 <1> add di, ax 559 00000398 7242 <1> jc .error 560 0000039A B90300 <1> mov cx, len_low_bits 561 0000039D E854FF <1> call Range_decoder.decode_tree 562 000003A0 EB38 <1> jmp .ret 563 <1> 564 <1> .not_decode_bit_choice1_equals_zero: 565 000003A2 8D7D02 <1> lea di, [di + len_model.choice2] 566 000003A5 E8E7FE <1> call Range_decoder.decode_bit 567 000003A8 5F <1> pop di ; reset to ?len_model_struc 568 000003A9 57 <1> push di 569 000003AA 721E <1> jc .not_decode_bit_choice2_equals_zero 570 <1> 571 000003AC 8D7D44 <1> lea di, [di + len_model.bm_mid] 572 000003AF B81000 <1> mov ax, len_mid_symbols * bit_model_size 573 000003B2 F7E6 <1> mul si 574 000003B4 85D2 <1> test dx, dx 575 000003B6 7524 <1> jnz .error 576 000003B8 01C7 <1> add di, ax 577 000003BA 7220 <1> jc .error 578 000003BC B90300 <1> mov cx, len_mid_bits 579 000003BF E832FF <1> call Range_decoder.decode_tree 580 000003C2 83C008 <1> add ax, len_low_symbols & 0FFFFh 581 000003C5 83D200 <1> adc dx, len_low_symbols >> 16 582 000003C8 EB10 <1> jmp .ret 583 <1> 584 <1> .not_decode_bit_choice2_equals_zero: 585 000003CA 8DBD8400 <1> lea di, [di + len_model.bm_high] 586 000003CE B90800 <1> mov cx, len_high_bits 587 000003D1 E820FF <1> call Range_decoder.decode_tree 588 000003D4 83C010 <1> add ax, (len_low_symbols + len_mid_symbols) & 0FFFFh 589 000003D7 83D200 <1> adc dx, (len_low_symbols + len_mid_symbols) >> 16 590 <1> .ret: 591 000003DA 5F <1> pop di 592 000003DB C3 <1> retn 593 <1> 594 <1> .error: 595 000003DC E90C05 <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 000003DF 395716 <1> cmp word [bx + lz_decoder.pos + 2], dx 612 000003E2 7503 <1> jne @F 613 000003E4 394714 <1> cmp word [bx + lz_decoder.pos], ax 614 <1> @@: 615 000003E7 760A <1> jna .not_pos_above_distance 616 <1> 617 000003E9 E80A00 <1> call calculate_peek_pointer_disi 618 <1> 619 000003EC 8EC7 <1> mov es, di ; es:si -> peek address 620 000003EE 31C0 <1> xor ax, ax 621 000003F0 26AC <1> es lodsb 622 000003F2 C3 <1> retn 623 <1> 624 <1> .not_pos_above_distance: 625 000003F3 31C0 <1> xor ax, ax 626 000003F5 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 000003F6 53 <1> push bx 635 000003F7 FF772E <1> push word [bx + destinationbuffer_constant + 2] 636 000003FA FF772C <1> push word [bx + destinationbuffer_constant] 637 <1> 638 000003FD F7DA <1> neg dx 639 000003FF F7D8 <1> neg ax 640 00000401 83DA00 <1> sbb dx, byte 0 ; neg dx:ax = - distance 641 00000404 83E801 <1> sub ax, 1 642 00000407 83DA00 <1> sbb dx, 0 ; - 1 643 0000040A 034714 <1> add ax, word [bx + lz_decoder.pos] 644 0000040D 135716 <1> adc dx, word [bx + lz_decoder.pos + 2] 645 <1> ; + pos 646 00000410 91 <1> xchg cx, ax 647 00000411 87DA <1> xchg bx, dx 648 <1> 649 00000413 E88D06 <1> call normalise_pointer_with_displacement_bxcx 650 00000416 5E <1> pop si 651 00000417 5F <1> pop di ; di:si -> source 652 00000418 5B <1> pop bx 653 00000419 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 0000041A 90 <1> align 4 702 <1> lzip_header_bytes: 703 <1> .: 704 0000041C 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 00000421 5589E5 <1> lenter early 733 <1> %if _IMAGE_EXE 734 <1> lvar word, exemode ; must be bp - 2! 735 00000424 53 <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 00000425 31DB <1> xor bx, bx 742 <1> %endif 743 <1> %endif 744 <1> %if _COUNTER 745 <1> lvar word, counter 746 00000427 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 00000428 8D66EC <1> lenter 756 <1> 757 0000042B E84406 <1> call normalise_both_pointers 758 <1> 759 <1> ; ! di < 16, so dih == 0 760 <1> lvar dword, src 761 0000042E 1E <1> push ds 762 0000042F 56 <1> push si 763 <1> lvar dword, final_dst 764 00000430 06 <1> push es 765 00000431 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 00000432 52 <1> push dx 771 00000433 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 00000434 1E <1> push ds 792 00000435 56 <1> push si 793 00000436 E89906 <1> call pointer_to_linear 794 <1> 795 00000439 87DA <1> xchg bx, dx 796 0000043B 91 <1> xchg cx, ax ; bx:cx = source linear, clobber dx:ax 797 <1> 798 0000043C 06 <1> push es 799 0000043D 57 <1> push di 800 0000043E E89106 <1> call pointer_to_linear 801 <1> 802 <1> %if _ALLOW_OVERLAPPING 803 00000441 034EE0 <1> add cx, word [bp + ?length_of_source] 804 00000444 135EE2 <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 00000447 29C1 <1> sub cx, ax 819 00000449 19D3 <1> sbb bx, dx ; bx:cx = source linear - destination linear 820 <1> 821 0000044B 81E96039 <1> sub cx, localvariables_size & 0FFFFh 822 0000044F 83DB00 <1> sbb bx, localvariables_size >> 16 823 00000452 7703E99404 <1> jbe .error ; make variables buffer available 824 <1> 825 <1> lvar dword, length_of_destination 826 00000457 53 <1> push bx ; push into [bp + ?length_of_destination + 2] 827 00000458 51 <1> push cx ; push into [bp + ?length_of_destination] 828 <1> 829 00000459 06 <1> push es 830 0000045A 57 <1> push di 831 <1> %if localvariables_size >> 16 832 <1> mov bx, localvariables_size >> 16 833 <1> %else 834 0000045B 31DB <1> xor bx, bx 835 <1> %endif 836 0000045D B96039 <1> mov cx, localvariables_size & 0FFFFh 837 00000460 E84006 <1> call normalise_pointer_with_displacement_bxcx 838 00000463 5F <1> pop di 839 00000464 07 <1> pop es 840 <1> 841 <1> lvar dword, original_dst 842 00000465 06 <1> push es 843 00000466 57 <1> push di 844 <1> lvar dword, dst 845 00000467 06 <1> push es 846 00000468 57 <1> push di 847 <1> 848 <1> %if _ALLOW_OVERLAPPING 849 00000469 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 0000046C 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 0000046E 837EE200 <1> cmp word [bp + ?length_of_source + 2], 0 868 00000472 7504 <1> jne @F 869 00000474 837EE01A <1> cmp word [bp + ?length_of_source], member_min_size 870 <1> @@: 871 00000478 770F <1> ja .got_member 872 <1> 873 0000047A 837EE200 <1> cmp word [bp + ?length_of_source + 2], 0 874 0000047E 7504 <1> jne @F 875 00000480 837EE00F <1> cmp word [bp + ?length_of_source], 15 876 <1> @@: 877 00000484 7710 <1> ja short .error_NZ_a ; (NZ if jumping) 878 00000486 E92E04 <1> jmp .end 879 <1> 880 <1> .got_member: 881 00000489 C576E8 <1> lds si, [bp + ?src] ; ds:si -> lzip_header.magic, .version 882 0000048C 0E <1> push cs 883 0000048D 07 <1> pop es 884 0000048E BF[1C04] <1> mov di, lzip_header_bytes 885 00000491 B90500 <1> mov cx, lzip_header_bytes.length 886 00000494 F3A6 <1> repe cmpsb 887 <1> .error_NZ_a: 888 00000496 7403E95004 <1> jne .error 889 <1> %if _COUNTER && !_PROGRESS 890 <1> mov al, '#' 891 <1> call disp_al 892 <1> %endif 893 0000049B 31C0 <1> xor ax, ax 894 0000049D AC <1> lodsb ; ax = lzip_header.coded_dict_size 895 <1> 896 0000049E 1E <1> push ds 897 0000049F 56 <1> push si 898 000004A0 E8DE05 <1> call normalise_pointer 899 000004A3 8F46E8 <1> pop word [bp + ?src] 900 000004A6 8F46EA <1> pop word [bp + ?src + 2] 901 000004A9 836EE006 <1> sub word [bp + ?length_of_source], 6 902 000004AD 835EE200 <1> sbb word [bp + ?length_of_source + 2], 0 903 <1> .error_CY_a: 904 000004B1 7235 <1> jc short .error_CY_b 905 <1> 906 000004B3 50 <1> push ax 907 000004B4 241F <1> and al, 1Fh 908 000004B6 91 <1> xchg cx, ax ; cx = coded dict size & 1Fh, clobber ax 909 000004B7 B80100 <1> mov ax, 1 910 000004BA 31D2 <1> xor dx, dx 911 <1> @@: 912 000004BC D1E0 <1> shl ax, 1 913 000004BE D1D2 <1> rcl dx, 1 914 000004C0 E2FA <1> loop @B 915 <1> 916 000004C2 89D3 <1> mov bx, dx 917 000004C4 89C7 <1> mov di, ax ; bx:di = dict_size 918 000004C6 B104 <1> mov cl, 4 919 <1> @@: 920 000004C8 D1EB <1> shr bx, 1 921 000004CA D1DF <1> rcr di, 1 922 000004CC E2FA <1> loop @B ; bx:di = dict_size / 16 923 000004CE 59 <1> pop cx 924 000004CF 88CD <1> mov ch, cl 925 000004D1 B105 <1> mov cl, 5 926 000004D3 D2ED <1> shr ch, cl 927 000004D5 88E9 <1> mov cl, ch 928 000004D7 B500 <1> mov ch, 0 929 000004D9 E331 <1> jcxz @FF 930 <1> 931 000004DB 52 <1> push dx 932 000004DC 50 <1> push ax 933 <1> 934 000004DD 89F8 <1> mov ax, di ; ax = low word of input 935 000004DF F7E1 <1> mul cx 936 000004E1 93 <1> xchg ax, bx ; ax = high word of input 937 000004E2 89D7 <1> mov di, dx ; di:bx = low word + first high word 938 000004E4 F7E1 <1> mul cx ; = high word 939 000004E6 01C7 <1> add di, ax ; add into sum 940 <1> .error_CY_b: 941 000004E8 7217 <1> jc short .error_CY_c 942 000004EA 85D2 <1> test dx, dx ; overflows ? 943 000004EC 7403E9FA03 <1> jnz .error 944 <1> ; bx:di = dict_size / 16 * fraction 945 000004F1 58 <1> pop ax 946 000004F2 5A <1> pop dx 947 000004F3 29D8 <1> sub ax, bx 948 000004F5 19FA <1> sbb dx, di 949 000004F7 7208 <1> jc short .error_CY_c 950 <1> 951 000004F9 83FA00 <1> cmp dx, min_dictionary_size >> 16 952 000004FC 7503 <1> jne @F 953 000004FE 3D0010 <1> cmp ax, min_dictionary_size & 0FFFFh 954 <1> @@: 955 <1> .error_CY_c: 956 00000501 7273 <1> jb short .error_CY_d 957 <1> 958 00000503 81FA0020 <1> cmp dx, max_dictionary_size >> 16 959 00000507 7503 <1> jne @F 960 00000509 83F800 <1> cmp ax, max_dictionary_size & 0FFFFh 961 <1> @@: 962 0000050C 7603E9DA03 <1> ja .error 963 <1> 964 00000511 C55EE4 <1> lds bx, [bp + ?final_dst] 965 00000514 FF76D6 <1> push word [bp + ?dst + 2] 966 00000517 FF76D4 <1> push word [bp + ?dst] 967 0000051A 8F472C <1> pop word [bx + destinationbuffer_constant] 968 0000051D 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 00000520 52 <1> push dx 986 00000521 50 <1> push ax ; preserve dictionary size 987 00000522 1E <1> push ds 988 00000523 07 <1> pop es 989 00000524 89DF <1> mov di, bx 990 00000526 B90C00 <1> mov cx, fromdwords(dwords(lz_decoder_size)) / 2 991 00000529 31C0 <1> xor ax, ax 992 0000052B F3AB <1> rep stosw ; initialise lz_decoder structure 993 <1> 994 0000052D E8EBFC <1> call Range_decoder.init ; initialise embedded range_decoder 995 <1> 996 00000530 8F4710 <1> pop word [bx + lz_decoder.dictionary_size] 997 00000533 8F4712 <1> pop word [bx + lz_decoder.dictionary_size + 2] 998 <1> ; set dictionary size 999 <1> 1000 00000536 8D7F30 <1> lea di, [bx + bit_models_start] 1001 00000539 B9971C <1> mov cx, (bit_models_end - bit_models_start) / bit_model_size 1002 0000053C 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 0000053F F3AB <1> rep stosw ; initialise this bit_model 1007 <1> ; loop for all bit_model and len_model 1008 <1> 1009 00000541 8D7F18 <1> lea di, [bx + zeros_start] 1010 00000544 31C0 <1> xor ax, ax 1011 00000546 B10A <1> mov cl, (zeros_end - zeros_start) / 2 1012 00000548 F3AB <1> rep stosw 1013 <1> 1014 <1> .loop: 1015 <1> %if _COUNTER 1016 0000054A FE46FC <1> inc byte [bp + ?counter] 1017 0000054D F646FCFF <1> test byte [bp + ?counter], _COUNTER - 1 1018 00000551 7505 <1> jnz @F 1019 00000553 B02E <1> mov al, '.' 1020 00000555 E8E4FA <1> call disp_al_counter 1021 <1> @@: 1022 <1> %endif 1023 00000558 8B5EE4 <1> mov bx, word [bp + ?localvariables] 1024 0000055B 8B4714 <1> mov ax, word [bx + lz_decoder.pos] 1025 0000055E 83E003 <1> and ax, pos_state_mask 1026 00000561 91 <1> xchg cx, ax ; cx = pos_state, ax clobbered 1027 00000562 894EEC <1> mov word [bp + ?pos_state], cx 1028 <1> 1029 00000565 1E <1> push ds 1030 00000566 07 <1> pop es 1031 00000567 8D7F30 <1> lea di, [bx + bm_match] ; es:di -> bm_match 2D array 1032 0000056A B80800 <1> mov ax, bit_model_size * pos_states 1033 0000056D 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 00000570 01C9 <1> add cx, cx ; = second index (from pos_state) 1042 <1> ; pos_state < 4 1043 <1> ; cx < 8 1044 <1> ; ax <= 88 1045 00000572 01C8 <1> add ax, cx ; = second index is pos_state 1046 00000574 01C7 <1> add di, ax ; es:di -> bm_match[state()][pos_state] 1047 <1> .error_CY_d: 1048 00000576 7222 <1> jc short .error_CY_1 1049 00000578 E814FD <1> call Range_decoder.decode_bit 1050 0000057B 7244 <1> jc .1st_bit_not_zero 1051 <1> 1052 <1> .1st_bit_zero: ; literal byte 1053 0000057D 31C0 <1> xor ax, ax 1054 0000057F 31D2 <1> xor dx, dx 1055 00000581 E85BFE <1> call LZ_decoder.peek ; al = prev_byte 1056 <1> 1057 00000584 B105 <1> mov cl, 8 - literal_context_bits 1058 00000586 D2E8 <1> shr al, cl ; = literal_state 1059 00000588 1E <1> push ds 1060 00000589 07 <1> pop es 1061 0000058A 8DBFF000 <1> lea di, [bx + bm_literal] ; -> 2D array bm_literal 1062 0000058E B90006 <1> mov cx, bit_model_size * 300h 1063 00000591 F7E1 <1> mul cx ; first index is literal_state 1064 00000593 85D2 <1> test dx, dx 1065 00000595 F9 <1> stc 1066 00000596 7502 <1> jnz short .error_CY_1 1067 00000598 01C7 <1> add di, ax ; es:di -> bm_literal[literal_state] 1068 <1> .error_CY_1: 1069 0000059A 7232 <1> jc short .error_CY_2 1070 <1> 1071 0000059C E85AFC <1> call State.is_char 1072 0000059F 7308 <1> jnc .not_is_char 1073 <1> .is_char: 1074 000005A1 B90800 <1> mov cx, 8 1075 000005A4 E84DFD <1> call Range_decoder.decode_tree 1076 000005A7 EB10 <1> jmp @F 1077 <1> 1078 <1> .not_is_char: 1079 000005A9 8B4718 <1> mov ax, word [bx + rep0] 1080 000005AC 8B571A <1> mov dx, word [bx + rep0 + 2] 1081 000005AF 06 <1> push es 1082 000005B0 57 <1> push di 1083 000005B1 E82BFE <1> call LZ_decoder.peek 1084 000005B4 5F <1> pop di 1085 000005B5 07 <1> pop es 1086 000005B6 E87AFD <1> call Range_decoder.decode_matched 1087 <1> @@: 1088 000005B9 E86703 <1> call LZ_decoder.put_byte 1089 000005BC E83FFC <1> call State.set_char 1090 000005BF EB89 <1> jmp .loop 1091 <1> 1092 <1> 1093 <1> .1st_bit_not_zero: ; match or repeated match 1094 000005C1 1E <1> push ds 1095 000005C2 07 <1> pop es 1096 000005C3 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 000005C7 8B4728 <1> mov ax, word [bx + state.st] 1101 000005CA 01C0 <1> add ax, ax ; ax = index is state 1102 <1> ; jc short .error_CY_2 ; (state.st is always < 12) 1103 000005CC 01C7 <1> add di, ax ; es:di -> bm_rep[state()] 1104 <1> .error_CY_2: 1105 000005CE 7230 <1> jc short .error_CY_3 1106 000005D0 E8BCFC <1> call Range_decoder.decode_bit 1107 000005D3 7203E9EA00 <1> jnc .2nd_bit_zero 1108 <1> 1109 <1> .2nd_bit_not_zero: 1110 000005D8 1E <1> push ds 1111 000005D9 07 <1> pop es 1112 000005DA 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 000005DE 8B4728 <1> mov ax, word [bx + state.st] 1117 000005E1 01C0 <1> add ax, ax ; ax = index is state 1118 <1> ; jc short .error_CY_3 ; (state.st is always < 12) 1119 000005E3 01C7 <1> add di, ax ; es:di -> bm_rep0[state()] 1120 000005E5 7219 <1> jc short .error_CY_3 1121 000005E7 E8A5FC <1> call Range_decoder.decode_bit 1122 000005EA 7233 <1> jc .3rd_bit_not_zero 1123 <1> 1124 <1> .3rd_bit_zero: 1125 000005EC 1E <1> push ds 1126 000005ED 07 <1> pop es 1127 000005EE 8DBFF030 <1> lea di, [bx + bm_len] ; es:di -> bm_len 2D array 1128 000005F2 B80800 <1> mov ax, bit_model_size * pos_states 1129 <1> ; (2 * 4 = 8) 1130 000005F5 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 000005F8 0346EC <2> add ax, word [bp + ?pos_state] 1140 <2> 1141 <2> 1142 <2> 1139 000005FB 0346EC <2> add ax, word [bp + ?pos_state] 1140 <2> 1141 <2> 1142 <2> 1144 000005FE 01C7 <1> add di, ax ; es:di -> bm_len[state()] 1145 <1> .error_CY_3: 1146 00000600 722A <1> jc short .error_CY_4 1147 00000602 E88AFC <1> call Range_decoder.decode_bit 1148 00000605 7303E99500 <1> jc .4th_bit_not_zero 1149 <1> 1150 <1> .4th_bit_zero: 1151 <1> ; State.set_short_rep 1152 0000060A B8090B <1> mov ax, 9 | (11 << 8) 1153 0000060D E802FC <1> call State.select 1154 <1> 1155 00000610 8B4718 <1> mov ax, word [bx + rep0] 1156 00000613 8B571A <1> mov dx, word [bx + rep0 + 2] 1157 00000616 E8C6FD <1> call LZ_decoder.peek 1158 00000619 E80703 <1> call LZ_decoder.put_byte 1159 0000061C E92BFF <1> jmp .loop 1160 <1> 1161 <1> .3rd_bit_not_zero: 1162 0000061F 1E <1> push ds 1163 00000620 07 <1> pop es 1164 00000621 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 00000625 8B4728 <1> mov ax, word [bx + state.st] 1169 00000628 01C0 <1> add ax, ax ; ax = index is state 1170 <1> ; jc short .error_CY_4 ; (state.st is always < 12) 1171 0000062A 01C7 <1> add di, ax ; es:di -> bm_rep1[state()] 1172 <1> .error_CY_4: 1173 0000062C 7220 <1> jc short .error_CY_4a 1174 0000062E E85EFC <1> call Range_decoder.decode_bit 1175 00000631 720E <1> jc .3rd_bit_not_zero.4th_bit_not_zero 1176 <1> 1177 <1> .3rd_bit_not_zero.4th_bit_zero: 1178 00000633 FF771E <1> push word [bx + rep1 + 2] 1179 00000636 FF771C <1> push word [bx + rep1] 1180 00000639 8F46F8 <1> pop word [bp + ?distance] 1181 0000063C 8F46FA <1> pop word [bp + ?distance + 2] 1182 0000063F EB46 <1> jmp .3rd_bit_not_zero.common 1183 <1> 1184 <1> .3rd_bit_not_zero.4th_bit_not_zero: 1185 00000641 1E <1> push ds 1186 00000642 07 <1> pop es 1187 00000643 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 00000647 8B4728 <1> mov ax, word [bx + state.st] 1192 0000064A 01C0 <1> add ax, ax ; ax = index is state 1193 <1> ; jc short .error_CY_5 ; (state.st is always < 12) 1194 0000064C 01C7 <1> add di, ax ; es:di -> bm_rep2[state()] 1195 <1> .error_CY_4a: 1196 0000064E 7267 <1> jc short .error_CY_5 1197 00000650 E83CFC <1> call Range_decoder.decode_bit 1198 00000653 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 00000655 FF7722 <1> push word [bx + rep2 + 2] 1202 00000658 FF7720 <1> push word [bx + rep2] 1203 0000065B 8F46F8 <1> pop word [bp + ?distance] 1204 0000065E 8F46FA <1> pop word [bp + ?distance + 2] 1205 00000661 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 00000663 FF7726 <1> push word [bx + rep3 + 2] 1209 00000666 FF7724 <1> push word [bx + rep3] 1210 00000669 8F46F8 <1> pop word [bp + ?distance] 1211 0000066C 8F46FA <1> pop word [bp + ?distance + 2] ; distance = rep3 1212 0000066F FF7722 <1> push word [bx + rep2 + 2] 1213 00000672 FF7720 <1> push word [bx + rep2] 1214 00000675 8F4724 <1> pop word [bx + rep3] 1215 00000678 8F4726 <1> pop word [bx + rep3 + 2] ; rep3 = rep2 1216 <1> 1217 <1> .3rd_bit_not_zero.4th_bit_not_zero.common: 1218 0000067B FF771E <1> push word [bx + rep1 + 2] 1219 0000067E FF771C <1> push word [bx + rep1] 1220 00000681 8F4720 <1> pop word [bx + rep2] 1221 00000684 8F4722 <1> pop word [bx + rep2 + 2] ; rep2 = rep1 1222 <1> 1223 <1> .3rd_bit_not_zero.common: 1224 00000687 FF771A <1> push word [bx + rep0 + 2] 1225 0000068A FF7718 <1> push word [bx + rep0] 1226 0000068D 8F471C <1> pop word [bx + rep1] 1227 00000690 8F471E <1> pop word [bx + rep1 + 2] ; rep1 = rep0 1228 00000693 FF76FA <1> push word [bp + ?distance + 2] 1229 00000696 FF76F8 <1> push word [bp + ?distance] 1230 00000699 8F4718 <1> pop word [bx + rep0] 1231 0000069C 8F471A <1> pop word [bx + rep0 + 2] ; rep0 = distance 1232 <1> 1233 <1> .4th_bit_not_zero: 1234 <1> ; State.set_rep 1235 0000069F B8080B <1> mov ax, 8 | (11 << 8) 1236 000006A2 E86DFB <1> call State.select 1237 <1> 1238 000006A5 8B46EC <1> mov ax, word [bp + ?pos_state] ; ax = pos_state variable 1239 000006A8 1E <1> push ds 1240 000006A9 07 <1> pop es 1241 000006AA 8DBFDA36 <1> lea di, [bx + rep_len_model] ; -> len_model to use 1242 000006AE E8CDFC <1> call Range_decoder.decode_len ; dx:ax = length 1243 000006B1 83C002 <1> add ax, min_match_len 1244 000006B4 83D200 <1> adc dx, 0 1245 <1> .error_CY_5: 1246 000006B7 7250 <1> jc short .error_CY_6 1247 000006B9 8946F4 <1> mov word [bp + ?len], ax 1248 000006BC 8956F6 <1> mov word [bp + ?len + 2], dx 1249 000006BF E93001 <1> jmp .handle_match 1250 <1> 1251 <1> .2nd_bit_zero: ; match 1252 000006C2 FF7722 <1> push word [bx + rep2 + 2] 1253 000006C5 FF7720 <1> push word [bx + rep2] 1254 000006C8 8F4724 <1> pop word [bx + rep3] 1255 000006CB 8F4726 <1> pop word [bx + rep3 + 2] ; rep3 = rep2 1256 <1> 1257 000006CE FF771E <1> push word [bx + rep1 + 2] 1258 000006D1 FF771C <1> push word [bx + rep1] 1259 000006D4 8F4720 <1> pop word [bx + rep2] 1260 000006D7 8F4722 <1> pop word [bx + rep2 + 2] ; rep2 = rep1 1261 <1> 1262 000006DA FF771A <1> push word [bx + rep0 + 2] 1263 000006DD FF7718 <1> push word [bx + rep0] 1264 000006E0 8F471C <1> pop word [bx + rep1] 1265 000006E3 8F471E <1> pop word [bx + rep1 + 2] ; rep1 = rep0 1266 <1> 1267 000006E6 8B46EC <1> mov ax, word [bp + ?pos_state] ; ax = pos_state variable 1268 000006E9 1E <1> push ds 1269 000006EA 07 <1> pop es 1270 000006EB 8DBF5634 <1> lea di, [bx + match_len_model] ; -> len_model to use 1271 000006EF E88CFC <1> call Range_decoder.decode_len ; dx:ax = length 1272 <1> 1273 000006F2 8946EE <1> mov word [bp + ?len_state], ax 1274 000006F5 85D2 <1> test dx, dx 1275 000006F7 7505 <1> jnz @F 1276 000006F9 83F803 <1> cmp ax, len_states - 1 1277 000006FC 7205 <1> jb @FF 1278 <1> @@: 1279 000006FE C746EE0300 <1> mov word [bp + ?len_state], len_states - 1 1280 <1> @@: 1281 <1> 1282 00000703 83C002 <1> add ax, min_match_len 1283 00000706 83D200 <1> adc dx, 0 1284 <1> .error_CY_6: 1285 00000709 723C <1> jc short .error_CY_7 1286 <1> 1287 0000070B 8946F4 <1> mov word [bp + ?len], ax 1288 0000070E 8956F6 <1> mov word [bp + ?len + 2], dx 1289 <1> 1290 00000711 1E <1> push ds 1291 00000712 07 <1> pop es 1292 00000713 8DBF5031 <1> lea di, [bx + bm_dis_slot] ; -> 2D array bm_dis_slot 1293 <1> 1294 00000717 B88000 <1> mov ax, bit_model_size * (1 << dis_slot_bits) 1295 0000071A F766EE <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 0000071D 01C7 <1> add di, ax ; -> 1D array at bm_dis_slot[len_state] 1302 0000071F B90600 <1> mov cx, dis_slot_bits 1303 00000722 E8CFFB <1> call Range_decoder.decode_tree 1304 00000725 894718 <1> mov word [bx + rep0], ax 1305 00000728 89571A <1> mov word [bx + rep0 + 2], dx 1306 <1> 1307 0000072B 85D2 <1> test dx, dx ; (same flags as cmp dx, 0) 1308 0000072D 7503 <1> jne @F 1309 0000072F 83F804 <1> cmp ax, start_dis_model 1310 <1> @@: 1311 00000732 7303E99B00 <1> jnae .not_rep0_ae_start_dis_model 1312 <1> 1313 <1> .rep0_ae_start_dis_model: 1314 00000737 8946F0 <1> mov word [bp + ?dis_slot], ax 1315 0000073A 8956F2 <1> mov word [bp + ?dis_slot + 2], dx 1316 <1> 1317 0000073D D1EA <1> shr dx, 1 1318 0000073F D1D8 <1> rcr ax, 1 ; dis_slot >> 1 1319 00000741 83E801 <1> sub ax, 1 1320 00000744 83DA00 <1> sbb dx, 0 ; - 1 1321 <1> .error_CY_7: 1322 <1> .error_CY_8: 1323 00000747 7230 <1> jc short .error_CY_9 1324 00000749 F9 <1> stc 1325 0000074A 752D <1> jnz short .error_CY_9 1326 0000074C 91 <1> xchg cx, ax ; cx = direct_bits, clobber ax 1327 0000074D 31D2 <1> xor dx, dx 1328 0000074F B80100 <1> mov ax, 1 1329 00000752 2246F0 <1> and al, byte [bp + ?dis_slot] 1330 00000755 0C02 <1> or al, 2 1331 00000757 51 <1> push cx 1332 00000758 E306 <1> jcxz @FF 1333 <1> @@: 1334 0000075A D1E0 <1> shl ax, 1 1335 0000075C D1D2 <1> rcl dx, 1 1336 0000075E E2FA <1> loop @B 1337 <1> @@: 1338 00000760 59 <1> pop cx 1339 00000761 894718 <1> mov word [bx + rep0], ax 1340 00000764 89571A <1> mov word [bx + rep0 + 2], dx 1341 <1> 1342 00000767 837EF200 <1> cmp word [bp + ?dis_slot + 2], 0 1343 0000076B 7504 <1> jne @F 1344 0000076D 837EF00E <1> cmp word [bp + ?dis_slot], end_dis_model 1345 <1> @@: 1346 00000771 7328 <1> jnb .not_dis_slot_below_end_dis_model 1347 <1> 1348 <1> .dis_slot_below_end_dis_model: 1349 00000773 2B46F0 <1> sub ax, word [bp + ?dis_slot] 1350 00000776 1B56F2 <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 00000779 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 0000077B 01C0 <1> add ax, ax 1360 0000077D 11D2 <1> adc dx, dx ; dx:ax *= 2 1361 0000077F 7227 <1> jc short .error_CY_10 1362 00000781 F9 <1> stc 1363 00000782 7524 <1> jnz short .error_CY_10 ; if dx != 0 --> 1364 00000784 1E <1> push ds 1365 00000785 07 <1> pop es 1366 00000786 8DBF5033 <1> lea di, [bx + bm_dis] ; es:di -> bm_dis array 1367 0000078A 01C7 <1> add di, ax ; index into the array 1368 0000078C 721A <1> jc short .error_CY_10 1369 0000078E E88FFB <1> call Range_decoder.decode_tree_reversed 1370 00000791 014718 <1> add word [bx + rep0], ax 1371 00000794 11571A <1> adc word [bx + rep0 + 2], dx 1372 00000797 720F <1> jc short .error_CY_10 1373 00000799 EB37 <1> jmp .after_dis_slot_below 1374 <1> 1375 <1> .not_dis_slot_below_end_dis_model: 1376 0000079B 83E904 <1> sub cx, dis_align_bits 1377 0000079E E8BBFA <1> call Range_decoder.decode 1378 000007A1 B90400 <1> mov cx, dis_align_bits 1379 <1> @@: 1380 000007A4 D1E0 <1> shl ax, 1 1381 000007A6 D1D2 <1> rcl dx, 1 1382 <1> .error_CY_10: 1383 000007A8 721A <1> jc short .error_CY_11 1384 000007AA E2F8 <1> loop @B 1385 000007AC 014718 <1> add word [bx + rep0], ax 1386 000007AF 11571A <1> adc word [bx + rep0 + 2], dx 1387 <1> 1388 000007B2 B90400 <1> mov cx, dis_align_bits 1389 000007B5 1E <1> push ds 1390 000007B6 07 <1> pop es 1391 000007B7 8DBF3634 <1> lea di, [bx + bm_align] 1392 000007BB E862FB <1> call Range_decoder.decode_tree_reversed 1393 000007BE 014718 <1> add word [bx + rep0], ax 1394 000007C1 11571A <1> adc word [bx + rep0 + 2], dx 1395 <1> .error_CY_11: 1396 000007C4 727D <1> jc .error_CY_12 1397 <1> 1398 000007C6 837F1AFF <1> cmp word [bx + rep0 + 2], -1 ; rep0 = 0FFFF_FFFFh ? 1399 000007CA 7504 <1> jne @F 1400 000007CC 837F18FF <1> cmp word [bx + rep0], -1 1401 <1> @@: 1402 000007D0 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 000007D2 B8070A <1> mov ax, 7 | (10 << 8) 1410 000007D5 E83AFA <1> call State.select 1411 <1> 1412 000007D8 8B571A <1> mov dx, word [bx + rep0 + 2] 1413 000007DB 8B4718 <1> mov ax, word [bx + rep0] 1414 <1> 1415 000007DE 3B5712 <1> cmp dx, word [bx + lz_decoder.dictionary_size + 2] 1416 000007E1 7503 <1> jne @F 1417 000007E3 3B4710 <1> cmp ax, word [bx + lz_decoder.dictionary_size] 1418 <1> @@: 1419 000007E6 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 000007E8 3B5716 <1> cmp dx, word [bx + lz_decoder.pos + 2] 1424 000007EB 7503 <1> jne @F 1425 000007ED 3B4714 <1> cmp ax, word [bx + lz_decoder.pos] 1426 <1> @@: 1427 <1> .error_AE_1: 1428 000007F0 7356 <1> jae short .error_1 1429 <1> 1430 <1> .handle_match: 1431 000007F2 8B571A <1> mov dx, word [bx + rep0 + 2] 1432 000007F5 8B4718 <1> mov ax, word [bx + rep0] 1433 <1> 1434 000007F8 E8FBFB <1> call calculate_peek_pointer_disi 1435 <1> 1436 000007FB 8B46F4 <1> mov ax, word [bp + ?len] 1437 000007FE 8B56F6 <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 00000801 014714 <1> add word [bx + lz_decoder.pos], ax 1453 00000804 115716 <1> adc word [bx + lz_decoder.pos + 2], dx 1454 00000807 723A <1> jc short .error_CY_12 ; (CY) --> 1455 <1> 1456 00000809 2946DC <1> sub word [bp + ?length_of_destination], ax 1457 0000080C 1956DE <1> sbb word [bp + ?length_of_destination + 2], dx 1458 <1> ; enough space left ? 1459 0000080F 7232 <1> jb short .error_CY_12 ; no --> (below == CY) 1460 <1> 1461 00000811 1E <1> push ds 1462 <1> 1463 00000812 8EDF <1> mov ds, di ; ds:si -> source 1464 00000814 C47ED4 <1> les di, [bp + ?dst] ; es:di -> destination 1465 <1> .hm_loop: 1466 00000817 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 0000081A 85D2 <1> test dx, dx ; >= 1_0000h ? 1471 0000081C 7508 <1> jnz @F ; yes, full block --> 1472 0000081E 85C0 <1> test ax, ax ; == 0 ? 1473 00000820 7415 <1> jz .hm_end ; yes, done --> 1474 00000822 39C8 <1> cmp ax, cx ; can move in one (last) block ? 1475 00000824 7607 <1> jbe .hm_last ; yes --> 1476 <1> @@: 1477 <1> ; no, move one block and continue 1478 00000826 29C8 <1> sub ax, cx 1479 00000828 83DA00 <1> sbb dx, 0 ; left over remaining 1480 0000082B EB03 <1> jmp .hm_copy 1481 <1> 1482 <1> .hm_last: 1483 0000082D 91 <1> xchg cx, ax ; cx = remaining length 1484 0000082E 31C0 <1> xor ax, ax ; no more remaining 1485 <1> 1486 <1> .hm_copy: 1487 00000830 F3A4 <1> rep movsb ; move one block (full or partial) 1488 <1> 1489 00000832 E83D02 <1> call normalise_both_pointers 1490 00000835 EBE0 <1> jmp .hm_loop 1491 <1> 1492 <1> .hm_end: 1493 00000837 897ED4 <1> mov word [bp + ?dst], di 1494 0000083A 8C46D6 <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 0000083D 1F <1> pop ds 1503 <1> %if _ALLOW_OVERLAPPING 1504 0000083E 53 <1> push bx 1505 0000083F E81402 <1> call check_pointers_not_overlapping 1506 00000842 5B <1> pop bx ; returns CF 1507 <1> .error_CY_12: 1508 00000843 7203 <1> jc short .error_1 1509 <1> %endif 1510 00000845 E902FD <1> jmp .loop 1511 <1> 1512 <1> %if ! _ALLOW_OVERLAPPING 1513 <1> .error_CY_12: 1514 <1> %endif 1515 <1> .error_1: 1516 00000848 E9A000 <1> jmp .error 1517 <1> 1518 <1> 1519 <1> .end_member: ; End Of Stream marker 1520 0000084B 837EF600 <1> cmp word [bp + ?len + 2], min_match_len >> 16 1521 0000084F 7504 <1> jne @F 1522 00000851 837EF402 <1> cmp word [bp + ?len], min_match_len & 0FFFFh 1523 <1> @@: 1524 00000855 75F1 <1> jne short .error_1 1525 <1> 1526 <1> ; decode_member succeeded 1527 <1> 1528 00000857 C55EE4 <1> lds bx, [bp + ?final_dst] ; -> localvariables 1529 <1> 1530 0000085A 836EE014 <1> sub word [bp + ?length_of_source], lzip_trailer_size 1531 0000085E 835EE200 <1> sbb word [bp + ?length_of_source + 2], 0 1532 00000862 7303E98400 <1> jc .error 1533 <1> 1534 00000867 C476E8 <1> les si, [bp + ?src] ; es:si -> lzip_trailer.uncompressed_checksum 1535 0000086A 83C604 <1> add si, 4 ; skip CRC 1536 <1> 1537 <1> ; es:si -> lzip_trailer.uncompressed_size 1538 0000086D 26AD <1> es lodsw ; does the destination length match ? 1539 0000086F 3B4714 <1> cmp ax, word [bx + lz_decoder.pos] 1540 00000872 7577 <1> jne .error 1541 00000874 26AD <1> es lodsw 1542 00000876 3B4716 <1> cmp ax, word [bx + lz_decoder.pos + 2] 1543 00000879 7570 <1> jne .error ; if no --> 1544 0000087B 26AD <1> es lodsw 1545 0000087D 85C0 <1> test ax, ax 1546 0000087F 756A <1> jnz .error 1547 00000881 26AD <1> es lodsw 1548 00000883 85C0 <1> test ax, ax 1549 00000885 7564 <1> jnz .error 1550 <1> 1551 00000887 830714 <1> add word [bx + lz_decoder.range_decoder + range_decoder.member_pos], lzip_trailer_size 1552 0000088A 83570200 <1> adc word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2], 0 1553 0000088E 725B <1> jc .error 1554 <1> 1555 <1> ; es:si -> lzip_trailer.member_size 1556 00000890 26AD <1> es lodsw ; does the source length match ? 1557 00000892 3B07 <1> cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos] 1558 00000894 7555 <1> jne .error 1559 00000896 26AD <1> es lodsw 1560 00000898 3B4702 <1> cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2] 1561 0000089B 754E <1> jne .error 1562 0000089D 26AD <1> es lodsw 1563 0000089F 85C0 <1> test ax, ax 1564 000008A1 7548 <1> jnz .error 1565 000008A3 26AD <1> es lodsw 1566 000008A5 85C0 <1> test ax, ax 1567 000008A7 7542 <1> jnz .error 1568 <1> 1569 <1> ; es:si -> behind lzip_trailer 1570 000008A9 06 <1> push es 1571 000008AA 56 <1> push si 1572 000008AB E8D301 <1> call normalise_pointer 1573 000008AE 8F46E8 <1> pop word [bp + ?src] 1574 000008B1 8F46EA <1> pop word [bp + ?src + 2] 1575 <1> 1576 000008B4 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 000008B7 C47EE4 <1> les di, [bp + ?final_dst] 1586 <1> ; -> destination 1587 000008BA C576D8 <1> lds si, [bp + ?original_dst] 1588 <1> ; -> source 1589 000008BD 1E <1> push ds 1590 000008BE 56 <1> push si 1591 000008BF E81002 <1> call pointer_to_linear ; dx:ax = linear ?original_dst 1592 000008C2 91 <1> xchg cx, ax 1593 000008C3 87DA <1> xchg bx, dx ; bx:cx = linear ?original_dst, clobber dx:ax 1594 000008C5 FF76D6 <1> push word [bp + ?dst + 2] 1595 000008C8 FF76D4 <1> push word [bp + ?dst] 1596 000008CB E80402 <1> call pointer_to_linear 1597 000008CE 29C8 <1> sub ax, cx 1598 000008D0 19DA <1> sbb dx, bx ; = linear dst minus linear original_dst 1599 <1> 1600 000008D2 B90400 <1> mov cx, 4 1601 000008D5 83C00F <1> add ax, 15 1602 000008D8 83D200 <1> adc dx, 0 1603 <1> @@: 1604 000008DB D1EA <1> shr dx, 1 1605 000008DD D1D8 <1> rcr ax, 1 1606 000008DF E2FA <1> loop @B 1607 000008E1 89C1 <1> mov cx, ax 1608 000008E3 85D2 <1> test dx, dx 1609 <1> d0 mov byte [bp + ?errordata], 84h 1610 000008E5 7504 <1> jnz .error 1611 <1> 1612 000008E7 E8D400 <1> call x_mov_p 1613 <1> 1614 000008EA A8 <1> db __TEST_IMM8 ; (NC) 1615 <1> .error: 1616 000008EB F9 <1> stc 1617 <1> 1618 <1> %if _COUNTER 1619 000008EC 9F <1> lahf 1620 000008ED B00D <1> mov al, 13 1621 000008EF E8BEF8 <1> call disp_al_for_progress 1622 000008F2 B00A <1> mov al, 10 1623 000008F4 E8B9F8 <1> call disp_al_for_progress 1624 000008F7 9E <1> sahf 1625 <1> %endif 1626 <1> d0 mov bx, word [bp + ?errordata] 1627 000008F8 89EC5D <1> lleave code 1628 000008FB 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 000008FC 830701 <1> add word [bx + range_decoder.member_pos], 1 1639 000008FF 83570200 <1> adc word [bx + range_decoder.member_pos + 2], 0 1640 00000903 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 00000905 1E <1> push ds 1650 00000906 56 <1> push si 1651 <1> 1652 00000907 836EE001 <1> sub word [bp + ?length_of_source], 1 1653 0000090B 835EE200 <1> sbb word [bp + ?length_of_source + 2], 0 1654 0000090F 72DA <1> jc short .error 1655 <1> 1656 00000911 C576E8 <1> lds si, [bp + ?src] 1657 00000914 AC <1> lodsb 1658 00000915 1E <1> push ds 1659 00000916 56 <1> push si 1660 00000917 E86701 <1> call normalise_pointer 1661 0000091A 8F46E8 <1> pop word [bp + ?src] 1662 0000091D 8F46EA <1> pop word [bp + ?src + 2] 1663 00000920 5E <1> pop si 1664 00000921 1F <1> pop ds 1665 00000922 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 00000923 C47ED4 <1> les di, [bp + ?dst] 1677 <1> 1678 00000926 83471401 <1> add word [bx + lz_decoder.pos], 1 1679 0000092A 83571600 <1> adc word [bx + lz_decoder.pos + 2], 0 1680 0000092E 72BB <1> jc short .error 1681 <1> 1682 00000930 836EDC01 <1> sub word [bp + ?length_of_destination], 1 1683 00000934 835EDE00 <1> sbb word [bp + ?length_of_destination + 2], 0 1684 00000938 72B1 <1> jb short .error 1685 <1> 1686 0000093A AA <1> stosb 1687 0000093B 06 <1> push es 1688 0000093C 57 <1> push di 1689 0000093D E84101 <1> call normalise_pointer 1690 00000940 8F46D4 <1> pop word [bp + ?dst] 1691 00000943 8F46D6 <1> pop word [bp + ?dst + 2] 1692 <1> 1693 <1> %if _ALLOW_OVERLAPPING 1694 00000946 53 <1> push bx 1695 00000947 E80C01 <1> call check_pointers_not_overlapping 1696 0000094A 5B <1> pop bx ; returns CF 1697 0000094B 729E <1> jc short .error 1698 <1> %endif 1699 0000094D 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 0000094E 1E <1> push ds 1710 0000094F 56 <1> push si 1711 00000950 E80A00 <1> call anti_normalise_pointer 1712 00000953 5E <1> pop si 1713 00000954 1F <1> pop ds 1714 <1> 1715 00000955 06 <1> push es 1716 00000956 57 <1> push di 1717 00000957 E80300 <1> call anti_normalise_pointer 1718 0000095A 5F <1> pop di 1719 0000095B 07 <1> pop es 1720 0000095C 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 0000095D 5589E5 <1> lenter 1734 00000960 53 <1> push bx 1735 00000961 51 <1> push cx 1736 <1> 1737 00000962 31DB <1> xor bx, bx 1738 00000964 31C9 <1> xor cx, cx 1739 00000966 FF7606 <1> push word [bp + ?segment] 1740 00000969 FF7604 <1> push word [bp + ?offset] 1741 0000096C E80A00 <1> call anti_normalise_pointer_with_displacement_bxcx 1742 0000096F 8F4604 <1> pop word [bp + ?offset] 1743 00000972 8F4606 <1> pop word [bp + ?segment] 1744 <1> 1745 00000975 59 <1> pop cx 1746 00000976 5B <1> pop bx 1747 00000977 5D <1> lleave 1748 00000978 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 00000979 5589E5 <1> lenter 1765 0000097C 50 <1> push ax 1766 0000097D 52 <1> push dx 1767 <1> 1768 0000097E FF7606 <1> push word [bp + ?segment] 1769 00000981 FF7604 <1> push word [bp + ?offset] 1770 00000984 E84B01 <1> call pointer_to_linear 1771 <1> 1772 00000987 01C8 <1> add ax, cx 1773 00000989 11DA <1> adc dx, bx ; dx:ax += bx:cx 1774 <1> 1775 0000098B 83FA01 <1> cmp dx, 1 1776 0000098E 7223 <1> jb @F 1777 <1> 1778 00000990 50 <1> push ax 1779 00000991 83C8F0 <1> or ax, 0FFF0h 1780 00000994 894604 <1> mov word [bp + ?offset], ax 1781 00000997 58 <1> pop ax 1782 <1> 1783 00000998 83E8F0 <1> sub ax, 0FFF0h 1784 0000099B 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 0000099E D1EA <2> shr dx, 1 1788 000009A0 D1D8 <2> rcr ax, 1 1787 000009A2 D1EA <2> shr dx, 1 1788 000009A4 D1D8 <2> rcr ax, 1 1787 000009A6 D1EA <2> shr dx, 1 1788 000009A8 D1D8 <2> rcr ax, 1 1787 000009AA D1EA <2> shr dx, 1 1788 000009AC D1D8 <2> rcr ax, 1 1790 000009AE 894606 <1> mov word [bp + ?segment], ax 1791 <1> 1792 000009B1 EB07 <1> jmp .return 1793 <1> 1794 <1> ; dx:ax = 0000:offset 1795 <1> @@: 1796 000009B3 894604 <1> mov word [bp + ?offset], ax 1797 000009B6 83660600 <1> and word [bp + ?segment], 0 1798 <1> 1799 <1> .return: 1800 000009BA 5A <1> pop dx 1801 000009BB 58 <1> pop ax 1802 000009BC 5D <1> lleave 1803 000009BD 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 000009BE E8B100 <1> call normalise_both_pointers 1818 000009C1 8CD8 <1> mov ax, ds 1819 000009C3 8CC2 <1> mov dx, es 1820 <1> 1821 000009C5 85C9 <1> test cx, cx 1822 000009C7 7503E98800 <1> jz .return 1823 <1> 1824 000009CC 39D0 <1> cmp ax, dx ; source above destination ? 1825 000009CE 7716 <1> ja .up ; yes, move up (forwards) --> 1826 000009D0 7206 <1> jb .check_down 1827 <1> 1828 000009D2 39FE <1> cmp si, di 1829 000009D4 7710 <1> ja .up 1830 000009D6 747C <1> je .return ; pointers are the same, no need to move --> 1831 <1> .check_down: 1832 000009D8 50 <1> push ax 1833 000009D9 01C8 <1> add ax, cx ; (expected not to carry) 1834 000009DB 39D0 <1> cmp ax, dx ; end of source is above destination ? 1835 000009DD 58 <1> pop ax 1836 000009DE 7726 <1> ja .down ; yes, move from top down --> 1837 000009E0 7204 <1> jb .up 1838 000009E2 39FE <1> cmp si, di 1839 000009E4 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 000009E6 81E9FF0F <1> sub cx, 0FFFh ; 64 KiB - 16 B left ? 1846 000009EA 760C <1> jbe .uplast ; no --> 1847 000009EC 51 <1> push cx 1848 000009ED B9F87F <1> mov cx, 0FFF0h /2 1849 000009F0 F3A5 <1> rep movsw ; move 64 KiB - 16 B 1850 000009F2 59 <1> pop cx 1851 000009F3 E87C00 <1> call normalise_both_pointers 1852 000009F6 EBEE <1> jmp short .uploop ; proceed for more --> 1853 <1> .uplast: 1854 000009F8 81C1FF0F <1> add cx, 0FFFh ; restore counter 1855 000009FC D1E1 <1> shl cx, 1 1856 000009FE D1E1 <1> shl cx, 1 1857 00000A00 D1E1 <1> shl cx, 1 ; *8, paragraphs to words 1858 00000A02 F3A5 <1> rep movsw ; move last part 1859 00000A04 EB4E <1> jmp short .return 1860 <1> 1861 <1> .down: 1862 00000A06 FD <1> std ; _AMD_ERRATUM_109_WORKAROUND as below 1863 <1> 1864 00000A07 89C8 <1> mov ax, cx 1865 00000A09 31DB <1> xor bx, bx 1866 00000A0B 51 <1> push cx 1867 00000A0C B90400 <1> mov cx, 4 1868 <1> @@: 1869 00000A0F D1E0 <1> shl ax, 1 1870 00000A11 D1D3 <1> rcl bx, 1 1871 00000A13 E2FA <1> loop @B 1872 00000A15 83E802 <1> sub ax, 2 1873 00000A18 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 00000A1B 91 <1> xchg ax, cx ; bx:cx = displacement to point to last word 1878 00000A1C 1E <1> push ds 1879 00000A1D 56 <1> push si 1880 00000A1E E858FF <1> call anti_normalise_pointer_with_displacement_bxcx 1881 00000A21 5E <1> pop si 1882 00000A22 1F <1> pop ds ; -> last word of source 1883 00000A23 06 <1> push es 1884 00000A24 57 <1> push di 1885 00000A25 E851FF <1> call anti_normalise_pointer_with_displacement_bxcx 1886 00000A28 5F <1> pop di 1887 00000A29 07 <1> pop es ; -> last word of destination 1888 00000A2A 59 <1> pop cx 1889 <1> 1890 <1> .dnloop: 1891 00000A2B 81E9FF0F <1> sub cx, 0FFFh ; 64 KiB - 16 B left ? 1892 00000A2F 760C <1> jbe .dnlast ; no --> 1893 00000A31 51 <1> push cx 1894 00000A32 B9F87F <1> mov cx, 0FFF0h /2 1895 00000A35 F3A5 <1> rep movsw ; move 64 KiB - 16 B 1896 00000A37 59 <1> pop cx 1897 00000A38 E813FF <1> call anti_normalise_both_pointers 1898 00000A3B EBEE <1> jmp short .dnloop ; proceed for more --> 1899 <1> .dnlast: 1900 00000A3D 81C1FF0F <1> add cx, 0FFFh ; restore counter 1901 00000A41 D1E1 <1> shl cx, 1 1902 00000A43 D1E1 <1> shl cx, 1 1903 00000A45 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 00000A47 E308 <1> jcxz @FF 1944 00000A49 83F914 <1> cmp cx, 20 1945 00000A4C 7703 <1> ja @FF 1946 <1> @@: 1947 00000A4E A5 <1> movsw 1948 00000A4F E2FD <1> loop @B 1949 <1> @@: 1950 <1> %endif 1951 00000A51 F3A5 <1> rep movsw ; move first part 1952 00000A53 FC <1> cld 1953 <1> .return: 1954 00000A54 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 00000A56 FF76D6 push word [bp + ?dst + 2] 1851 00000A59 FF76D4 push word [bp + ?dst] 1852 %else 1853 push es 1854 push di 1855 %endif 1856 00000A5C E87300 call pointer_to_linear 1857 1858 00000A5F 91 xchg cx, ax 1859 00000A60 87DA xchg bx, dx ; bx:cx = linear ?dst after write 1860 1861 %if CHECK_POINTERS_VARIABLE_SRC 1862 00000A62 FF76EA push word [bp + ?src + 2] 1863 00000A65 FF76E8 push word [bp + ?src] 1864 %else 1865 push ds 1866 push si 1867 %endif 1868 00000A68 E86700 call pointer_to_linear ; dx:ax = linear ?src before next read 1869 1870 00000A6B 39DA cmp dx, bx ; ?src >= ?dst ? 1871 00000A6D 7502 jne @F 1872 00000A6F 39C8 cmp ax, cx 1873 @@: 1874 ; (CY) if error (src < dst) 1875 ; (NC) if no error 1876 00000A71 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 00000A72 06 push es 1892 00000A73 57 push di 1893 00000A74 E80A00 call normalise_pointer 1894 00000A77 5F pop di 1895 00000A78 07 pop es 1896 %endif 1897 1898 normalise_dssi_pointer: 1899 00000A79 1E push ds 1900 00000A7A 56 push si 1901 00000A7B E80300 call normalise_pointer 1902 00000A7E 5E pop si 1903 00000A7F 1F pop ds 1904 00000A80 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 00000A81 5589E5 lenter 1919 1920 00000A84 837E040F cmp word [bp + ?offset], 15 1921 00000A88 7617 jbe .ret 1922 1923 00000A8A 53 push bx 1924 00000A8B 51 push cx 1925 1926 00000A8C 31DB xor bx, bx 1927 00000A8E 31C9 xor cx, cx 1928 00000A90 FF7606 push word [bp + ?segment] 1929 00000A93 FF7604 push word [bp + ?offset] 1930 00000A96 E80A00 call normalise_pointer_with_displacement_bxcx 1931 00000A99 8F4604 pop word [bp + ?offset] 1932 00000A9C 8F4606 pop word [bp + ?segment] 1933 1934 00000A9F 59 pop cx 1935 00000AA0 5B pop bx 1936 .ret: 1937 00000AA1 5D lleave 1938 00000AA2 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 00000AA3 5589E5 lenter 1953 1954 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1955 cmp word [bp + ?offset], 15 1956 jbe .ret 1957 %endif 1958 1959 00000AA6 50 push ax 1960 00000AA7 51 push cx 1961 00000AA8 52 push dx 1962 1963 00000AA9 FF7606 push word [bp + ?segment] 1964 00000AAC FF7604 push word [bp + ?offset] 1965 00000AAF 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 00000AB2 01C1 add cx, ax 1975 00000AB4 11DA adc dx, bx ; dx:cx = dx:ax + bx:cx 1976 ; pop bx 1977 00000AB6 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 00000AB7 53 push bx 1997 00000AB8 89CB mov bx, cx 1998 00000ABA 83E10F and cx, 15 1999 00000ABD 894E04 mov word [bp + ?offset], cx 2000 2001 00000AC0 B104 mov cl, 4 2002 @@: 2003 00000AC2 D1EA shr dx, 1 2004 00000AC4 D1DB rcr bx, 1 2005 00000AC6 E2FA loop @B 2006 2007 00000AC8 895E06 mov word [bp + ?segment], bx 2008 00000ACB 5B pop bx 2009 2010 ; test dx, dx 2011 ; jnz .error 2012 2013 .return: 2014 2015 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2016 00000ACC 9E sahf ; restore flags from ah 2017 %endif 2018 00000ACD 5A pop dx 2019 00000ACE 59 pop cx 2020 00000ACF 58 pop ax 2021 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2022 .ret: 2023 %endif 2024 00000AD0 5D lleave 2025 00000AD1 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 00000AD2 5589E5 lenter 2036 2037 00000AD5 8B4606 mov ax, word [bp + ?segment] 2038 00000AD8 31D2 xor dx, dx 2039 00000ADA 51 push cx 2040 00000ADB B90400 mov cx, 4 2041 @@: 2042 00000ADE D1E0 shl ax, 1 2043 00000AE0 D1D2 rcl dx, 1 2044 00000AE2 E2FA loop @B 2045 2046 00000AE4 034604 add ax, word [bp + ?offset] 2047 00000AE7 11CA adc dx, cx ; cx = 0 here 2048 00000AE9 59 pop cx 2049 2050 00000AEA 5D lleave 2051 00000AEB C20400 lret 2052 2053 2054 %if _PASSLCFG 2055 align 16 2056 transfer_lcfg_block: 2057 times lcfg.size nop 2058 %endif 2059 00000AEE 90 align 16 2060 init1_end: 2061 2062 2063 usesection INIT0 2064 %if _TEST_PROGRAM 2065 init0_msg: 2066 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 2067 .error_stderr_file: db "Error: Unable to open own executable file.",13,10 2068 .error_stderr_file.length equ $ - .error_stderr_file 2069 %endif 2070 000001B2 4572726F723A204E6F- .error_stderr: db "Error: Not enough memory allocated.",13,10 2070 000001BB 7420656E6F75676820- 2070 000001C4 6D656D6F727920616C- 2070 000001CD 6C6F63617465642E0D- 2070 000001D6 0A 2071 .error_stderr.length: equ $ - .error_stderr 2072 .error_c_stdout: 2073 000001D7 30 .error_stdout: db "0" 2074 %if 0 2075 _autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE + (payload_end - payload) + (init1_end - init1_start) + ADDITIONAL_MEMORY ) 2080 %endif 2081 000001D8 0D0A db 13,10 2082 .error_c_stdout.length: equ $ - .error_c_stdout 2083 .error_stdout.length: equ $ - .error_stdout 2084 2085 000001DA 90 align 1024 2086 %if ($ - $$) != 1024 2087 %error Wrong INIT0 size 2088 %endif 2089 %endif 2090 2091 align 16 2092 init0_end: 2093 2094 2095 %assign num (init1_end - init1_start) + (init0_end - init0_start) 2096 %if _BRIEFLZ 2097 %define which iniblz 2098 %elif _LZ4 2099 %define which inilz4 2100 %elif _SNAPPY 2101 %define which inisz 2102 %elif _EXODECR 2103 %define which iniexo 2104 %elif _X 2105 %define which inix 2106 %elif _HEATSHRINK 2107 %define which inihs 2108 %elif _LZD 2109 %define which inilz 2110 %elif _LZO 2111 %define which inilzo 2112 %elif _LZSA2 2113 %define which inilzsa2 2114 %elif _APL 2115 %define which iniapl 2116 %elif _BZP 2117 %define which inibzp 2118 %elif _ZEROCOMP 2119 %define which inizero 2120 %elif _MVCOMP 2121 %define which inimv 2122 %elif _LZEXEDAT 2123 %define which inilzexe 2124 %endif 2125 %warning which: num bytes used for depacker 2125 ****************** warning: inilz: 3824 bytes used for depacker [-w+user] 2126 2127 2128 %if _TEST_PROGRAM 2129 addsection INIT2, align=16 follows=INIT1 vstart=0 2130 init2_start: 2131 ; si => after PSP 2132 ; cs => INIT2 2133 ; psp, free, payload, init1, init2, payload space, stack 2134 ; 2135 ; The correct allocation for the test program 2136 ; is image size (init0, payload, init1, init2) 2137 ; minus init0 plus compressed payload size 2138 ; plus decompressed size plus stack. For 2139 ; simplicity, init0 subtraction may be skipped. 2140 2141 ; ss:sp -> word amount repetitions, word ax 2142 ; bx = 1 if A mode test, 2143 ; 8001h if B mode test, 2144 ; 4001h if C mode test 2145 00000000 53 push bx ; push into ?whichtest 2146 2147 lframe 0 2148 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 2149 lpar word, handle 2150 %endif 2151 lpar word, repetitions 2152 lpar word, whichtest 2153 %if _RELOAD_XMS 2154 lvar dword, xmsentry 2155 lvar word, xmshandle 2156 %endif 2157 %if _INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2158 lequ 128, buffersize 2159 lvar ?buffersize, buffer 2160 %endif 2161 00000001 5589E5 lenter 2162 2163 %if _RELOAD_FILE && _RELOAD_XMS 2164 or word [bp + ?xmshandle], -1 2165 %endif 2166 2167 00000004 8B5604 mov dx, word [bp + ?repetitions] 2168 00000007 83FAFF cmp dx, -1 2169 0000000A 7509 jne @F 2170 2171 .cmdline_error: 2172 %if _DEBUG0 2173 mov bx, -1 2174 %endif 2175 0000000C BA[D602] mov dx, init2_msg.cmdline_error 2176 0000000F B92400 mov cx, init2_msg.cmdline_error.length 2177 00000012 E98401 jmp init2_error 2178 2179 2180 @@: 2181 00000015 F6460340 testopt [bp + ?whichtest], 4000h 2182 00000019 750C jnz .a_or_c 2183 0000001B F6460380 testopt [bp + ?whichtest], 8000h 2184 0000001F 7406 jz .a_or_c 2185 .b: 2186 00000021 85D2 test dx, dx 2187 00000023 74E7 jz .cmdline_error 2188 00000025 EB04 jmp @F 2189 2190 .a_or_c: 2191 00000027 85D2 test dx, dx 2192 00000029 75E1 jnz .cmdline_error 2193 @@: 2194 2195 %if _RELOAD_XMS 2196 push si 2197 mov ax, 4300h 2198 int 2Fh 2199 cmp al, 80h 2200 %if _RELOAD_FILE 2201 jne .noxms 2202 %else 2203 jne init2_error_xms 2204 %endif 2205 mov ax, 4310h 2206 int 2Fh 2207 mov word [bp + ?xmsentry], bx 2208 mov word [bp + ?xmsentry + 2], es 2209 mov ah, 09h 2210 mov dx, KiB(payload_end - payload) 2211 call far [bp + ?xmsentry] 2212 cmp ax, 1 2213 %if _RELOAD_FILE 2214 jne .noxms 2215 %else 2216 jne init2_error_xms 2217 %endif 2218 mov word [bp + ?xmshandle], dx 2219 mov ax, cs 2220 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2223 push cs 2224 pop ds 2225 mov si, init2_xmsm_to_save 2226 mov word [si + XMSM.dsthdl], dx 2227 mov word [si + XMSM.srcadr + 2], ax 2228 %ifn _RELOAD_FILE 2229 push ax 2230 %endif 2231 mov ah, 0Bh 2232 call far [bp + ?xmsentry] 2233 cmp ax, 1 2234 jne init2_error_xms_free 2235 %ifn _RELOAD_FILE 2236 pop ax ; => payload 2237 %else 2238 .noxms: 2239 mov ax, cs 2240 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2243 @@: 2244 %endif 2245 pop si 2246 %elif _RELOAD_FILE 2247 mov ax, cs 2248 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2251 %else 2252 0000002B 8CCA mov dx, cs 2253 0000002D 81C23914 add dx, (init2_end - init2_start) >> 4 2254 ; => payload saving area 2255 00000031 8CC8 mov ax, cs 2256 00000033 2DBE0C sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2259 00000036 B90F0C mov cx, (payload_end - payload) >> 4 2260 00000039 E8C102 call init2_movp ; copy payload to payload saving area 2261 %endif 2262 ; We save away the payload here because a failure 2263 ; to decompress generally overwrites part of that 2264 ; payload which was used as source. 2265 2266 0000003C 89C2 mov dx, ax ; dx => payload source to use 2267 0000003E 8CC8 mov ax, cs 2268 00000040 2DAF00 sub ax, (init1_end - init1_start) >> 4 2269 ; ax => INIT1 2270 00000043 BB0100 mov bx, 1 ; say we're in EXE mode 2271 00000046 52 push dx 2272 00000047 50 push ax 2273 00000048 56 push si ; si => target 2274 00000049 0E push cs 2275 0000004A E80D01 call .transfer ; call decompression 2276 0000004D 5E pop si 2277 0000004E 58 pop ax 2278 0000004F 5A pop dx 2279 ; Returns here after decompression. 2280 ; CY if error. 2281 00000050 7309 jnc @F 2282 2283 00000052 BA[2702] mov dx, init2_msg.initial_error 2284 00000055 B93C00 mov cx, init2_msg.initial_error.length 2285 00000058 E93E01 jmp init2_error_free 2286 2287 @@: 2288 %if _INCLUDE_UNCOMPRESSED 2289 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2290 payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed 2291 %else 2292 payload_uncompressed_size equ _TEST_PROGRAM_DECOMPRESSED_SIZE 2293 %endif 2294 0000005B E80201 call checkdecompressed 2295 0000005E 7409 je @F 2296 2297 %if _WRITE_WRONG_FILE 2298 call writefiles 2299 %endif 2300 2301 %if _DEBUG0 2302 mov bx, -1 2303 %endif 2304 00000060 BA[6302] mov dx, init2_msg.initial_error_2 2305 00000063 B93C00 mov cx, init2_msg.initial_error_2.length 2306 00000066 E93001 jmp init2_error_free 2307 2308 @@: 2309 %endif 2310 2311 00000069 F6460340 testopt [bp + ?whichtest], 4000h 2312 0000006D 741D jz @F 2313 0000006F 8CC8 mov ax, cs 2314 00000071 2DAF00 sub ax, (init1_end - init1_start) >> 4 2315 ; ax => INIT1 2316 00000074 8EC0 mov es, ax 2317 00000076 26A1[4200] mov ax, word [es:init1_c_mode_counter] 2318 0000007A E85601 call init2_disp_ax_dec 2319 0000007D B00D mov al, 13 2320 0000007F E84601 call init2_disp_al 2321 00000082 B00A mov al, 10 2322 00000084 E84101 call init2_disp_al 2323 %if _RELOAD_XMS 2324 call freexms 2325 %endif 2326 00000087 B8004C mov ax, 4C00h 2327 0000008A CD21 int 21h 2328 2329 @@: 2330 lvar word, upperbound 2331 0000008C 52 push dx 2332 lvar word, lowerbound 2333 0000008D 56 push si 2334 lvar word, current_init1 2335 0000008E 50 push ax 2336 2337 %if _TEST_PROGRESS 2338 0000008F BA[1C02] mov dx, init2_msg.progress.1 2339 00000092 B90700 mov cx, init2_msg.progress.1.length 2340 .loop: 2341 00000095 0E push cs 2342 00000096 1F pop ds 2343 00000097 BB0200 mov bx, 2 2344 0000009A B440 mov ah, 40h 2345 0000009C CD21 int 21h 2346 %else 2347 .loop: 2348 %endif 2349 2350 0000009E 8B56FE mov dx, [bp + ?upperbound] 2351 2352 000000A1 F6460380 testopt [bp + ?whichtest], 8000h 2353 000000A5 7419 jz @F 2354 2355 000000A7 FF4E04 dec word [bp + ?repetitions] 2356 000000AA 751E jnz .test_b_skip_bound 2357 2358 %if _TEST_PROGRESS 2359 000000AC 0E push cs 2360 000000AD 1F pop ds 2361 000000AE BA[2502] mov dx, init2_msg.progress.linebreak 2362 000000B1 B90200 mov cx, init2_msg.progress.linebreak.length 2363 000000B4 BB0200 mov bx, 2 2364 000000B7 B440 mov ah, 40h 2365 000000B9 CD21 int 21h 2366 %endif 2367 %if _RELOAD_XMS 2368 call freexms 2369 %endif 2370 000000BB B8004C mov ax, 4C00h 2371 000000BE CD21 int 21h 2372 2373 2374 @@: 2375 000000C0 2B56FC sub dx, [bp + ?lowerbound] 2376 000000C3 746C jz .found 2377 000000C5 D1EA shr dx, 1 2378 ; Rounding down, so that we never retry upper bound. 2379 ; The upper bound is known to be working. 2380 000000C7 0356FC add dx, [bp + ?lowerbound] 2381 2382 .test_b_skip_bound: 2383 000000CA 52 push dx 2384 000000CB 81C20F0C add dx, (payload_end - payload) >> 4 2385 000000CF 8B46FA mov ax, [bp + ?current_init1] 2386 000000D2 B9AF00 mov cx, (init1_end - init1_start) >> 4 2387 000000D5 E82502 call init2_movp 2388 000000D8 8956FA mov [bp + ?current_init1], dx 2389 000000DB 5A pop dx 2390 2391 %if _RELOAD_XMS 2392 mov ax, [bp + ?xmshandle] 2393 %if _RELOAD_FILE 2394 cmp ax, -1 2395 je .restore_no_xms 2396 %endif 2397 push si 2398 push cs 2399 pop ds 2400 mov si, init2_xmsm_from_save 2401 mov word [si + XMSM.srchdl], ax 2402 mov word [si + XMSM.dstadr + 2], dx 2403 mov ah, 0Bh 2404 call far [bp + ?xmsentry] 2405 cmp ax, 1 2406 jne init2_error_xms_free 2407 pop si 2408 %if _RELOAD_FILE 2409 jmp .restore_done 2410 %endif 2411 %endif 2412 %if _RELOAD_FILE 2413 .restore_no_xms: 2414 size_compressed equ (payload.end - payload) 2415 push dx 2416 mov ds, dx 2417 mov cx, ((- size_compressed) >> 16) & 0FFFFh 2418 mov dx, (- size_compressed) & 0FFFFh 2419 mov ax, 4202h 2420 mov bx, [bp + ?handle] 2421 int 21h 2422 jc init2_error_file 2423 mov dx, size_compressed >> 16 2424 mov ax, size_compressed & 0FFFFh 2425 @@: 2426 mov cx, 0FF00h 2427 test dx, dx 2428 jnz @F 2429 cmp ax, cx 2430 jae @F 2431 mov cx, ax 2432 @@: 2433 sub ax, cx 2434 sbb dx, 0 2435 push dx 2436 push ax 2437 xor dx, dx 2438 mov ah, 3Fh 2439 int 21h 2440 jc init2_error_file 2441 cmp ax, cx 2442 jne init2_error_file 2443 mov dx, ds 2444 add dx, 0FF0h 2445 mov ds, dx 2446 pop ax 2447 pop dx 2448 mov cx, ax 2449 or cx, dx 2450 jnz @BB 2451 pop dx 2452 .restore_done: 2453 %endif 2454 %ifn _RELOAD_XMS || _RELOAD_FILE 2455 000000DC 8CC8 mov ax, cs 2456 000000DE 053914 add ax, (init2_end - init2_start) >> 4 2457 ; => payload in saving area 2458 000000E1 B90F0C mov cx, (payload_end - payload) >> 4 2459 000000E4 E81602 call init2_movp ; copy payload from payload saving area 2460 %endif 2461 ; dx => source 2462 000000E7 8B46FA mov ax, [bp + ?current_init1] 2463 000000EA BB0100 mov bx, 1 2464 000000ED 52 push dx 2465 000000EE 56 push si 2466 000000EF 0E push cs 2467 000000F0 E86700 call .transfer 2468 000000F3 5E pop si 2469 000000F4 5A pop dx 2470 ; Returns here after decompression. 2471 ; CY if error. 2472 000000F5 7312 jnc @F 2473 2474 000000F7 F6460380 testopt [bp + ?whichtest], 8000h 2475 000000FB 7511 jnz .test_b_fail 2476 2477 ; error: this attempt is one below the new lower bound 2478 000000FD 42 inc dx 2479 000000FE 8956FC mov word [bp + ?lowerbound], dx 2480 2481 %if _TEST_PROGRESS 2482 00000101 BA[2302] mov dx, init2_msg.progress.fail 2483 00000104 B90100 mov cx, init2_msg.progress.fail.length 2484 %endif 2485 00000107 EB8C jmp .loop 2486 2487 @@: 2488 %if _INCLUDE_UNCOMPRESSED 2489 00000109 E85400 call checkdecompressed 2490 0000010C 7417 je @F 2491 2492 %if _WRITE_WRONG_FILE 2493 call writefiles 2494 %endif 2495 2496 .test_b_fail: 2497 %if _TEST_PROGRESS 2498 0000010E 0E push cs 2499 0000010F 1F pop ds 2500 00000110 BA[2502] mov dx, init2_msg.progress.linebreak 2501 00000113 B90200 mov cx, init2_msg.progress.linebreak.length 2502 00000116 BB0200 mov bx, 2 2503 00000119 B440 mov ah, 40h 2504 0000011B CD21 int 21h 2505 %endif 2506 %if _DEBUG0 2507 mov bx, -2 2508 %endif 2509 0000011D BA[9F02] mov dx, init2_msg.subsequent_error_2 2510 00000120 B93700 mov cx, init2_msg.subsequent_error_2.length 2511 00000123 EB74 jmp init2_error_free 2512 2513 @@: 2514 %endif 2515 ; success: this attempt is the new upper bound 2516 00000125 8956FE mov word [bp + ?upperbound], dx 2517 %if _TEST_PROGRESS 2518 00000128 BA[2402] mov dx, init2_msg.progress.success 2519 0000012B B90100 mov cx, init2_msg.progress.success.length 2520 %endif 2521 0000012E E964FF jmp .loop 2522 2523 .found: 2524 %if _TEST_PROGRESS 2525 00000131 0E push cs 2526 00000132 1F pop ds 2527 00000133 BA[2502] mov dx, init2_msg.progress.linebreak 2528 00000136 B90200 mov cx, init2_msg.progress.linebreak.length 2529 00000139 BB0200 mov bx, 2 2530 0000013C B440 mov ah, 40h 2531 0000013E CD21 int 21h 2532 %endif 2533 00000140 8B46FE mov ax, word [bp + ?upperbound] 2534 00000143 29F0 sub ax, si ; = how many paragraphs in buffer before source 2535 00000145 05BE0C add ax, paras( (init1_end - init1_start) + (payload_end - payload) ) 2537 ; = how many paragraphs needed for process 2538 00000148 E88800 call init2_disp_ax_dec 2539 0000014B B00D mov al, 13 2540 0000014D E87800 call init2_disp_al 2541 00000150 B00A mov al, 10 2542 00000152 E87300 call init2_disp_al 2543 %if _RELOAD_XMS 2544 call freexms 2545 %endif 2546 00000155 B8004C mov ax, 4C00h 2547 00000158 CD21 int 21h 2548 2549 2550 .transfer: 2551 0000015A 31FF xor di, di 2552 0000015C 57 push di ; placeholder ax value on stack 2553 0000015D 50 push ax ; INIT1 segment 2554 0000015E 57 push di ; zero = init1_start 2555 0000015F CB retf ; transfer to INIT1:init1_start 2556 2557 2558 2559 %if _INCLUDE_UNCOMPRESSED 2560 2561 2562 %if _WRITE_WRONG_FILE 2563 ; INP: si => decompressed image 2564 ; payload_uncompressed_size = size 2565 ; ! _INCLUDE_UNCOMPRESSED_IN_IMAGE: 2566 ; word [bp + ?handle] = file handle 2567 ; [bp + ?buffer] = ?buffersize buffer 2568 ; OUT: WRONG.BIN contains what we decompressed 2569 ; WRONG2.BIN contains expected payload 2570 ; CHG: ds, si, ax, bx, cx, dx 2571 ; STT: UP 2572 writefiles: 2573 push cs 2574 pop ds 2575 mov dx, init2_msg.wrong_file_name 2576 xor cx, cx 2577 mov ah, 3Ch 2578 int 21h 2579 jc .notfile 2580 2581 mov bx, ax 2582 mov cx, payload_uncompressed_size >> 4 2583 xor dx, dx 2584 .loopfile: 2585 mov ds, si 2586 mov ah, 40h 2587 push cx 2588 mov cx, 16 2589 int 21h 2590 pop cx 2591 inc si 2592 loop .loopfile 2593 2594 mov ds, si 2595 mov cx, payload_uncompressed_size & 15 2596 mov ah, 40h 2597 int 21h 2598 2599 mov ah, 3Eh 2600 int 21h 2601 2602 .notfile: 2603 2604 push cs 2605 pop ds 2606 mov dx, init2_msg.wrong_file_name2 2607 xor cx, cx 2608 mov ah, 3Ch 2609 int 21h 2610 jc .notfile2 2611 2612 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2613 mov bx, ax 2614 mov cx, payload_uncompressed_size >> 4 2615 mov si, cs 2616 add si, (payload_uncompressed - init2_start) >> 4 2617 xor dx, dx 2618 .loopfile2: 2619 mov ds, si 2620 mov ah, 40h 2621 push cx 2622 mov cx, 16 2623 int 21h 2624 pop cx 2625 inc si 2626 loop .loopfile2 2627 2628 mov ds, si 2629 mov cx, payload_uncompressed_size & 15 2630 mov ah, 40h 2631 int 21h 2632 2633 mov ah, 3Eh 2634 int 21h 2635 %else 2636 xchg si, ax 2637 2638 %if _RELOAD_FILE 2639 mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh 2640 mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh 2641 %else 2642 mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh 2643 mov dx, (- payload_uncompressed_size) & 0FFFFh 2644 %endif 2645 mov ax, 4202h 2646 mov bx, [bp + ?handle] 2647 int 21h 2648 jc .closefile2 2649 2650 push ss 2651 pop ds 2652 lea dx, [bp + ?buffer] 2653 2654 %if payload_uncompressed_size == 0 2655 %error Empty payload not allowed 2656 %endif 2657 %if (payload_uncompressed_size / ?buffersize) != 0 2658 mov cx, payload_uncompressed_size / ?buffersize 2659 %if ?buffersize == 0 || (?buffersize & 15) != 0 2660 %error Unexpected layout 2661 %endif 2662 .loop: 2663 push cx 2664 mov cx, ?buffersize 2665 call transferchunk 2666 pop cx 2667 jc .closefile2 2668 loop .loop 2669 %endif 2670 %if (payload_uncompressed_size % ?buffersize) != 0 2671 mov cx, payload_uncompressed_size % ?buffersize 2672 call transferchunk 2673 %endif 2674 2675 .closefile2: 2676 mov bx, si 2677 mov ah, 3Eh 2678 int 21h 2679 %endif 2680 2681 .notfile2: 2682 retn 2683 2684 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2685 ; INP: ds:dx -> buffer 2686 ; cx = size to transfer, must fit in buffer 2687 ; ?handle = source file handle 2688 ; si = destination file handle 2689 ; OUT: NC if success 2690 ; CY if error 2691 ; CHG: ax, bx 2692 ; STT: UP 2693 transferchunk: 2694 mov bx, word [bp + ?handle] 2695 mov ah, 3Fh 2696 int 21h 2697 jc .ret 2698 cmp ax, cx 2699 stc 2700 jne .ret ; if partial read --> (CY) 2701 mov bx, si 2702 mov ah, 40h 2703 int 21h 2704 jc .ret 2705 cmp ax, cx 2706 je .ret ; if not partial write --> (NC) 2707 stc 2708 .ret: 2709 retn 2710 %endif 2711 2712 %endif 2713 2714 2715 ; INP: si => decompressed image 2716 ; payload_uncompressed_size = size 2717 ; ! _INCLUDE_UNCOMPRESSED_IN_IMAGE: 2718 ; word [bp + ?handle] = file handle 2719 ; [bp + ?buffer] = ?buffersize buffer 2720 ; OUT: ZR if matching 2721 ; NZ if mismatching 2722 ; CHG: es, ds, di, bx, cx 2723 ; STT: UP 2724 checkdecompressed: 2725 00000160 50 push ax 2726 00000161 52 push dx 2727 00000162 56 push si 2728 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2729 %if _PAYLOAD_KERNEL_MAX_PARAS 2730 mov cx, _PAYLOAD_KERNEL_MAX_PARAS 2731 mov bx, 0 2732 %else 2733 00000163 B9FF13 mov cx, payload_uncompressed_size >> 4 2734 00000166 BB0A00 mov bx, payload_uncompressed_size & 15 2735 %endif 2736 00000169 8CCF mov di, cs 2737 0000016B 83C739 add di, (payload_uncompressed - init2_start) >> 4 2738 0000016E E319 jcxz .end 2739 .loop: 2740 00000170 51 push cx 2741 00000171 B90800 mov cx, 8 2742 00000174 8EDE mov ds, si 2743 00000176 8EC7 mov es, di 2744 00000178 46 inc si 2745 00000179 47 inc di 2746 0000017A 56 push si 2747 0000017B 57 push di 2748 0000017C 31F6 xor si, si 2749 0000017E 31FF xor di, di 2750 00000180 F3A7 repe cmpsw 2751 00000182 5F pop di 2752 00000183 5E pop si 2753 00000184 59 pop cx 2754 00000185 750E jne .ret 2755 00000187 E2E7 loop .loop 2756 .end: 2757 00000189 8EDE mov ds, si 2758 0000018B 8EC7 mov es, di 2759 0000018D 31F6 xor si, si 2760 0000018F 31FF xor di, di ; (ZR) 2761 00000191 89D9 mov cx, bx 2762 00000193 F3A6 repe cmpsb 2763 %else 2764 %if _RELOAD_FILE 2765 size_compressed_plus_uncompressed equ payload_uncompressed_size + (payload.end - payload) 2767 mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh 2768 mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh 2769 %else 2770 mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh 2771 mov dx, (- payload_uncompressed_size) & 0FFFFh 2772 %endif 2773 mov ax, 4202h 2774 mov bx, [bp + ?handle] 2775 int 21h 2776 jc .error 2777 %if payload_uncompressed_size == 0 2778 %error Empty payload not allowed 2779 %endif 2780 %if (payload_uncompressed_size / ?buffersize) != 0 2781 mov cx, payload_uncompressed_size / ?buffersize 2782 %if ?buffersize == 0 || (?buffersize & 15) != 0 2783 %error Unexpected layout 2784 %endif 2785 .loop: 2786 push cx 2787 mov cx, ?buffersize 2788 call comparechunk 2789 pop cx 2790 jne .ret 2791 loop .loop 2792 %endif 2793 %if (payload_uncompressed_size % ?buffersize) != 0 2794 mov cx, payload_uncompressed_size % ?buffersize 2795 call comparechunk 2796 %endif 2797 %endif 2798 .ret: 2799 00000195 5E pop si 2800 00000196 5A pop dx 2801 00000197 58 pop ax 2802 00000198 C3 retn 2803 2804 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2805 .error: 2806 or al, 1 ; NZ 2807 jmp .ret 2808 %endif 2809 %endif 2810 2811 2812 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2813 ; INP: ?buffer -> ?buffersize buffer 2814 ; cx = amount of bytes, 0 < cx <= ?buffersize 2815 ; si => chunk 2816 ; ?handle = handle 2817 ; seek -> chunk 2818 ; OUT: NZ if mismatch or error 2819 ; ZR else, 2820 ; si => next chunk (assumes full chunk) 2821 ; CHG: ds, es, di, ax, bx, cx, dx 2822 ; STT: UP 2823 comparechunk: 2824 push ss 2825 pop ds 2826 lea dx, [bp + ?buffer] 2827 mov bx, [bp + ?handle] 2828 mov ah, 3Fh 2829 int 21h 2830 jc .error 2831 cmp ax, cx 2832 jne .error 2833 mov es, si 2834 add si, ?buffersize / 16 2835 push si 2836 xor di, di 2837 mov si, dx 2838 repe cmpsb 2839 pop si 2840 .ret: 2841 retn 2842 2843 .error: 2844 or al, 1 ; NZ 2845 retn 2846 %endif 2847 2848 %if _RELOAD_XMS 2849 freexms: 2850 push ax 2851 push bx 2852 push dx 2853 mov dx, -1 2854 xchg dx, [bp + ?xmshandle] 2855 %if _RELOAD_FILE 2856 cmp dx, -1 2857 je @F 2858 %endif 2859 mov ah, 0Ah 2860 call far [bp + ?xmsentry] 2861 @@: 2862 pop dx 2863 pop bx 2864 pop ax 2865 retn 2866 2867 init2_error_xms_free: 2868 call freexms 2869 init2_error_xms: 2870 mov dx, init2_msg.xms_error 2871 mov cx, init2_msg.xms_error.length 2872 jmp init2_error 2873 %endif 2874 2875 %if _RELOAD_FILE 2876 init2_error_file: 2877 mov dx, init2_msg.file_error 2878 mov cx, init2_msg.file_error.length 2879 %endif 2880 2881 init2_error_free: 2882 %if _RELOAD_XMS 2883 call freexms 2884 %endif 2885 init2_error: 2886 %if _DEBUG0 2887 push bx 2888 %endif 2889 00000199 0E push cs 2890 0000019A 1F pop ds 2891 0000019B BB0200 mov bx, 2 2892 0000019E B440 mov ah, 40h 2893 000001A0 CD21 int 21h 2894 2895 %if _DEBUG0 2896 mov dx, init2_msg.rc 2897 mov cx, init2_msg.rc.length 2898 mov bx, 2 2899 mov ah, 40h 2900 int 21h 2901 pop ax 2902 call init2_error_disp_ax_hex 2903 mov dx, init2_msg.linebreak 2904 mov cx, init2_msg.linebreak.length 2905 mov bx, 2 2906 mov ah, 40h 2907 int 21h 2908 %endif 2909 2910 000001A2 F6460340 testopt [bp + ?whichtest], 4000h 2911 000001A6 7408 jz @F 2912 000001A8 BA[FA02] mov dx, init2_msg.error_c_stdout 2913 000001AB B90300 mov cx, init2_msg.error_c_stdout.length 2914 000001AE EB0C jmp @FF 2915 @@: 2916 000001B0 F6460380 testopt [bp + ?whichtest], 8000h 2917 000001B4 750D jnz @FF 2918 000001B6 BA[FA02] mov dx, init2_msg.error_stdout 2919 000001B9 B90300 mov cx, init2_msg.error_stdout.length 2920 @@: 2921 000001BC BB0100 mov bx, 1 2922 000001BF B440 mov ah, 40h 2923 000001C1 CD21 int 21h 2924 @@: 2925 000001C3 B8FF4C mov ax, 4CFFh 2926 000001C6 CD21 int 21h 2927 2928 lleave ctx 2929 2930 2931 %if _DEBUG0 2932 init2_error_disp_ax_hex: ; ax 2933 xchg al,ah 2934 call init2_error_disp_al_hex ; display former ah 2935 xchg al,ah ; and fall trough for al 2936 init2_error_disp_al_hex: ; al 2937 push cx 2938 mov cl,4 2939 ror al,cl 2940 call init2_error_disp_al_lownibble_hex 2941 ; display former high-nibble 2942 rol al,cl 2943 pop cx 2944 ; and fall trough for low-nibble 2945 init2_error_disp_al_lownibble_hex: 2946 push ax ; save ax for call return 2947 and al,00001111b ; high nibble must be zero 2948 add al,'0' ; if number is 0-9, now it's the correct character 2949 cmp al,'9' 2950 jna .decimalnum ; if we get decimal number with this, ok --> 2951 add al,7 ; otherwise, add 7 and we are inside our alphabet 2952 .decimalnum: 2953 call init2_error_disp_al 2954 pop ax 2955 retn 2956 2957 2958 init2_error_disp_al: 2959 push dx 2960 push cx 2961 push bx 2962 push ax 2963 mov dx, sp 2964 push ds 2965 push ss 2966 pop ds 2967 mov cx, 1 2968 mov bx, 2 2969 mov ah, 40h 2970 int 21h 2971 pop ds 2972 pop ax 2973 pop bx 2974 pop cx 2975 pop dx 2976 retn 2977 %endif 2978 2979 2980 init2_disp_al: 2981 000001C8 52 push dx 2982 000001C9 50 push ax 2983 000001CA 88C2 mov dl, al 2984 000001CC B402 mov ah, 2 2985 000001CE CD21 int 21h 2986 000001D0 58 pop ax 2987 000001D1 5A pop dx 2988 000001D2 C3 retn 2989 2990 2991 ; Display number in ax decimal 2992 ; 2993 ; INP: ax = number 2994 ; OUT: displayed using Int21.02 2995 ; CHG: none 2996 init2_disp_ax_dec: ; ax (no leading zeros) 2997 000001D3 53 push bx 2998 000001D4 31DB xor bx, bx 2999 .pushax: 3000 000001D6 52 push dx 3001 000001D7 50 push ax 3002 000001D8 08DB or bl, bl 3003 000001DA 7405 jz .nobl 3004 000001DC 80EB05 sub bl, 5 3005 000001DF F6DB neg bl 3006 .nobl: 3007 000001E1 51 push cx 3008 000001E2 B91027 mov cx, 10000 3009 000001E5 E81B00 call .divide_out 3010 000001E8 B9E803 mov cx, 1000 3011 000001EB E81500 call .divide_out 3012 000001EE B96400 mov cx, 100 3013 000001F1 E80F00 call .divide_out 3014 000001F4 B10A mov cl, 10 3015 000001F6 E80A00 call .divide_out 3016 ; (Divisor 1 is useless) 3017 000001F9 0430 add al, '0' 3018 000001FB E8CAFF call init2_disp_al 3019 000001FE 59 pop cx 3020 000001FF 58 pop ax 3021 00000200 5A pop dx 3022 00000201 5B pop bx ; Caller's register 3023 00000202 C3 retn 3024 3025 3026 ; INP: ax = number 3027 ; cx = divisor 3028 ; OUT: ax = remainder of operation 3029 ; result displayed 3030 .divide_out: 3031 00000203 52 push dx 3032 00000204 31D2 xor dx, dx 3033 00000206 F7F1 div cx ; 0:ax / cx 3034 00000208 52 push dx ; remainder 3035 00000209 FECB dec bl 3036 0000020B 7503 jnz .nobl2 3037 0000020D 80CF01 or bh, 1 3038 .nobl2: 3039 00000210 08C7 or bh, al 3040 00000212 7405 jz .leadingzero 3041 00000214 0430 add al, '0' 3042 00000216 E8AFFF call init2_disp_al ; display result 3043 .leadingzero: 3044 00000219 58 pop ax ; remainder 3045 0000021A 5A pop dx 3046 0000021B C3 retn 3047 3048 3049 init2_msg: 3050 %if _TEST_PROGRESS 3051 0000021C 496E666F3A2031 .progress.1: db "Info: 1" 3052 .progress.1.length: equ $ - .progress.1 3053 00000223 46 .progress.fail: db "F" 3054 .progress.fail.length: equ $ - .progress.fail 3055 00000224 53 .progress.success: db "S" 3056 .progress.success.length: equ $ - .progress.success 3057 00000225 0D0A .progress.linebreak: db 13,10 3058 .progress.linebreak.length: equ $ - .progress.linebreak 3059 %endif 3060 %if _WRITE_WRONG_FILE 3061 .wrong_file_name: asciz "WRONG.BIN" 3062 .wrong_file_name2: asciz "WRONG2.BIN" 3063 %endif 3064 00000227 4572726F723A205465- .initial_error: db "Error: Test program failed to decompress with full buffer." 3064 00000230 73742070726F677261- 3064 00000239 6D206661696C656420- 3064 00000242 746F206465636F6D70- 3064 0000024B 726573732077697468- 3064 00000254 2066756C6C20627566- 3064 0000025D 6665722E 3065 00000261 0D0A .linebreak: db 13,10 3066 .initial_error.length: equ $ - .initial_error 3067 .linebreak.length: equ $ - .linebreak 3068 %if _DEBUG0 3069 .rc: db "Error: Failure code=" 3070 .rc.length: equ $ - .rc 3071 %endif 3072 %if _INCLUDE_UNCOMPRESSED 3073 00000263 4572726F723A205465- .initial_error_2: db "Error: Test program decompressed wrongly with full buffer.",13,10 3073 0000026C 73742070726F677261- 3073 00000275 6D206465636F6D7072- 3073 0000027E 65737365642077726F- 3073 00000287 6E676C792077697468- 3073 00000290 2066756C6C20627566- 3073 00000299 6665722E0D0A 3074 .initial_error_2.length: equ $ - .initial_error_2 3075 0000029F 4572726F723A205465- .subsequent_error_2: db "Error: Test program decompressed wrongly during test.",13,10 3075 000002A8 73742070726F677261- 3075 000002B1 6D206465636F6D7072- 3075 000002BA 65737365642077726F- 3075 000002C3 6E676C792064757269- 3075 000002CC 6E6720746573742E0D- 3075 000002D5 0A 3076 .subsequent_error_2.length: equ $ - .subsequent_error_2 3077 %endif 3078 000002D6 4572726F723A20496E- .cmdline_error: db "Error: Invalid command line input.",13,10 3078 000002DF 76616C696420636F6D- 3078 000002E8 6D616E64206C696E65- 3078 000002F1 20696E7075742E0D0A 3079 .cmdline_error.length: equ $ - .cmdline_error 3080 %if _RELOAD_XMS 3081 .xms_error: db "Error: XMS failure.",13,10 3082 .xms_error.length: equ $ - .xms_error 3083 %endif 3084 %if _RELOAD_FILE 3085 .file_error: db "Error: File read failure.",13,10 3086 .file_error.length: equ $ - .file_error 3087 %endif 3088 3089 .error_c_stdout: 3090 000002FA 30 .error_stdout: db "0" 3091 %if 0 3092 _autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE + (payload_end - payload) + (init1_end - init1_start) + ADDITIONAL_MEMORY ) 3097 %endif 3098 000002FB 0D0A db 13,10 3099 .error_c_stdout.length: equ $ - .error_c_stdout 3100 .error_stdout.length: equ $ - .error_stdout 3101 3102 3103 ; Move paragraphs 3104 ; 3105 ; INP: ax => source 3106 ; dx => destination 3107 ; cx = number of paragraphs 3108 ; CHG: - 3109 ; OUT: ax and dx unchanged 3110 ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 3111 ; Do not provide a wrapped/HMA source or destination! 3112 init2_movp: 3113 000002FD 51 push cx 3114 000002FE 1E push ds 3115 000002FF 56 push si 3116 00000300 06 push es 3117 00000301 57 push di 3118 3119 00000302 39D0 cmp ax, dx ; source above destination ? 3120 00000304 770A ja .up ; yes, move up (forwards) --> 3121 00000306 747B je .return ; same, no need to move --> 3122 00000308 50 push ax 3123 00000309 01C8 add ax, cx ; (expected not to carry) 3124 0000030B 39D0 cmp ax, dx ; end of source is above destination ? 3125 0000030D 58 pop ax 3126 0000030E 7730 ja .down ; yes, move from top down --> 3127 ; Here, the end of source is below-or-equal the destination, 3128 ; so they do not overlap. In this case we prefer moving up. 3129 3130 .up: 3131 00000310 50 push ax 3132 00000311 52 push dx 3133 .uploop: 3134 00000312 8ED8 mov ds, ax 3135 00000314 8EC2 mov es, dx 3136 00000316 31FF xor di, di 3137 00000318 31F6 xor si, si ; -> start of segment 3138 0000031A 81E90010 sub cx, 1000h ; 64 KiB left ? 3139 0000031E 7610 jbe .uplast ; no --> 3140 00000320 51 push cx 3141 00000321 B90080 mov cx, 10000h /2 3142 00000324 F3A5 rep movsw ; move 64 KiB 3143 00000326 59 pop cx 3144 00000327 050010 add ax, 1000h 3145 0000032A 81C20010 add dx, 1000h ; -> next segment 3146 0000032E EBE2 jmp short .uploop ; proceed for more --> 3147 .uplast: 3148 00000330 81C10010 add cx, 1000h ; restore counter 3149 00000334 D1E1 shl cx, 1 3150 00000336 D1E1 shl cx, 1 3151 00000338 D1E1 shl cx, 1 ; *8, paragraphs to words 3152 0000033A F3A5 rep movsw ; move last part 3153 0000033C 5A pop dx 3154 0000033D 58 pop ax 3155 0000033E EB43 jmp short .return 3156 3157 .down: 3158 00000340 FD std ; _AMD_ERRATUM_109_WORKAROUND as below 3159 .dnloop: 3160 00000341 81E90010 sub cx, 1000h ; 64 KiB left ? 3161 00000345 761A jbe .dnlast ; no --> 3162 00000347 50 push ax 3163 00000348 52 push dx 3164 00000349 01C8 add ax, cx 3165 0000034B 01CA add dx, cx 3166 0000034D 8ED8 mov ds, ax ; -> 64 KiB not yet moved 3167 0000034F 8EC2 mov es, dx 3168 00000351 5A pop dx 3169 00000352 58 pop ax 3170 00000353 BFFEFF mov di, -2 3171 00000356 89FE mov si, di ; moved from last word down 3172 00000358 51 push cx 3173 00000359 B90080 mov cx, 10000h /2 3174 0000035C F3A5 rep movsw ; move 64 KiB 3175 0000035E 59 pop cx 3176 0000035F EBE0 jmp short .dnloop ; proceed for more --> 3177 .dnlast: 3178 00000361 81C10010 add cx, 1000h ; restore counter 3179 00000365 D1E1 shl cx, 1 3180 00000367 D1E1 shl cx, 1 3181 00000369 D1E1 shl cx, 1 ; *8, paragraphs to words 3182 0000036B 89CF mov di, cx 3183 0000036D 4F dec di 3184 0000036E D1E7 shl di, 1 ; words to offset, -> last word 3185 00000370 89FE mov si, di 3186 00000372 8ED8 mov ds, ax 3187 00000374 8EC2 mov es, dx ; first segment correct 3188 3189 ; Refer to comment in init0_movp. 3190 %if _AMD_ERRATUM_109_WORKAROUND 3191 00000376 E308 jcxz @FF 3192 00000378 83F914 cmp cx, 20 3193 0000037B 7703 ja @FF 3194 @@: 3195 0000037D A5 movsw 3196 0000037E E2FD loop @B 3197 @@: 3198 %endif 3199 00000380 F3A5 rep movsw ; move first part 3200 00000382 FC cld 3201 .return: 3202 00000383 5F pop di 3203 00000384 07 pop es 3204 00000385 5E pop si 3205 00000386 1F pop ds 3206 00000387 59 pop cx 3207 00000388 C3 retn 3208 3209 3210 00000389 90 align 4 3211 %if _RELOAD_XMS 3212 init2_xmsm_from_save: 3213 istruc XMSM 3214 at XMSM.size_, dd payload_end - payload 3215 iend 3216 init2_xmsm_to_save: 3217 istruc XMSM 3218 at XMSM.size_, dd payload_end - payload 3219 iend 3220 %endif 3221 3222 0000038C 90 align 16 3223 3224 %if _INCLUDE_UNCOMPRESSED && _INCLUDE_UNCOMPRESSED_IN_IMAGE 3225 strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN" 3226 payload_uncompressed: 3227 00000390 incbin _UNCOMPRESSED_FILE 3228 .end: 3229 0001438A 26 db 38 3230 0001438B 26 align 16, db 38 3231 %endif 3232 init2_end: 3233 %endif 3234