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 [list -] 51 ------------------ note: Disable usesection detection 89 90 numdef SCAN, 0 91 92 numdef USESCAN, 0 93 strdef SCANBINARY, "" 94 95 numdef DEBUG0 ; use errordata to generate an error code 96 numdef DEBUG1 ; dump_stack_frame after an error occurred 97 numdef DEBUG2 ; dump_stack_frame before blz_depack_safe call 98 numdef DEBUG3 ; dump_stack_frame at start of blz_depack_safe 99 100 numdef OPTIMISE_INPUT_SMALL, 0 101 numdef OPTIMISE_OUYPUT_SMALL, 0 102 numdef ALLOW_OVERLAPPING, 1 ; allow overlapping src and dst 103 numdef TEST_PROGRAM, 0 104 numdef TEST_PROGRAM_DECOMPRESSED_SIZE, 0,0 105 %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE 106 %error Test program has to learn of decompressed size. 107 %endif 108 numdef TEST_PROGRESS, 0 109 110 numdef INCLUDE_UNCOMPRESSED 111 numdef INCLUDE_UNCOMPRESSED_IN_IMAGE, 1 112 numdef WRITE_WRONG_FILE 113 numdef RELOAD_XMS, 0 114 numdef RELOAD_FILE, 0 115 116 numdef EXEC_OFFSET, 0 117 numdef EXEC_SEGMENT, 0 118 numdef IMAGE_EXE, 0 119 %if ! _IMAGE_EXE && _TEST_PROGRAM 120 %error Test program can only be used as EXE. 121 %endif 122 numdef IMAGE_EXE_CS, -16 ; relative-segment for CS 123 numdef IMAGE_EXE_IP, 256 +64 ; value for IP 124 ; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0. 125 numdef IMAGE_EXE_SS, -16 ; relative-segment for SS 126 numdef IMAGE_EXE_SP, 0FFFEh ; value for SP (0 underflows) 127 numdef IMAGE_EXE_AUTO_STACK, 0, 2048 ; use stack behind image 128 ; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of 129 ; the same name. This one is only used as a flag; if non-zero, 130 ; keep the stack given to us by iniload; if zero, set up the 131 ; stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP. 132 numdef IMAGE_EXE_GET_COM_STACK, 0 133 ; set up stack for flat .COM style entry 134 numdef DEVICE, 0 135 gendef DEVICE_NAME, "" 136 numdef DEVICE_ATTRIBUTE, 8000h 137 numdef DEVICE_ZERO_ENTRYPOINT, 0 138 numdef BOOTLDR, 1 ; support boot loaded entrypoint 139 140 numdef BRIEFLZ, 0 141 numdef LZ4, 0 142 numdef SNAPPY, 0 143 numdef EXODECR, 0 144 numdef X, 0 145 numdef HEATSHRINK, 0 146 numdef LZD, 0 147 numdef LZO, 0 148 numdef LZSA2, 0 149 numdef APL, 0 150 numdef BZP, 0 151 numdef ZEROCOMP, 0 152 numdef MVCOMP, 0 153 numdef LZEXEDAT, 0 154 numdef ZX0, 0 155 %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK + !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP + !!_ZEROCOMP + !!_MVCOMP + !!_LZEXEDAT + !!_ZX0) != 1 158 %fatal Exactly one compression method must be selected. 159 %endif 160 %assign ADDITIONAL_MEMORY 0 161 %if _BRIEFLZ 162 strdef PAYLOAD_FILE, "lDOSLOAD.BLZ" 163 %elif _LZ4 164 strdef PAYLOAD_FILE, "lDOSLOAD.LZ4" 165 %elif _SNAPPY 166 strdef PAYLOAD_FILE, "lDOSLOAD.SZ" 167 %elif _EXODECR 168 strdef PAYLOAD_FILE, "lDOSLOAD.EXO" 169 %elif _X 170 strdef PAYLOAD_FILE, "lDOSLOAD.X" 171 %elif _HEATSHRINK 172 strdef PAYLOAD_FILE, "lDOSLOAD.HS" 173 %elif _LZD 174 strdef PAYLOAD_FILE, "lDOSLOAD.LZ" 175 %elif _LZO 176 strdef PAYLOAD_FILE, "lDOSLOAD.LZO" 177 %elif _LZSA2 178 strdef PAYLOAD_FILE, "lDOSLOAD.SA2" 179 %elif _APL 180 strdef PAYLOAD_FILE, "lDOSLOAD.APL" 181 %elif _BZP 182 strdef PAYLOAD_FILE, "lDOSLOAD.BZP" 183 %elif _ZEROCOMP 184 strdef PAYLOAD_FILE, "lDOSLOAD.ZER" 185 %elif _MVCOMP 186 strdef PAYLOAD_FILE, "lDOSLOAD.MV" 187 %elif _LZEXEDAT 188 strdef PAYLOAD_FILE, "lDOSLOAD.LZE" 189 %elif _ZX0 190 strdef PAYLOAD_FILE, "lDOSLOAD.ZX0" 191 %endif 192 numdef PAYLOAD_KERNEL_MAX_PARAS, 0, 0 193 %if _PAYLOAD_KERNEL_MAX_PARAS && ! (_IMAGE_EXE || _DEVICE) 194 %error Kernel mode max paras requires building dual-mode or triple-mode executable 195 %endif 196 numdef COUNTER, 0, 32 197 %if (_COUNTER - 1) & _COUNTER 198 %error COUNTER must be a power of two 199 %endif 200 numdef PROGRESS, 0, 1 201 numdef PROGRESSAMOUNT, 0, 0 202 numdef PROGRESSMULTI, 1 203 numdef PROGRESSVAR, 1 204 numdef PROGRESSVARNAME, "" 205 numdef PROGRESSDEFAULT, 0 206 numdef PROGRESSDEFAULTAPP, _PROGRESSDEFAULT 207 numdef PROGRESSDEFAULTDEVICE, _PROGRESSDEFAULT 208 numdef PROGRESSDEFAULTBOOT,1 209 numdef PASSLCFG, 0 210 numdef LCFG, (_PROGRESS && _PROGRESSMULTI) || _PASSLCFG 211 212 213 %define MODULE inicomp 214 strdef INILOAD_CFG, "" 215 %ifnidn _INILOAD_CFG, "" 216 %include _INILOAD_CFG 1 <1> ; File auto-generated, do not edit. 2 <1> strdef INILOAD_SIGNATURE, "TR" 3 <1> %assign _DEVICE 0 4 <1> %ifidni MODULE, directpl 5 <1> %define _PAYLOAD_FILE "testrand.bin" 6 <1> %endif 7 <1> %ifn _TEST_PROGRAM 8 <1> numdef IMAGE_EXE, 0 9 <1> numdef SECOND_PAYLOAD_EXE, 0 10 <1> %endif 217 %endif 218 strdef LCFG_CFG, "" 219 220 %if _DEVICE 221 %ifidn _DEVICE_NAME, "" 222 %error Device name must be set 223 %endif 224 %endif 225 226 struc XMSM 227 00000000 ???????? .size_: resd 1 228 00000004 ???? .srchdl: resw 1 229 00000006 ???????? .srcadr: resd 1 230 0000000A ???? .dsthdl: resw 1 231 0000000C ???????? .dstadr: resd 1 232 endstruc 233 234 235 cpu 8086 236 [list -] 239 240 addsection INIT0, start=0 vstart=0 240 ------------------ note: usesection INIT0 241 init0_start: 242 %if _DEVICE 243 ; The device header is of a fixed format. 244 ; For our purposes, the 4-byte code for 245 ; each the strategy entry and the 246 ; interrupt entry is part of this format. 247 ; (DOS may read the attributes or entrypoint 248 ; offsets before calling either, so in the inicomp 249 ; stage we need to recreate in the entrypoints part 250 ; exactly what the application has here.) 251 ; _PASSLCFG: The lCFG block is passed in the dword 252 ; behind the interrupt entry. 253 device_header: 254 .next: 255 %if _DEVICE_ZERO_ENTRYPOINT 256 fill 2, -1, jmp strict short j_zero_entrypoint 257 dw -1 258 %else 259 dd -1 ; link to next device 260 %endif 261 .attributes: 262 dw _DEVICE_ATTRIBUTE ; attributes 263 .strategy: 264 dw .strategy_entry ; -> strategy entry 265 .interrupt: 266 dw .interrupt_entry ; -> interrupt entry 267 .name: 268 fill 8, 32, db _DEVICE_NAME ; character device name, 269 ; or block device number of units 270 ; + optional name 271 .strategy_entry: 272 fill 4, 90h, jmp device_entrypoint 273 .interrupt_entry: 274 fill 4, 90h, retf 275 .pass_lcfg: 276 %endif 277 278 279 %if _IMAGE_EXE || _DEVICE 280 00000000 90 nop 281 00000001 90 align 32, nop 282 init0_kernel_entry: 283 ; cs:ip = load seg : 32 here 284 %if ($ - $$) != 32 285 %error Wrong kernel mode entrypoint 286 %endif 287 %if _TEST_PROGRAM 288 @@: 289 00000020 CC int3 290 00000021 FB sti 291 00000022 F4 hlt 292 00000023 EBFB jmp @B 293 %endif 294 %if _BOOTLDR 295 %if ! _IMAGE_EXE 296 j_zero_entrypoint: 297 %endif 298 00000025 31DB xor bx, bx ; 0 = kernel mode 299 00000027 50 push ax 300 00000028 8CC8 mov ax, cs 301 0000002A 83C040 add ax, (init0_end - init0_start) >> 4 302 0000002D 8B56E2 mov dx, word [ bp + ldLoadTop ] ; => after end of available space 303 00000030 BE6000 mov si, 60h ; => destination 304 00000033 E9AF00 jmp init0_common 305 %endif 306 307 %if _IMAGE_EXE 308 00000036 90 align 64, nop 309 j_zero_entrypoint: 310 init0_exe_entry: 311 ; NOTE: This part is called with ip = 256 + 64, cs = PSP. 312 %if ($ - $$) != 64 313 %error Wrong EXE mode entrypoint 314 %endif 315 %if _IMAGE_EXE_GET_COM_STACK 316 mov bx, ds ; => PSP 317 dec bx ; => MCB 318 mov ds, bx 319 add bx, word [3] ; add size of memory block 320 sub bx, -1 + paras(512) ; add one, then subtract enough paragraphs 321 cli 322 mov ss, bx 323 mov sp, 512 ; -> new stack 324 sti 325 %endif 326 00000040 BB0100 mov bx, 1 ; EXE mode 327 00000043 50 push ax 328 %if _TEST_PROGRAM 329 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 330 00000044 1E push ds 331 00000045 A12C00 mov ax, word [2Ch] ; => environment 332 00000048 85C0 test ax, ax 333 0000004A 7503 jnz @F 334 .errorfile: 335 0000004C E9E700 jmp init0_error_file 336 @@: 337 0000004F 8ED8 mov ds, ax 338 00000051 B90080 mov cx, 8000h 339 00000054 31F6 xor si, si ; -> environment 340 @@: 341 00000056 AC lodsb 342 00000057 84C0 test al, al 343 00000059 E0FB loopnz @B ; si -> past one NUL 344 0000005B E3EF jcxz .errorfile 345 0000005D 803C00 cmp byte [si], 0 ; -> another NUL ? 346 00000060 E0F4 loopne @B ; no, skip next variable --> 347 00000062 E3E8 jcxz .errorfile 348 00000064 46 inc si ; skip double NUL 349 00000065 AD lodsw ; load amount strings after environment 350 00000066 83F801 cmp ax, 1 ; 1 ? 351 00000069 75E1 jne .errorfile ; no --> 352 0000006B 89F2 mov dx, si ; ds:dx -> executable pathname 353 0000006D B8203D mov ax, 3D00h + 0_010_0_000b ; deny write, read only 354 00000070 CD21 int 21h ; open 355 00000072 72D8 jc .errorfile 356 00000074 1F pop ds ; restore => PSP 357 00000075 50 push ax ; push into ?handle 358 %endif 359 360 00000076 BE8100 mov si, 81h 361 00000079 31D2 xor dx, dx 362 0000007B 31C0 xor ax, ax 363 cmdline: 364 .: 365 0000007D AC lodsb 366 0000007E 3C09 cmp al, 9 367 00000080 74FB je . 368 00000082 3C20 cmp al, 32 369 00000084 74F7 je . 370 00000086 3C0D cmp al, 13 371 00000088 744E je .end 372 0000008A 3C30 cmp al, '0' 373 0000008C 721E jb .notdigit 374 0000008E 3C39 cmp al, '9' 375 00000090 771A ja .notdigit 376 .digit: 377 00000092 2C30 sub al, '0' 378 00000094 89D1 mov cx, dx ; times 1 379 00000096 01D2 add dx, dx 380 00000098 722A jc .invalid 381 0000009A 01D2 add dx, dx ; times 4 382 0000009C 7226 jc .invalid 383 0000009E 01CA add dx, cx ; times 5 384 000000A0 7222 jc .invalid 385 000000A2 01D2 add dx, dx ; times 10 386 000000A4 721E jc .invalid 387 000000A6 01C2 add dx, ax ; add in low digit 388 000000A8 721A jc .invalid 389 000000AA EBD1 jmp . 390 391 .notdigit: 392 000000AC 3C41 cmp al, 'A' 393 000000AE 7419 je .a 394 000000B0 3C61 cmp al, 'a' 395 000000B2 7415 je .a 396 000000B4 3C42 cmp al, 'B' 397 000000B6 7416 je .b 398 000000B8 3C62 cmp al, 'b' 399 000000BA 7412 je .b 400 000000BC 3C43 cmp al, 'C' 401 000000BE 7413 je .c 402 000000C0 3C63 cmp al, 'c' 403 000000C2 740F je .c 404 .invalid: 405 000000C4 BAFFFF mov dx, -1 ; invalid 406 000000C7 EB0F jmp .end 407 408 .a: 409 000000C9 80E77F and bh, ~ 80h ; A mode. determine min alloc size 410 000000CC EBAF jmp . 411 412 .b: 413 000000CE 80CF80 or bh, 80h ; B mode. repeat depack, counter in command line 414 000000D1 EBAA jmp . 415 416 .c: 417 000000D3 80CF40 or bh, 40h ; C mode. how often would the counter be called 418 000000D6 EBA5 jmp . 419 420 .end: 421 ; bx for ?whichtest 422 000000D8 52 push dx ; for ?repetitions 423 %endif 424 000000D9 8CD2 mov dx, ss ; => after end of available space 425 000000DB 8CC8 mov ax, cs 426 000000DD 83C050 add ax, (256 + (init0_end - init0_start)) >> 4 ; => source 427 000000E0 8CCE mov si, cs 428 000000E2 83C610 add si, 256 >> 4 ; => destination 429 %endif 430 431 init0_common: 432 ; REM: This part must be position-independent, as it is 433 ; called either with ip = init0_common (kernel mode 434 ; or device mode) 435 ; or ip = init0_common + 256 (application mode). 436 ; INP: si => depack destination 437 ; ax => source of payload + INIT1 438 ; dx => behind available memory 439 ; OUT: cs:ip -> init1_start: 440 ; ax => INIT1 441 ; dx => payload source 442 ; si => depack destination 443 ; bx = mode 444 000000E5 FC cld 445 %if _TEST_PROGRAM 446 %ifn _RELOAD_XMS || _RELOAD_FILE 447 sub dx, ( (payload_end - payload) ) >> 4 448 jc .error 449 %endif 450 000000E6 B9BA01 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) + (init2_end - init2_start) ) >> 4 456 000000E9 29CA sub dx, cx 457 000000EB 7214 jc .error 458 000000ED 39C2 cmp dx, ax 459 000000EF 7210 jb .error 460 %else 461 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 466 ; cx = amount paragraphs in INIT0B + payload + INIT1 467 sub dx, cx ; => destination for INIT0B + payload + INIT1 468 ; (highest possible spot in available memory) 469 %endif 470 000000F1 56 push si ; preserve destination 471 000000F2 E88B00 call init0_movp ; move up payload + INIT1 472 000000F5 5E pop si 473 %else 474 cld 475 mov ax, cs 476 add ax, (init0_end - init0_start) >> 4 477 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 482 mov dx, word [ bp + ldLoadTop ] 483 sub dx, cx 484 call init0_movp 485 %endif 486 487 %if _LCFG && ! _TEST_PROGRAM 488 push cs 489 call @F ; position-independent far pointer 490 @@: 491 pop ax 492 add ax, lcfg - @B ; -> lCFG block 493 push ax 494 %endif 495 496 000000F6 89D0 mov ax, dx ; => INIT0B 497 ; (same as => payload if INIT0B is empty) 498 %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM 499 add dx, ( + (init0b_end - init0b_start) ) >> 4 ; => payload 502 %else 503 %if _TEST_PROGRAM 504 000000F8 05C500 add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 ; => INIT2 509 %else 510 add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) ) >> 4 ; => INIT1 514 %endif 515 %endif 516 517 %if _USESCAN && _TEST_PROGRAM 518 000000FB B9[B608] mov cx, init2_entry 519 %else 520 xor cx, cx 521 %endif 522 000000FE 50 push ax 523 000000FF 51 push cx 524 00000100 CB retf ; jump to relocated 525 ; INIT0B:init0b_start 526 ; or INIT1:init1_start 527 ; or INIT2:init2_start 528 529 530 %if _TEST_PROGRAM 531 .error: 532 00000101 89DF mov di, bx ; whichtest 533 534 00000103 0E push cs 535 00000104 1F pop ds 536 00000105 BA[2E03] mov dx, init0_msg.error_stderr + 256 537 00000108 B92500 mov cx, init0_msg.error_stderr.length 538 0000010B BB0200 mov bx, 2 539 0000010E B440 mov ah, 40h 540 00000110 CD21 int 21h 541 542 00000112 F7C70040 test di, 4000h ; whichtest 543 00000116 7408 jz @F 544 00000118 BA[5303] mov dx, init0_msg.error_c_stdout + 256 545 0000011B B90300 mov cx, init0_msg.error_c_stdout.length 546 0000011E EB0A jmp @FF 547 @@: 548 00000120 85FF test di, di ; whichtest 549 00000122 780D js @FF 550 00000124 BA[5303] mov dx, init0_msg.error_stdout + 256 551 00000127 B90300 mov cx, init0_msg.error_stdout.length 552 @@: 553 0000012A BB0100 mov bx, 1 554 0000012D B440 mov ah, 40h 555 0000012F CD21 int 21h 556 @@: 557 00000131 B8FF4C mov ax, 4CFFh 558 00000134 CD21 int 21h 559 560 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 561 init0_error_file: 562 00000136 BA[0203] mov dx, init0_msg.error_stderr_file + 256 563 00000139 B92C00 mov cx, init0_msg.error_stderr_file.length 564 0000013C 0E push cs 565 0000013D 1F pop ds 566 0000013E BB0200 mov bx, 2 567 00000141 B440 mov ah, 40h 568 00000143 CD21 int 21h 569 570 00000145 BA[5303] mov dx, init0_msg.error_stdout + 256 571 00000148 B90300 mov cx, init0_msg.error_stdout.length 572 0000014B BB0100 mov bx, 1 573 0000014E B440 mov ah, 40h 574 00000150 CD21 int 21h 575 00000152 B8FF4C mov ax, 4CFFh 576 00000155 CD21 int 21h 577 %endif 578 579 %endif 580 581 582 %if _LCFG 583 %imacro lcfgoption 3+.nolist 584 _fill %1, 0, lcfg 585 %%start: 586 %2 587 %3 588 %%end: 589 %assign %%index %%start - lcfg 590 %rep %%end - %%start 591 %assign LCFGINUSE LCFGINUSE | (1 << %%index) 592 %assign %%index %%index + 1 593 %endrep 594 %endmacro 595 %assign LCFGINUSE 0 596 597 00000157 90 align 16 598 lcfg: 599 00000160 EB1E .: jmp strict short .end 600 00000162 6C434647 lcfgoption 2,, db "lCFG" 601 00000166 3030 lcfgoption 6,, db "00" 602 00000168 FCFF050000000000 lcfgoption 8,, dq .inuse 603 %if _PROGRESS && _PROGRESSMULTI 604 %if _IMAGE_EXE 605 00000170 00 lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP 606 %endif 607 %if _DEVICE 608 lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE 609 %endif 610 %if _BOOTLDR 611 00000171 0001 lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT 612 %endif 613 %endif 614 615 %ifnidn _LCFG_CFG, "" 616 %include _LCFG_CFG 1 <1> ; File auto-generated, do not edit. 617 %endif 618 619 00000173 00 lcfgoption 32,, 620 .end: 621 .size: equ .end - . 622 .inuse equ LCFGINUSE 623 %endif 624 625 626 %if _DEVICE 627 device_entrypoint: 628 %if _TEST_PROGRAM 629 @@: 630 int3 631 sti 632 hlt 633 jmp @B 634 %endif 635 cmp byte [es:bx + 2], 0 ; command code 0 (init) ? 636 je @F 637 638 mov word [es:bx + 3], 8103h ; error, done, code: unknown command 639 retf 640 641 @@: 642 or word [cs:device_header.next], -1 643 push cs 644 push word [cs:device_header.strategy] 645 ; -> far return to payload's strategy 646 push bp 647 push ds 648 push si 649 push di 650 push dx 651 push cx 652 push ax 653 push bx 654 push es 655 656 mov dx, word [es:bx + 14] 657 mov cl, 4 658 shr dx, cl ; = how many full paragraphs (rounded down) 659 add dx, word [es:bx + 14 + 2] 660 ; ax => behind end 661 662 mov di, cs 663 image_size: equ ( + (init0_end - init0_start) + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) 669 add di, image_size >> 4 ; di => end of image 670 671 cmp dx, di ; enough memory to hold all of us ? 672 jb @F ; no --> 673 ; yes 674 .have_some_memory: 675 ; dx => after end of memory 676 mov bx, 2 ; device mode 677 push ax 678 mov ax, cs 679 add ax, (init0_end - init0_start) >> 4 680 mov si, cs ; => destination 681 jmp init0_common 682 683 684 @@: 685 push cs 686 pop ds 687 mov dx, .msg_no_memory 688 mov ah, 09h 689 int 21h 690 691 mov ax, 3000h 692 int 21h 693 cmp al, 5 694 jae @F 695 mov dx, .msg_dos_below_5 696 mov ah, 09h 697 int 21h 698 @@: 699 700 mov dx, .msg_linebreak 701 mov ah, 09h 702 int 21h 703 704 ; tear down the stack frame and modify the request header 705 pop es 706 pop bx 707 mov word [es:bx + 3], 8103h ; set error, done, invalid command 708 mov byte [es:bx + 13], 0 ; set number of units = 0 709 mov word [es:bx + 14 + 2], cs 710 and word [es:bx + 14], 0 ; -> after end of memory to allocate 711 pop ax 712 pop cx 713 pop dx 714 pop di 715 pop si 716 pop ds 717 pop bp 718 add sp, 4 ; discard far return to payload's strategy 719 retf ; return to DOS 720 721 722 .msg_no_memory: ascic "Load error: Not enough memory." 723 .msg_dos_below_5: ascic " Note: DOS must be at least version 5." 724 .msg_linebreak: ascic 13,10 725 %endif 726 727 728 ; Move paragraphs 729 ; 730 ; INP: ax => source 731 ; dx => destination 732 ; cx = number of paragraphs 733 ; CHG: cx, ds, si, es, di 734 ; OUT: ax and dx unchanged 735 ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 736 ; Do not provide a wrapped/HMA source or destination! 737 init0_movp: 738 00000180 39D0 cmp ax, dx ; source above destination ? 739 00000182 770A ja .up ; yes, move up (forwards) --> 740 00000184 747B je .return ; same, no need to move --> 741 00000186 50 push ax 742 00000187 01C8 add ax, cx ; (expected not to carry) 743 00000189 39D0 cmp ax, dx ; end of source is above destination ? 744 0000018B 58 pop ax 745 0000018C 7730 ja .down ; yes, move from top down --> 746 ; Here, the end of source is below-or-equal the destination, 747 ; so they do not overlap. In this case we prefer moving up. 748 749 .up: 750 0000018E 50 push ax 751 0000018F 52 push dx 752 .uploop: 753 00000190 8ED8 mov ds, ax 754 00000192 8EC2 mov es, dx 755 00000194 31FF xor di, di 756 00000196 31F6 xor si, si ; -> start of segment 757 00000198 81E90010 sub cx, 1000h ; 64 KiB left ? 758 0000019C 7610 jbe .uplast ; no --> 759 0000019E 51 push cx 760 0000019F B90080 mov cx, 10000h /2 761 000001A2 F3A5 rep movsw ; move 64 KiB 762 000001A4 59 pop cx 763 000001A5 050010 add ax, 1000h 764 000001A8 81C20010 add dx, 1000h ; -> next segment 765 000001AC EBE2 jmp short .uploop ; proceed for more --> 766 .uplast: 767 000001AE 81C10010 add cx, 1000h ; restore counter 768 000001B2 D1E1 shl cx, 1 769 000001B4 D1E1 shl cx, 1 770 000001B6 D1E1 shl cx, 1 ; *8, paragraphs to words 771 000001B8 F3A5 rep movsw ; move last part 772 000001BA 5A pop dx 773 000001BB 58 pop ax 774 000001BC EB43 jmp short .return 775 776 .down: 777 000001BE FD std ; _AMD_ERRATUM_109_WORKAROUND as below 778 .dnloop: 779 000001BF 81E90010 sub cx, 1000h ; 64 KiB left ? 780 000001C3 761A jbe .dnlast ; no --> 781 000001C5 50 push ax 782 000001C6 52 push dx 783 000001C7 01C8 add ax, cx 784 000001C9 01CA add dx, cx 785 000001CB 8ED8 mov ds, ax ; -> 64 KiB not yet moved 786 000001CD 8EC2 mov es, dx 787 000001CF 5A pop dx 788 000001D0 58 pop ax 789 000001D1 BFFEFF mov di, -2 790 000001D4 89FE mov si, di ; moved from last word down 791 000001D6 51 push cx 792 000001D7 B90080 mov cx, 10000h /2 793 000001DA F3A5 rep movsw ; move 64 KiB 794 000001DC 59 pop cx 795 000001DD EBE0 jmp short .dnloop ; proceed for more --> 796 .dnlast: 797 000001DF 81C10010 add cx, 1000h ; restore counter 798 000001E3 D1E1 shl cx, 1 799 000001E5 D1E1 shl cx, 1 800 000001E7 D1E1 shl cx, 1 ; *8, paragraphs to words 801 000001E9 89CF mov di, cx 802 000001EB 4F dec di 803 000001EC D1E7 shl di, 1 ; words to offset, -> last word 804 000001EE 89FE mov si, di 805 000001F0 8ED8 mov ds, ax 806 000001F2 8EC2 mov es, dx ; first segment correct 807 808 809 numdef AMD_ERRATUM_109_WORKAROUND, 1 810 %if 0 811 812 Jack R. Ellis pointed out this erratum: 813 814 Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69: 815 816 109 Certain Reverse REP MOVS May Produce Unpredictable Behavior 817 818 Description 819 820 In certain situations a REP MOVS instruction may lead to 821 incorrect results. An incorrect address size, data size 822 or source operand segment may be used or a succeeding 823 instruction may be skipped. This may occur under the 824 following conditions: 825 826 * EFLAGS.DF=1 (the string is being moved in the reverse direction). 827 828 * The number of items being moved (RCX) is between 1 and 20. 829 830 * The REP MOVS instruction is preceded by some microcoded instruction 831 that has not completely retired by the time the REP MOVS begins 832 execution. The set of such instructions includes BOUND, CLI, LDS, 833 LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions. 834 835 Potential Effect on System 836 837 Incorrect results may be produced or the system may hang. 838 839 Suggested Workaround 840 841 Contact your AMD representative for information on a BIOS update. 842 843 %endif 844 845 %if _AMD_ERRATUM_109_WORKAROUND 846 000001F4 E308 jcxz @FF 847 000001F6 83F914 cmp cx, 20 848 000001F9 7703 ja @FF 849 @@: 850 000001FB A5 movsw 851 000001FC E2FD loop @B 852 @@: 853 %endif 854 000001FE F3A5 rep movsw ; move first part 855 00000200 FC cld 856 .return: 857 00000201 C3 retn 858 859 860 addsection INIT0B, align=16 vstart=0 follows=INIT0 860 ------------------ note: usesection INIT0B 861 ; INP: ax:cx = cs:ip = cs:0 862 ; ax => INIT0B 863 ; dx => payload source 864 ; ss:sp -> (dword pointer to lCFG block) 865 ; if app/device mode supported: 866 ; si => depack destination 867 ; bx = mode 868 init0b_start: 869 %if _LCFG || _PROGRESS 870 871 00000000 83C015 add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) ) >> 4 ; => INIT1 875 876 %if _LCFG && _PASSLCFG 877 %if (_IMAGE_EXE || _DEVICE) 878 mov cx, si ; preserve si 879 %endif 880 pop si 881 pop ds ; -> lCFG block 882 mov es, ax 883 mov di, transfer_lcfg_block 884 ; -> destination 885 %if (_IMAGE_EXE || _DEVICE) 886 push cx 887 %endif 888 push di 889 mov cx, words(lcfg.size) 890 rep movsw ; cx = 0 891 pop di ; es:di -> relocated lCFG block, same difference 892 %if (_IMAGE_EXE || _DEVICE) 893 pop si ; preserve si 894 %endif 895 %elif _LCFG 896 00000003 5F pop di 897 00000004 07 pop es ; es:di -> (original) lCFG block 898 %endif 899 900 00000005 50 push ax 901 00000006 51 push cx ; -> far return address to init1_start 902 903 %if _PROGRESS && _PROGRESSMULTI 904 %if (_IMAGE_EXE || _DEVICE) 905 00000007 56 push si 906 00000008 53 push bx 907 %endif 908 %if _BOOTLDR 909 %if _LCFG 910 00000009 31C0 xor ax, ax 911 0000000B 268A4512 mov al, byte [es:di + lcfg.progress_boot - lcfg] 912 0000000F 97 xchg di, ax ; di = boot default progress 913 ; es:ax -> lCFG block 914 %else ; _LCFG 915 mov di, _PROGRESSDEFAULTBOOT 916 %endif ; _LCFG 917 %endif ; _BOOTLDR 918 %if (_IMAGE_EXE || _DEVICE) 919 %if _BOOTLDR 920 00000010 85DB test bx, bx 921 00000012 7503E9A700 jz .default 922 %endif ; _BOOTLDR 923 %if _LCFG 924 00000017 06 push es 925 %if _BOOTLDR 926 00000018 50 push ax ; -> lCFG block 927 %else ; _BOOTLDR 928 push di 929 %endif ; _BOOTLDR 930 %endif ; _LCFG 931 %if _PROGRESSVAR 932 00000019 B451 mov ah, 51h 933 0000001B CD21 int 21h 934 @@: 935 0000001D 8EDB mov ds, bx 936 0000001F A12C00 mov ax, word [2Ch] 937 00000022 85C0 test ax, ax 938 00000024 7510 jnz .gotenv 939 00000026 A11600 mov ax, word [16h] 940 00000029 40 inc ax 941 0000002A 7469 jz .default_nonboot 942 0000002C 48 dec ax 943 0000002D 7466 jz .default_nonboot 944 0000002F 39C3 cmp bx, ax 945 00000031 7462 je .default_nonboot 946 00000033 93 xchg bx, ax 947 00000034 EBE7 jmp @B 948 949 .gotenv: 950 00000036 0E push cs 951 00000037 1F pop ds ; => cs 952 00000038 8EC0 mov es, ax ; => environment 953 %ifnidni _PROGRESSVARNAME, "" 954 0000003A BB[EA00] mov bx, progressvarname1 955 0000003D E80C00 call .findenv 956 00000040 732E jnc .foundenv ; match --> 957 00000042 BB[ED00] mov bx, progressvarname2 958 %endif 959 00000045 E80400 call .findenv 960 00000048 7326 jnc .foundenv ; match --> 961 0000004A EB49 jmp .default_nonboot 962 963 .findenv: 964 0000004C 31FF xor di, di 965 @@: 966 %ifnidni _PROGRESSVARNAME, "" 967 0000004E 89DE mov si, bx ; -> variable name 968 %else 969 mov si, progressvarname2 ; -> variable name 970 %endif 971 00000050 31C0 xor ax, ax 972 00000052 AC lodsb ; get length 973 00000053 91 xchg cx, ax ; cx = length 974 00000054 57 push di 975 00000055 F3A6 repe cmpsb ; match ? 976 00000057 7415 je .findret_pop ; (NC) yes --> 977 00000059 5F pop di 978 0000005A B90080 mov cx, 8000h ; maximum env size 979 0000005D 29F9 sub cx, di ; any left ? 980 0000005F 760B jbe .findret_CY ; no --> 981 00000061 B000 mov al, 0 982 00000063 F2AE repne scasb ; find next NUL 983 00000065 7505 jne .findret_CY 984 00000067 263805 cmp byte [es:di], al ; double NUL ? 985 0000006A 75E2 jne @B ; no, loop --> 986 .findret_CY: 987 0000006C F9 stc ; not found 988 0000006D C3 retn 989 990 .findret_pop: 991 0000006E 59 pop cx 992 0000006F C3 retn 993 994 .foundenv: 995 %if _LCFG 996 00000070 5E pop si 997 00000071 5E pop si ; discard far pointer to lCFG 998 %endif 999 00000072 89FE mov si, di ; es:si -> var content 1000 00000074 31FF xor di, di ; = 0 1001 00000076 31C0 xor ax, ax ; ah = 0 1002 @@: 1003 00000078 26AC es lodsb ; next candidate digit 1004 0000007A 2C30 sub al, '0' ; digit ? 1005 0000007C 7212 jb @F ; no --> 1006 0000007E 3C09 cmp al, 9 1007 00000080 770E ja @F ; no --> 1008 00000082 01FF add di, di ; times 2 1009 00000084 89FB mov bx, di 1010 00000086 01FF add di, di ; times 4 1011 00000088 01FF add di, di ; times 8 1012 0000008A 01DF add di, bx ; times 8 + times 2 = times 10 1013 0000008C 01C7 add di, ax ; add in next digit 1014 0000008E EBE8 jmp @B ; and loop 1015 1016 @@: 1017 00000090 83E71F and di, 31 ; mask to low 5 bits 1018 00000093 EB0B jmp @F 1019 %endif ; _PROGRESSVAR 1020 1021 .default_nonboot: 1022 %if _LCFG 1023 00000095 5F pop di 1024 00000096 07 pop es ; -> lCFG block 1025 00000097 5B pop bx ; = 1 if app, = 2 if device 1026 00000098 53 push bx 1027 00000099 268B4510 mov ax, word [es:di + lcfg.progress_app - lcfg] 1028 %if _DEVICE 1029 %if lcfg.progress_app + 1 != lcfg.progress_dev 1030 %error Unexpected layout 1031 %endif 1032 ; al = app, ah = device 1033 dec bx 1034 jz .default_app 1035 xchg al, ah ; al = device 1036 .default_app: 1037 %endif ; _DEVICE 1038 0000009D B400 mov ah, 0 ; ax = default 1039 0000009F 97 xchg di, ax ; di = default 1040 %else ; _LCFG 1041 mov di, _PROGRESSDEFAULT 1042 %endif ; _LCFG 1043 @@: 1044 000000A0 F7C71000 test di, 16 1045 000000A4 7405 jz @F 1046 000000A6 83E7EF and di, ~16 1047 000000A9 EB13 jmp .outputdevice ; if 16 set skip device check 1048 @@: 1049 000000AB 52 push dx 1050 000000AC B80044 mov ax, 4400h ; IOCTL get device information 1051 000000AF BB0100 mov bx, 1 ; StdOut 1052 000000B2 B283 mov dl, 83h ; default if 21.4400 fails 1053 000000B4 CD21 int 21h 1054 000000B6 F6C280 test dl, 80h 1055 000000B9 5A pop dx 1056 000000BA 7502 jnz .outputdevice 1057 000000BC 31FF xor di, di ; stdout is a file: force no progress marker 1058 .outputdevice: 1059 %endif ; (_IMAGE_EXE || _DEVICE) 1060 1061 .default: 1062 %if (_IMAGE_EXE || _DEVICE) 1063 000000BE 5B pop bx 1064 000000BF 5E pop si 1065 %endif 1066 000000C0 83FF05 cmp di, step_progress_table.amount 1067 ; valid ? 1068 000000C3 7202 jb @F ; yes --> 1069 000000C5 31FF xor di, di ; disable 1070 @@: 1071 000000C7 D1E7 shl di, 1 ; = word index 1072 000000C9 59 pop cx ; = 0 1073 000000CA 1F pop ds ; ds => INIT1 1074 1075 000000CB 2E8B85[E000] mov ax, word [cs:step_progress_table + di] 1076 ; ax = rel16 for step progress handler 1077 000000D0 1E push ds 1078 000000D1 51 push cx ; -> init1_start 1079 000000D2 A3[6800] mov word [step_progress.handler], ax 1080 ; patch it 1081 1082 000000D5 83FF04 cmp di, 2 * 2 ; none or dots ? 1083 000000D8 7305 jae @F ; no, skip --> 1084 000000DA C606[0600]A9 mov byte [..@empty_step_progress], __TEST_IMM16 1085 ; for none and dots do not call here 1086 @@: 1087 %endif ; _PROGRESS && _PROGRESSMULTI 1088 000000DF CB retf 1089 %endif 1090 1091 %if _PROGRESS && _PROGRESSMULTI 1092 align 2, db 0 1093 step_progress_table: 1094 .: 1095 000000E0 1600 dw step_progress.0_step - step_progress.base 1096 000000E2 3B00 dw step_progress.1_step - step_progress.base 1097 000000E4 0000 dw step_progress.2_step - step_progress.base 1098 000000E6 4100 dw step_progress.3_step - step_progress.base 1099 000000E8 8600 dw step_progress.4_step - step_progress.base 1100 .amount equ ($ - .) / 2 1101 1102 %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE) 1103 %ifnidni _PROGRESSVARNAME, "" 1104 000000EA 02003D progressvarname1: counted _PROGRESSVARNAME, '=' 1105 %endif 1106 000000ED 0D4C444F5350524F47- progressvarname2: counted "LDOSPROGRESS=" 1106 000000F6 524553533D 1107 %endif 1108 %endif 1109 1110 000000FB 90 align 16 1111 init0b_end: 1112 1113 1114 addsection PAYLOAD, align=16 follows=INIT0B 1114 ------------------ note: usesection PAYLOAD 1115 payload: 1116 00000000 incbin _PAYLOAD_FILE 1117 .end: 1118 0000004A 26 align 16, db 38 1119 payload_end: 1120 1121 %if _OPTIMISE_INPUT_SMALL 1122 %ifn (payload_end - payload) <= 65_520 1123 %error Input declared small is not small 1124 %endif 1125 %else 1126 %if (payload_end - payload) <= 65_520 1127 %warning Input could be declared small 1127 ****************** warning: Input could be declared small [-w+user] 1128 %endif 1129 %endif 1130 1131 1132 addsection INIT1, align=16 follows=PAYLOAD vstart=0 1132 ------------------ note: usesection INIT1 1133 init1_start: 1134 ; INP: ax = cs = INIT1 1135 ; dx = cs - (payload_end - payload) >> 4 => source data 1136 ; if kernel mode: 1137 ; ss:bp -> LOADDATA and LOADSTACKVARS 1138 ; ss:sp -> valid stack above [bp + ldLoadTop] 1139 ; 60h => destination 1140 ; any mode: 1141 ; ss:sp -> word value for ax 1142 ; bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode 1143 ; si => destination (60h for kernel mode, 1144 ; after PSP for EXE mode, 1145 ; at device header for device mode) 1146 ; (not set if only kernel mode supported) 1147 ; if EXE mode: 1148 ; ss:sp -> valid stack above INIT1 1149 ; bp = unset 1150 ; if device mode: 1151 ; ss:sp -> device entrypoint stack 1152 ; holds: es, bx, ax, cx, dx, di, si, ds, bp, 1153 ; far address of payload strategy entrypoint, 1154 ; far return address to DOS 1155 ; bp = unset 1156 ; STT: UP 1157 ; CHG: ax, bx, cx, dx, es, ds, si, di 1158 %if _IMAGE_EXE || _DEVICE 1159 lframe 1160 00000000 5589E5 lenter 1161 lvar word, exemode ; must be bp - 2! 1162 00000003 53 push bx 1163 %if ?exemode != -2 1164 %error exemode variable must be directly below bp 1165 %endif 1166 00000004 56 push si 1167 %if _PROGRESS 1168 00000005 F8 clc ; NC 1169 %endif 1170 %else 1171 xor bx, bx ; always tell them it is kernel mode (NC) 1172 %endif 1173 1174 %if _PROGRESS 1175 ; clc 1176 ..@empty_step_progress: ; SMC, byte patched to __TEST_IMM16 if none or dots 1177 %if _TEST_PROGRAM 1178 00000006 90 times 3 nop 1179 %else 1180 call step_progress.CF ; display empty / 0.0% 1181 %endif 1182 @@: 1183 %endif 1184 1185 %if _IMAGE_EXE || _DEVICE 1186 00000009 8EC6 mov es, si ; es => destination 1187 %else 1188 mov ax, 60h 1189 mov es, ax ; es => destination 1190 %endif 1191 0000000B 31FF xor di, di ; -> destination 1192 1193 0000000D 8EDA mov ds, dx 1194 0000000F 31F6 xor si, si ; -> source 1195 1196 00000011 B94A00 mov cx, (payload.end - payload) & 0FFFFh 1197 %if (payload.end - payload) >> 16 1198 mov dx, (payload.end - payload) >> 16 ; = length of source 1199 %else 1200 00000014 31D2 xor dx, dx 1201 %endif 1202 %if _PAYLOAD_KERNEL_MAX_PARAS 1203 mov ax, _PAYLOAD_KERNEL_MAX_PARAS 1204 test bx, bx 1205 jz @F 1206 %endif 1207 00000016 B8FFFF mov ax, -1 1208 @@: 1209 1210 ; INP: ds:si -> source 1211 ; dx:cx = length of source 1212 ; es:di -> destination (below source) 1213 ; bx = EXE mode flag 1214 ; (1 if EXE mode, 0 if kernel mode) 1215 ; (always 0 if this is a build without EXE mode) 1216 ; if _PAYLOAD_KERNEL_MAX_PARAS: 1217 ; ax = maximum amount in paragraphs of destination needed 1218 ; (-1 if full source should be decompressed) 1219 ; else: 1220 ; ax = -1 1221 ; Note: The destination reaches up to below the source. 1222 00000019 E80504 call depack 1223 %ifn _TEST_PROGRAM 1224 jc strict short error ; -2 (replaced by retf \ nop) 1225 %endif 1226 %if _IMAGE_EXE || _DEVICE 1227 0000001C 5E pop si ; si 1228 %if _TEST_PROGRAM 1229 0000001D 58 pop ax ; (discard ?exemode, leave bx as returned) 1230 %else 1231 pop bx ; ?exemode 1232 %endif 1233 0000001E 5D pop bp ; bp 1234 0000001F 58 pop ax ; ax 1235 lleave ctx 1236 %endif 1237 %if _TEST_PROGRAM 1238 00000020 CB retf ; +1 (replace jc error) 1239 00000021 90 nop ; +1 1240 %endif 1241 1242 %if _DEVICE 1243 test bl, 2 1244 jz .jmp_exe_or_kernel_mode 1245 1246 .jmp_device_mode: 1247 mov ds, si 1248 or word [device_header.next], -1 1249 %if _LCFG && _PASSLCFG 1250 mov word [device_header.pass_lcfg], transfer_lcfg_block 1251 mov word [device_header.pass_lcfg + 2], cs 1252 %endif 1253 pop es 1254 pop bx 1255 pop ax 1256 pop cx 1257 pop dx 1258 pop di 1259 pop si 1260 pop ds 1261 pop bp 1262 retf ; transfer to payload strategy entrypoint 1263 ; still on stack: far return address to DOS 1264 1265 .jmp_exe_or_kernel_mode: 1266 %endif 1267 1268 %if _IMAGE_EXE 1269 00000022 F6C301 test bl, 1 1270 00000025 7410 jz .jmp_kernel_mode 1271 1272 .jmp_exe_mode: 1273 %if ! _IMAGE_EXE_AUTO_STACK 1274 mov cx, cs 1275 lea dx, [si + _IMAGE_EXE_SS] 1276 push dx ; stack = relocated ss value 1277 add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4 1278 cmp cx, dx ; INIT1 code is above intended stack ? 1279 jae @F ; yes --> 1280 1281 lframe 1282 lenter 1283 lvar word, exemode 1284 push bx 1285 %if ?exemode != -2 1286 %error exemode variable must be directly below bp 1287 %endif 1288 mov bx, -1 ; unimplemented, return error 1289 jmp error 1290 lleave ctx 1291 @@: 1292 cli 1293 pop ss ; = relocated ss value 1294 mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh ; change stack 1295 sti 1296 %endif 1297 1298 00000027 31C9 xor cx, cx 1299 00000029 51 push cx ; put zero on top of stack 1300 1301 %if _IMAGE_EXE_IP < 256 1302 mov cl, _IMAGE_EXE_IP 1303 %elif (_IMAGE_EXE_IP & 255) == 0 1304 mov ch, _IMAGE_EXE_IP >> 8 1305 %else 1306 0000002A B94001 mov cx, _IMAGE_EXE_IP 1307 %endif 1308 1309 %if _IMAGE_EXE_CS == -16 1310 0000002D 83C6F0 add si, -16 1311 00000030 8EDE mov ds, si 1312 00000032 8EC6 mov es, si 1313 %else 1314 lea dx, [si - 10h] ; => PSP 1315 mov ds, dx 1316 mov es, dx ; ds = es => PSP 1317 %if _IMAGE_EXE_CS 1318 add si, _IMAGE_EXE_CS ; = relocated cs value 1319 %endif 1320 %endif 1321 00000034 56 push si 1322 00000035 51 push cx 1323 %if _LCFG && _PASSLCFG 1324 mov di, transfer_lcfg_block 1325 mov cx, cs 1326 %endif 1327 00000036 CB retf ; jump to EXE mode of image 1328 1329 %endif 1330 .jmp_kernel_mode: 1331 %if _LCFG && _PASSLCFG 1332 mov di, transfer_lcfg_block 1333 mov cx, cs 1334 %endif 1335 00000037 EA00006000 jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET 1336 1337 1338 %if _TEST_PROGRAM 1339 disp_al_counter: 1340 0000003C 2EFF06[4200] inc word [cs:init1_c_mode_counter] ; 5 bytes 1341 00000041 C3 retn ; 1 byte 1342 1343 00000042 0000 init1_c_mode_counter: dw 0 ; 2 bytes, total 8 1344 %else 1345 %if _PROGRESS 1346 disp_al_counter equ step_progress 1347 %else 1348 disp_al_counter equ disp_al 1349 %endif 1350 %endif 1351 1352 1353 error: 1354 %ifn _TEST_PROGRAM ; 2 bytes 1355 push cs 1356 pop ds 1357 %endif 1358 %if _DEBUG0 1359 mov si, msg.error_begin 1360 call disp_error 1361 xchg ax, bx ; ax = error code 1362 call disp_ax_hex 1363 %ifn _TEST_PROGRAM ; 3 bytes 1364 mov si, msg.error_end 1365 %endif 1366 %else 1367 %ifn _TEST_PROGRAM ; 3 bytes 1368 mov si, msg.error 1369 %endif 1370 %endif 1371 %ifn _TEST_PROGRAM ; 3 bytes, total 2 + 3 + 3 = 8 1372 call disp_error 1373 %endif 1374 %if _DEVICE 1375 test byte [bp - 2], 2 1376 jz .exit_app_or_kernel 1377 1378 pop si ; => device segment 1379 pop bx ; mode word 1380 pop bp 1381 pop ax 1382 mov es, si 1383 xor di, di ; -> device header 1384 push cs 1385 pop ds 1386 mov si, device_header_copy ; -> to reset header 1387 mov cx, words(device_header_copy.length) 1388 rep movsw ; overwrite device header with default 1389 ; (reset to a valid state after unsuccessful 1390 ; decompression, which may have partially 1391 ; written the header already) 1392 push es 1393 pop ds ; -> device segment 1394 pop es 1395 pop bx 1396 mov word [es:bx + 3], 8103h ; set error, done, invalid command 1397 mov byte [es:bx + 13], 0 ; set number of units = 0 1398 mov word [es:bx + 14 + 2], ds 1399 and word [es:bx + 14], 0 ; -> after end of memory to allocate 1400 pop ax 1401 pop cx 1402 pop dx 1403 pop di 1404 pop si 1405 pop ds 1406 pop bp 1407 add sp, 4 ; discard far return to payload's strategy 1408 retf ; return to DOS 1409 1410 1411 .exit_app_or_kernel: 1412 %endif 1413 1414 %if _IMAGE_EXE 1415 %if _BOOTLDR 1416 00000044 F646FE01 test byte [bp - 2], 1 1417 00000048 7405 jz .exit_kernel_mode 1418 %endif 1419 1420 0000004A B87F4C mov ax, 4C7Fh 1421 0000004D CD21 int 21h 1422 1423 .exit_kernel_mode: 1424 %endif 1425 %if _BOOTLDR 1426 0000004F 31C0 xor ax, ax 1427 00000051 CD16 int 16h 1428 00000053 CD19 int 19h 1429 %endif 1430 1431 1432 %if _PROGRESS 1433 step_progress: 1434 00000055 F9 stc 1435 .CF: 1436 00000056 53 push bx 1437 00000057 51 push cx 1438 00000058 52 push dx 1439 00000059 1E push ds 1440 0000005A 56 push si 1441 0000005B 57 push di 1442 0000005C 50 push ax 1443 1444 0000005D 0E push cs 1445 0000005E 1F pop ds 1446 1447 0000005F 8316[9001]00 adc word [.counter], 0 1448 00000064 A1[9001] mov ax, word [.counter] 1449 1450 %if _PROGRESSMULTI 1451 %if _IMAGE_EXE || _DEVICE 1452 %assign defaultprogresshandler _PROGRESSDEFAULT 1453 %else 1454 %assign defaultprogresshandler _PROGRESSDEFAULTBOOT 1455 %endif 1456 00000067 E91600 jmp strict near . %+ defaultprogresshandler %+ _step 1457 .handler: equ $ - 2 ; SMC, patched to dispatch to handler 1458 .base: 1459 %endif 1460 1461 .2_step: 1462 0000006A BAE803 mov dx, 1000 1463 0000006D F7E2 mul dx ; dx:ax = counter times 1000 1464 %if _PROGRESSAMOUNT 1465 0000006F B90100 mov cx, _PROGRESSAMOUNT 1466 00000072 F7F1 div cx ; ax = 0..1000 1467 %else 1468 %warning Progress amount is zero 1469 mov ax, 1 1470 %endif 1471 1472 %if 0 1473 cmp word [.display], ax 1474 je .ret 1475 mov word [.display], ax 1476 %endif 1477 00000074 BE[9901] mov si, .message_number_end - 1 1478 00000077 E80E00 call .format_percentage 1479 1480 0000007A BE[9201] mov si, .message 1481 0000007D E82A01 call disp_error 1482 1483 .ret: 1484 00000080 58 pop ax 1485 .ret_ax: 1486 00000081 5F pop di 1487 00000082 5E pop si 1488 00000083 1F pop ds 1489 00000084 5A pop dx 1490 00000085 59 pop cx 1491 00000086 5B pop bx 1492 .retn: 1493 00000087 C3 retn 1494 1495 1496 .format_percentage: 1497 00000088 BB0200 mov bx, 2 ; skip dot 1498 1499 0000008B B90A00 mov cx, 10 ; base 1500 @@: 1501 0000008E 31D2 xor dx, dx ; dx:ax = current number 1502 00000090 F7F1 div cx ; dl = remainder, ax = next number 1503 00000092 80C230 add dl, '0' ; make decit 1504 00000095 8814 mov byte [si], dl ; store 1505 00000097 29DE sub si, bx ; -> next digit slot 1506 00000099 80FB02 cmp bl, 2 ; did we just store fractional ? 1507 0000009C B301 mov bl, 1 ; ! next iteration do not skip dot 1508 0000009E 74EE je @B ; yes, loop always --> 1509 000000A0 85C0 test ax, ax ; nonzero left ? 1510 000000A2 75EA jnz @B ; yes, loop if so --> 1511 000000A4 C3 retn 1512 1513 1514 %if _PROGRESSMULTI 1515 .0_step: equ .ret 1516 1517 .1_step: 1518 000000A5 58 pop ax 1519 000000A6 E80F01 call disp_al 1520 000000A9 EBD6 jmp .ret_ax 1521 1522 .3_step: 1523 000000AB BB4B00 mov bx, 80 - 1 - 4 1524 000000AE F7E3 mul bx ; dx:ax = counter times 75 1525 %if _PROGRESSAMOUNT 1526 000000B0 B90100 mov cx, _PROGRESSAMOUNT 1527 000000B3 F7F1 div cx ; ax = 0..75 1528 %else 1529 %warning Progress amount is zero 1530 mov ax, 1 1531 %endif 1532 1533 000000B5 3906[8E01] cmp word [.display], ax 1534 000000B9 74C5 je .ret 1535 000000BB A3[8E01] mov word [.display], ax 1536 1537 000000BE 50 push ax 1538 000000BF 91 xchg cx, ax 1539 000000C0 B00D mov al, 13 1540 000000C2 E8F300 call disp_al 1541 000000C5 B05B mov al, '[' 1542 000000C7 E8EE00 call disp_al 1543 000000CA B020 mov al, 32 1544 000000CC E8E900 call disp_al 1545 1546 000000CF B023 mov al, '#' 1547 000000D1 E305 jcxz @FF 1548 @@: 1549 000000D3 E8E200 call disp_al 1550 000000D6 E2FB loop @B 1551 @@: 1552 1553 000000D8 B020 mov al, 32 1554 000000DA 59 pop cx 1555 000000DB 29CB sub bx, cx 1556 000000DD 7607 jbe @FF 1557 000000DF 89D9 mov cx, bx 1558 @@: 1559 000000E1 E8D400 call disp_al 1560 000000E4 E2FB loop @B 1561 @@: 1562 1563 .m4done: 1564 000000E6 E8CF00 call disp_al 1565 000000E9 B05D mov al, ']' 1566 000000EB E8CA00 call disp_al 1567 000000EE EB90 jmp .ret 1568 1569 1570 .4_step: 1571 000000F0 50 push ax 1572 1573 000000F1 BAE803 mov dx, 1000 1574 000000F4 F7E2 mul dx ; dx:ax = counter times 1000 1575 %if _PROGRESSAMOUNT 1576 000000F6 B90100 mov cx, _PROGRESSAMOUNT 1577 000000F9 F7F1 div cx ; ax = 0..1000 1578 %else 1579 %warning Progress amount is zero 1580 mov ax, 1 1581 %endif 1582 1583 000000FB BE[A301] mov si, .message_4_number_end - 1 1584 000000FE E887FF call .format_percentage 1585 1586 00000101 58 pop ax 1587 00000102 BB4B00 mov bx, 80 - 1 - 4 1588 00000105 F7E3 mul bx ; dx:ax = counter times 75 1589 %if _PROGRESSAMOUNT 1590 00000107 B90100 mov cx, _PROGRESSAMOUNT 1591 0000010A F7F1 div cx ; ax = 0..75 1592 %else 1593 %warning Progress amount is zero 1594 mov ax, 1 1595 %endif 1596 1597 0000010C 50 push ax 1598 0000010D 91 xchg cx, ax 1599 0000010E B00D mov al, 13 1600 00000110 E8A500 call disp_al 1601 00000113 B05B mov al, '[' 1602 00000115 E8A000 call disp_al 1603 00000118 B020 mov al, 32 1604 0000011A E89B00 call disp_al 1605 1606 0000011D 31FF xor di, di 1607 0000011F BA2200 mov dx, (80 - 1 - 4 - .message_4_length) / 2 1608 00000122 803E[9F01]20 cmp byte [.message_4_number], 32 1609 00000127 7401 je @F 1610 00000129 47 inc di 1611 @@: 1612 0000012A 29FA sub dx, di 1613 1614 0000012C B023 mov al, '#' 1615 0000012E E306 jcxz @FF 1616 @@: 1617 00000130 E88500 call disp_al 1618 00000133 4A dec dx 1619 00000134 E0FA loopnz @B 1620 @@: 1621 1622 00000136 85D2 test dx, dx 1623 00000138 752E jnz .notyetm4 1624 1625 0000013A BE[9F01] mov si, .message_4 1626 0000013D 29FE sub si, di 1627 0000013F E86800 call disp_error 1628 1629 00000142 29F9 sub cx, di 1630 00000144 760E jbe @FF 1631 00000146 83E907 sub cx, .message_4_length 1632 00000149 7609 jbe @FF 1633 0000014B 89CA mov dx, cx 1634 0000014D B023 mov al, '#' 1635 @@: 1636 0000014F E86600 call disp_al 1637 00000152 E2FB loop @B 1638 @@: 1639 00000154 59 pop cx 1640 00000155 B020 mov al, 32 1641 00000157 83EB29 sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length 1642 0000015A 29D3 sub bx, dx 1643 0000015C 7607 jbe @FF 1644 0000015E 89D9 mov cx, bx 1645 @@: 1646 00000160 E85500 call disp_al 1647 00000163 E2FB loop @B 1648 @@: 1649 00000165 E97EFF jmp .m4done 1650 1651 .notyetm4: 1652 00000168 B020 mov al, 32 1653 0000016A 59 pop cx 1654 0000016B 29CB sub bx, cx 1655 0000016D 7608 jbe @FF 1656 0000016F 89D9 mov cx, bx 1657 @@: 1658 00000171 E84400 call disp_al 1659 00000174 4A dec dx 1660 00000175 E0FA loopnz @B 1661 @@: 1662 1663 00000177 BE[9F01] mov si, .message_4 1664 0000017A 29FE sub si, di 1665 0000017C E82B00 call disp_error 1666 1667 0000017F B020 mov al, 32 1668 00000181 29F9 sub cx, di 1669 00000183 83E907 sub cx, .message_4_length 1670 ; jbe @FF 1671 @@: 1672 00000186 E82F00 call disp_al 1673 00000189 E2FB loop @B 1674 @@: 1675 0000018B E958FF jmp .m4done 1676 %endif 1677 1678 align 2, db 0 1679 %if _PROGRESSMULTI 1680 0000018E FFFF .display: dw -1 1681 %endif 1682 00000190 0000 .counter: dw 0 1683 00000192 0D5B20 .message: db 13,"[ " 1684 00000195 2020312E30 .message_number:db " 1.0" ; enough digit slots for 100.0%, 1685 ; blanks are pre-init until written 1686 .message_number_end: 1687 0000019A 25205D00 db "% ]",0 1688 %if _PROGRESSMULTI 1689 0000019E 20 db " " 1690 .message_4: 1691 0000019F 2020312E30 .message_4_number:db " 1.0" ; enough digit slots for 100.0%, 1692 ; blanks are pre-init until written 1693 .message_4_number_end: 1694 000001A4 252000 db "% ",0 1695 .message_4_length: equ $ - 1 - .message_4 1696 %endif 1697 %endif 1698 1699 1700 %if _DEVICE 1701 align 16 1702 device_header_copy: 1703 .: 1704 .next: 1705 dd -1 ; already initialised 1706 .attributes: 1707 dw _DEVICE_ATTRIBUTE 1708 .strategy: 1709 dw .strategy_entry - . ; -> strategy entry 1710 .interrupt: 1711 dw .interrupt_entry - . ; -> interrupt entry 1712 .name: 1713 fill 8, 32, db _DEVICE_NAME 1714 1715 .strategy_entry: 1716 fill 4, 90h, jmp .set_error ; rel8 or rel16 jump, not minus . 1717 .interrupt_entry: 1718 fill 4, 90h, retf 1719 1720 .set_error: 1721 mov word [es:bx + 3], 8103h ; set error, done, invalid command 1722 retf 1723 .length: equ $ - . 1724 %endif 1725 1726 1727 disp_error.loop: 1728 000001A7 E80E00 call disp_al 1729 disp_error: 1730 000001AA AC lodsb 1731 000001AB 84C0 test al, al 1732 000001AD 75F8 jnz .loop 1733 000001AF C3 retn 1734 1735 %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3 1736 disp_ax_hex: ; ax 1737 xchg al,ah 1738 call disp_al_hex ; display former ah 1739 xchg al,ah ; and fall trough for al 1740 disp_al_hex: ; al 1741 push cx 1742 mov cl,4 1743 ror al,cl 1744 call disp_al_lownibble_hex ; display former high-nibble 1745 rol al,cl 1746 pop cx 1747 ; and fall trough for low-nibble 1748 disp_al_lownibble_hex: 1749 push ax ; save ax for call return 1750 and al,00001111b ; high nibble must be zero 1751 add al,'0' ; if number is 0-9, now it's the correct character 1752 cmp al,'9' 1753 jna .decimalnum ; if we get decimal number with this, ok --> 1754 add al,7 ; otherwise, add 7 and we are inside our alphabet 1755 .decimalnum: 1756 call disp_al 1757 pop ax 1758 retn 1759 %endif 1760 1761 1762 disp_al_for_progress: 1763 %if _PROGRESS && _PROGRESSMULTI 1764 000001B0 2E833E[6800]16 cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base 1765 000001B6 741B je disp_al.retn 1766 %endif 1767 disp_al: 1768 %if _TEST_PROGRAM 1769 000001B8 C3 retn 1770 %else 1771 push ax 1772 %endif 1773 %if _BOOTLDR 1774 000001B9 53 push bx 1775 000001BA 55 push bp 1776 000001BB B40E mov ah, 0Eh 1777 000001BD BB0700 mov bx, 7 1778 %endif 1779 %if _IMAGE_EXE || _DEVICE 1780 000001C0 52 push dx 1781 1782 %if _BOOTLDR 1783 000001C1 F646FE03 test byte [bp - 2], 1 | 2 1784 000001C5 7406 jz .display_kernel_mode 1785 %endif 1786 1787 000001C7 92 xchg dx, ax ; dl = input al 1788 000001C8 B402 mov ah, 02h 1789 000001CA CD21 int 21h 1790 %if _BOOTLDR 1791 000001CC A9 db __TEST_IMM16 ; (skip int) 1792 %endif 1793 1794 .display_kernel_mode: 1795 %endif 1796 %if _BOOTLDR 1797 000001CD CD10 int 10h 1798 %endif 1799 %if _IMAGE_EXE 1800 000001CF 5A pop dx 1801 %endif 1802 %if _BOOTLDR 1803 000001D0 5D pop bp 1804 000001D1 5B pop bx 1805 %endif 1806 000001D2 58 pop ax 1807 .retn: 1808 disp_error.ret: 1809 000001D3 C3 retn 1810 1811 1812 msg: 1813 %if _DEBUG0 1814 .error_begin: db "Load error: Decompression failure, code ",0 1815 .error_end: db "h.",13,10,0 1816 %else 1817 000001D4 4C6F6164206572726F- .error: db "Load error: Decompression failure.",13,10,0 1817 000001DD 723A204465636F6D70- 1817 000001E6 72657373696F6E2066- 1817 000001EF 61696C7572652E0D0A- 1817 000001F8 00 1818 %endif 1819 1820 1821 %endif ; _SCAN 1822 [list +] 1823 1824 %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1 1825 %assign NEED_NORMALISE_BOTH_POINTERS 1 1826 %assign CHECK_POINTERS_VARIABLE_SRC 1 1827 %assign CHECK_POINTERS_VARIABLE_DST 1 1828 %assign SCAN_SUPPORTED 0 1829 1830 ; Specific depacker's file is included within label msg. 1831 ; In the file, lframe is used and lleave ctx is not used. 1832 1833 %if _BRIEFLZ 1834 %include "brieflz.asm" 1835 %endif 1836 1837 1838 %if _LZ4 1839 %include "lz4.asm" 1840 %endif 1841 1842 1843 %if _SNAPPY 1844 %include "snappy.asm" 1845 %endif 1846 1847 1848 %if _EXODECR 1849 %include "exodecr.asm" 1850 %endif 1851 1852 1853 %if _X 1854 %include "x.asm" 1855 %endif 1856 1857 1858 %if _HEATSHRINK 1859 %include "heatshr.asm" 1860 %endif 1861 1862 1863 %if _LZD 1864 %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> %if _SCAN 26 <1> %assign SCAN_SUPPORTED 1 27 <1> 28 <1> int3 29 <1> jmp depack 30 <1> %endif 31 <1> 32 <1> 33 <1> numdef COUNTER, 0, 256 34 <1> %if (_COUNTER - 1) & _COUNTER 35 <1> %error COUNTER must be a power of two 36 <1> %endif 37 <1> 38 <1> 39 <1> amount_states equ 12 40 <1> 41 <1> numdef XLATBSEQ, 7 42 <1> numdef WARNXLATBSEQ, 0 43 <1> 44 <1> 45 <1> %if _XLATBSEQ != 7 46 <1> next_states.beforealign: 47 <1> align 2 48 <1> next_states: 49 <1> .: 50 <1> times 4 db 0 51 <1> db 1, 2, 3, 4, 5, 6, 4, 5 52 <1> .amount: equ $ - . 53 <1> %if .amount != amount_states 54 <1> %error Invalid next_states array content 55 <1> %endif 56 <1> %assign XLATBTABSIZE $ - .beforealign 57 <1> %else 58 <1> %assign XLATBTABSIZE 0 59 <1> %endif 60 <1> 61 <1> 62 <1> State: 63 <1> ; INP: ds:bx -> localvariables 64 <1> ; byte [bx + state.st] 65 <1> ; OUT: CY if st < 7 (is_char() == true) 66 <1> ; NC if st >= 7 (is_char() == false) 67 <1> ; CHG: - 68 <1> .is_char: 69 000001F9 807F2807 <1> cmp byte [bx + state.st], 7 70 000001FD C3 <1> retn 71 <1> 72 <1> 73 <1> ; INP: ds:bx -> localvariables 74 <1> ; byte [bx + state.st] 75 <1> ; OUT: byte [bx + state.st] = al = next state 76 <1> ; CHG: al, ah (ah only if _XLATBSEQ == 6) 77 <1> .set_char: 78 <1> 79 <1> .xlatbseq: 80 <1> %if 0 == _XLATBSEQ ; 10 81 <1> push bx 82 <1> mov al, byte [bx + state.st] 83 <1> mov bx, next_states 84 <1> cs xlatb 85 <1> ; Problem: It is reported that prior to the 386 86 <1> ; a segment override on an xlatb instruction 87 <1> ; does not have any effect. So this choice is 88 <1> ; possibly wrong on those machines. 89 <1> pop bx 90 <1> %elif 1 == _XLATBSEQ ; 13 91 <1> push bx 92 <1> mov al, byte [bx + state.st] 93 <1> mov bx, next_states 94 <1> push ds 95 <1> push cs 96 <1> pop ds 97 <1> xlatb 98 <1> pop ds 99 <1> pop bx 100 <1> %elif 2 == _XLATBSEQ ; 16 101 <1> push bx 102 <1> mov al, byte [bx + state.st] 103 <1> mov bx, next_states 104 <1> add bl, al 105 <1> adc bh, 0 106 <1> mov al, byte [cs:bx] 107 <1> pop bx 108 <1> %elif 3 == _XLATBSEQ ; 14 109 <1> push bx 110 <1> mov al, byte [bx + state.st] 111 <1> xor bx, bx 112 <1> mov bl, al 113 <1> mov al, byte [cs:next_states + bx] 114 <1> pop bx 115 <1> %elif 4 == _XLATBSEQ ; 12 116 <1> push bx 117 <1> mov bl, byte [bx + state.st] 118 <1> mov bh, 0 119 <1> mov al, byte [cs:next_states + bx] 120 <1> pop bx 121 <1> %elif 5 == _XLATBSEQ ; 10 122 <1> push bx 123 <1> mov bl, byte [bx + state.st] 124 <1> ; mov bh, 0 125 <1> ; ! because the pointer stored in ?localvariables 126 <1> ; is normalised bh is already zero here. 127 <1> mov al, byte [cs:next_states + bx] 128 <1> pop bx 129 <1> %elif 6 == _XLATBSEQ ; 12 130 <1> xor ax, ax 131 <1> mov al, byte [bx + state.st] 132 <1> xchg ax, bx 133 <1> mov bl, byte [cs:next_states + bx] 134 <1> xchg ax, bx 135 <1> %elif 7 == _XLATBSEQ ; 16, but minus 13 for table 136 000001FE 8A4728 <1> mov al, byte [bx + state.st] 137 00000201 2C03 <1> sub al, 3 ; below 4 ? 138 00000203 7607 <1> jbe .zero ; yes --> 139 00000205 3C07 <1> cmp al, 10 - 3 ; 10 or 11 initially ? 140 00000207 7202 <1> jb .have ; no --> 141 00000209 2C03 <1> sub al, 3 ; convert 142 <1> .have: 143 0000020B A9 <1> db __TEST_IMM16 ; (skip mov) 144 <1> .zero: 145 0000020C B000 <1> mov al, 0 146 <1> %else 147 <1> %error Invalid xlatb sequence specified 148 <1> %endif 149 <1> %if _WARNXLATBSEQ 150 <1> %assign SIZE $ - .xlatbseq 151 <1> %warning xlatb sequence takes SIZE bytes plus XLATBTABSIZE table 152 <1> %endif 153 <1> .end: 154 0000020E 884728 <1> mov byte [bx + state.st], al 155 00000211 C3 <1> retn 156 <1> 157 <1> 158 <1> ; INP: ds:bx -> localvariables 159 <1> ; byte [bx + state.st] 160 <1> ; al = value to use if is_char() == true 161 <1> ; ah = value to use else 162 <1> ; OUT: byte [bx + state.st] = al = value to use 163 <1> ; CHG: al 164 <1> .select: 165 00000212 E8E4FF <1> call .is_char 166 00000215 72F7 <1> jc .end 167 00000217 88E0 <1> mov al, ah 168 00000219 EBF3 <1> jmp .end 169 <1> 170 <1> 171 <1> min_dictionary_size: equ 1 << 12 172 <1> max_dictionary_size: equ 1 << 29 173 <1> literal_context_bits: equ 3 174 <1> literal_pos_state_bits: equ 0 ; not used 175 <1> pos_state_bits: equ 2 176 <1> pos_states: equ 1 << pos_state_bits 177 <1> pos_state_mask: equ pos_states - 1 178 <1> 179 <1> len_states: equ 4 180 <1> dis_slot_bits: equ 6 181 <1> start_dis_model: equ 4 182 <1> end_dis_model: equ 14 183 <1> modeled_distances: equ 1 << ( end_dis_model / 2 ) ; 128 184 <1> dis_align_bits: equ 4 185 <1> dis_align_size: equ 1 << dis_align_bits 186 <1> 187 <1> len_low_bits: equ 3 188 <1> len_mid_bits: equ 3 189 <1> len_high_bits: equ 8 190 <1> len_low_symbols: equ 1 << len_low_bits 191 <1> len_mid_symbols: equ 1 << len_mid_bits 192 <1> len_high_symbols: equ 1 << len_high_bits 193 <1> max_len_symbols: equ len_low_symbols + len_mid_symbols + len_high_symbols 194 <1> 195 <1> min_match_len: equ 2 ; must be 2 196 <1> 197 <1> bit_model_move_bits: equ 5 198 <1> bit_model_total_bits: equ 11 199 <1> bit_model_total: equ 1 << bit_model_total_bits 200 <1> 201 <1> 202 <1> struc bit_model 203 00000000 ???? <1> .probability: resw 1 ; initialise to bit_model_total / 2 204 <1> ; at most bit_model_total (800h) 205 <1> endstruc 206 <1> 207 <1> struc len_model 208 00000000 ???? <1> .choice1: resb bit_model_size 209 00000002 ???? <1> .choice2: resb bit_model_size 210 00000004 <1> .bm_low: resb bit_model_size * pos_states * len_low_symbols 211 00000044 <1> .bm_mid: resb bit_model_size * pos_states * len_mid_symbols 212 00000084 <1> .bm_high: resb bit_model_size * len_high_symbols 213 <1> endstruc 214 <1> 215 <1> struc lzip_header 216 00000000 ???????? <1> .magic: resd 1 217 00000004 ?? <1> .version: resb 1 218 00000005 ?? <1> .coded_dict_size: resb 1 219 <1> endstruc 220 <1> 221 <1> struc lzip_trailer 222 00000000 ???????? <1> .uncompressed_checksum: resd 1 223 00000004 ???????????????? <1> .uncompressed_size: resq 1 224 0000000C ???????????????? <1> .member_size: resq 1 225 <1> endstruc 226 <1> 227 <1> struc range_decoder 228 00000000 ???????? <1> .member_pos: resd 1 229 00000004 ???????? <1> .code: resd 1 230 00000008 ???????? <1> .range: resd 1 231 <1> endstruc 232 <1> 233 <1> ; INP: ds:bx -> range_decoder structure 234 <1> ; ss:bp -> depack stack frame 235 <1> ; OUT: ! If an error occurs, jumps to depack.error 236 <1> ; CHG: es, di, ax, cx 237 <1> Range_decoder.init: 238 0000021B 1E <1> push ds 239 0000021C 07 <1> pop es 240 0000021D B80600 <1> mov ax, 6 241 00000220 89DF <1> mov di, bx ; -> .member_pos 242 00000222 AB <1> stosw ; low word of .member_pos 243 00000223 31C0 <1> xor ax, ax 244 00000225 AB <1> stosw ; high word of .member_pos 245 00000226 AB <1> stosw 246 00000227 AB <1> stosw ; .code 247 00000228 48 <1> dec ax 248 00000229 AB <1> stosw 249 0000022A AB <1> stosw ; .range 250 0000022B B90500 <1> mov cx, 5 251 <1> .loop: 252 0000022E E81900 <1> call getbyteshiftcode 253 00000231 E2FB <1> loop .loop 254 00000233 C3 <1> retn 255 <1> 256 <1> 257 <1> ; INP: ds:bx -> range_decoder structure 258 <1> ; ss:bp -> depack stack frame 259 <1> ; OUT: ! If an error occurs, jumps to depack.error 260 <1> ; CHG: - 261 <1> normaliserange: 262 00000234 807F0B00 <1> cmp byte [bx + range_decoder.range + 3], 0 263 00000238 7521 <1> jnz @F ; (retn) 264 0000023A 50 <1> push ax 265 0000023B 8B4709 <1> mov ax, word [bx + range_decoder.range + 1] 266 0000023E 89470A <1> mov word [bx + range_decoder.range + 2], ax 267 00000241 8A6708 <1> mov ah, byte [bx + range_decoder.range] 268 00000244 B000 <1> mov al, 0 269 00000246 894708 <1> mov word [bx + range_decoder.range], ax 270 00000249 58 <1> pop ax 271 <1> ; fall through 272 <1> 273 <1> 274 <1> ; INP: ds:bx -> range_decoder structure 275 <1> ; ss:bp -> depack stack frame 276 <1> ; OUT: ! If an error occurs, jumps to depack.error 277 <1> ; CHG: - 278 <1> getbyteshiftcode: 279 0000024A 50 <1> push ax 280 0000024B 8B4705 <1> mov ax, word [bx + range_decoder.code + 1] 281 0000024E 894706 <1> mov word [bx + range_decoder.code + 2], ax 282 00000251 8A6704 <1> mov ah, byte [bx + range_decoder.code] 283 00000254 E8AC06 <1> call Range_decoder.get_byte 284 00000257 894704 <1> mov word [bx + range_decoder.code], ax 285 0000025A 58 <1> pop ax 286 <1> @@: 287 0000025B C3 <1> retn 288 <1> 289 <1> 290 <1> ; INP: ds:bx -> range_decoder structure 291 <1> ; cx = num_bits 292 <1> ; ss:bp -> depack stack frame 293 <1> ; OUT: ! If an error occurs, jumps to depack.error 294 <1> ; If success, 295 <1> ; dx:ax = symbol 296 <1> ; CHG: di, cx 297 <1> Range_decoder.decode: 298 0000025C 31D2 <1> xor dx, dx 299 0000025E 31C0 <1> xor ax, ax 300 00000260 E32C <1> jcxz .end 301 <1> .loop: 302 00000262 D16F0A <1> shr word [bx + range_decoder.range + 2], 1 303 00000265 D15F08 <1> rcr word [bx + range_decoder.range], 1 304 00000268 D1E0 <1> shl ax, 1 305 0000026A D1D2 <1> rcl dx, 1 306 0000026C 8B7F06 <1> mov di, word [bx + range_decoder.code + 2] 307 0000026F 3B7F0A <1> cmp di, word [bx + range_decoder.range + 2] 308 00000272 7506 <1> jne @F 309 00000274 8B7F04 <1> mov di, word [bx + range_decoder.code] 310 00000277 3B7F08 <1> cmp di, word [bx + range_decoder.range] 311 <1> @@: ; code >= range ? 312 0000027A 720D <1> jnae @F ; no, skip --> 313 0000027C 8B7F08 <1> mov di, word [bx + range_decoder.range] 314 0000027F 297F04 <1> sub word [bx + range_decoder.code], di 315 00000282 8B7F0A <1> mov di, word [bx + range_decoder.range + 2] 316 00000285 197F06 <1> sbb word [bx + range_decoder.code + 2], di 317 00000288 40 <1> inc ax ; symbol |= 1 (lowest bit always was zero) 318 <1> @@: 319 00000289 E8A8FF <1> call normaliserange 320 0000028C E2D4 <1> loop .loop 321 <1> .end: 322 0000028E C3 <1> retn 323 <1> 324 <1> 325 <1> ; INP: ds:bx -> range_decoder structure 326 <1> ; es:di -> bit_model structure 327 <1> ; ss:bp -> depack stack frame 328 <1> ; OUT: al = read bit 329 <1> ; NC if zero read 330 <1> ; CY if one read 331 <1> ; ! If an error occurs, jumps to depack.error 332 <1> ; CHG: cx, dx, ax 333 <1> Range_decoder.decode_bit: 334 0000028F 8B570A <1> mov dx, word [bx + range_decoder.range + 2] 335 00000292 8B4708 <1> mov ax, word [bx + range_decoder.range] 336 00000295 B90B00 <1> mov cx, bit_model_total_bits 337 <1> @@: 338 00000298 D1EA <1> shr dx, 1 339 0000029A D1D8 <1> rcr ax, 1 340 0000029C E2FA <1> loop @B 341 <1> 342 0000029E 89D1 <1> mov cx, dx 343 000002A0 26F725 <1> mul word [es:di + bit_model.probability] 344 <1> ; dx:ax = low word + first high word 345 000002A3 52 <1> push dx 346 000002A4 50 <1> push ax ; on stack = low word + first high word 347 000002A5 91 <1> xchg ax, cx 348 000002A6 26F725 <1> mul word [es:di + bit_model.probability] 349 <1> ; ax = second high word (dx overflow) 350 000002A9 91 <1> xchg ax, cx ; cx 351 000002AA 58 <1> pop ax 352 000002AB 5A <1> pop dx 353 000002AC 01CA <1> add dx, cx ; = full uint32_t result 354 000002AE B90500 <1> mov cx, bit_model_move_bits 355 <1> 356 000002B1 395706 <1> cmp word [bx + range_decoder.code + 2], dx 357 000002B4 7503 <1> jne @F 358 000002B6 394704 <1> cmp word [bx + range_decoder.code], ax 359 <1> @@: 360 000002B9 7317 <1> jnb .not_code_below_bound 361 <1> 362 <1> .code_below_bound: 363 000002BB 894708 <1> mov word [bx + range_decoder.range], ax 364 000002BE 89570A <1> mov word [bx + range_decoder.range + 2], dx 365 000002C1 B80008 <1> mov ax, bit_model_total 366 000002C4 262B05 <1> sub ax, word [es:di + bit_model.probability] 367 000002C7 7228 <1> jc .error 368 000002C9 D3E8 <1> shr ax, cl 369 000002CB 260105 <1> add word [es:di + bit_model.probability], ax 370 000002CE B000 <1> mov al, 0 371 000002D0 EB18 <1> jmp .after_if 372 <1> 373 <1> .not_code_below_bound: 374 000002D2 294708 <1> sub word [bx + range_decoder.range], ax 375 000002D5 19570A <1> sbb word [bx + range_decoder.range + 2], dx 376 000002D8 294704 <1> sub word [bx + range_decoder.code], ax 377 000002DB 195706 <1> sbb word [bx + range_decoder.code + 2], dx 378 <1> 379 000002DE 268B05 <1> mov ax, word [es:di + bit_model.probability] 380 000002E1 D3E8 <1> shr ax, cl 381 000002E3 262905 <1> sub word [es:di + bit_model.probability], ax 382 000002E6 7209 <1> jc .error 383 000002E8 B001 <1> mov al, 1 384 <1> 385 <1> .after_if: 386 000002EA E847FF <1> call normaliserange 387 000002ED 3C01 <1> cmp al, 1 ; CY if 0, NC if 1 388 000002EF F5 <1> cmc ; NC if 0, CY if 1 389 000002F0 C3 <1> retn 390 <1> 391 <1> .error: 392 000002F1 E9FE05 <1> jmp depack.error 393 <1> 394 <1> 395 <1> ; INP: ds:bx -> range_decoder structure 396 <1> ; es:di -> bit_model structure array 397 <1> ; cx = num_bits, <= 15 398 <1> ; ss:bp -> depack stack frame 399 <1> ; OUT: ! If an error occurs, jumps to depack.error 400 <1> ; If success, 401 <1> ; dx:ax = ax = symbol 402 <1> ; CHG: cx, si 403 <1> Range_decoder.decode_tree: 404 000002F4 BE0100 <1> mov si, 1 ; symbol = 1 405 000002F7 83F90F <1> cmp cx, 15 406 000002FA 7721 <1> ja .error 407 000002FC 51 <1> push cx 408 000002FD E312 <1> jcxz .end 409 <1> .loop: 410 000002FF 57 <1> push di 411 <1> ; Here si (symbol) is at most 1 << 14. 412 <1> %if bit_model_size != 2 413 <1> %error Assuming word size for bit_model_size 414 <1> %endif 415 00000300 D1E6 <1> shl si, 1 ; Note that this shift is both used instead of 416 <1> ; multiplying symbol (si) by bit_model_size 417 <1> ; and to actually shift symbol (si) left! 418 00000302 01F7 <1> add di, si ; index into bit_model array 419 00000304 7217 <1> jc .error_pop_2 420 00000306 51 <1> push cx 421 00000307 E885FF <1> call Range_decoder.decode_bit 422 0000030A 59 <1> pop cx 423 0000030B 83D600 <1> adc si, 0 ; add in the decoded bit 424 0000030E 5F <1> pop di 425 0000030F E2EE <1> loop .loop 426 <1> .end: 427 00000311 59 <1> pop cx 428 00000312 B80100 <1> mov ax, 1 429 00000315 D3E0 <1> shl ax, cl ; = 1 << num_bits 430 00000317 29C6 <1> sub si, ax ; symbol - ( 1 << num_bits ) 431 00000319 96 <1> xchg ax, si 432 0000031A 31D2 <1> xor dx, dx ; return symbol 433 0000031C C3 <1> retn 434 <1> 435 <1> .error_pop_2: 436 <1> .error: 437 0000031D E9D205 <1> jmp depack.error 438 <1> 439 <1> 440 <1> ; INP: ds:bx -> range_decoder structure 441 <1> ; es:di -> bit_model structure array 442 <1> ; cx = num_bits, <= 15 443 <1> ; ss:bp -> depack stack frame 444 <1> ; OUT: ! If an error occurs, jumps to depack.error 445 <1> ; If success, 446 <1> ; dx:ax = ax = reversed_symbol 447 <1> ; CHG: cx, si 448 <1> Range_decoder.decode_tree_reversed: 449 00000320 51 <1> push cx 450 00000321 E8D0FF <1> call Range_decoder.decode_tree 451 00000324 59 <1> pop cx 452 00000325 92 <1> xchg dx, ax ; dx = symbol 453 00000326 31C0 <1> xor ax, ax ; = reversed_symbol 454 00000328 E306 <1> jcxz .end 455 <1> .loop: 456 0000032A D1EA <1> shr dx, 1 457 0000032C D1D0 <1> rcl ax, 1 458 0000032E E2FA <1> loop .loop 459 <1> .end: 460 00000330 31D2 <1> xor dx, dx 461 00000332 C3 <1> retn 462 <1> 463 <1> 464 <1> ; INP: ds:bx -> range_decoder structure 465 <1> ; es:di -> bit_model structure array 466 <1> ; al = match_byte 467 <1> ; ss:bp -> depack stack frame 468 <1> ; OUT: ! If an error occurs, jumps to depack.error 469 <1> ; If success, 470 <1> ; al = return value (symbol & 0FFh) 471 <1> ; CHG: cx, dx, ax 472 <1> Range_decoder.decode_matched: 473 00000333 88C6 <1> mov dh, al ; = match_byte 474 <1> 475 00000335 B80100 <1> mov ax, 1 ; initialise symbol = 1 476 <1> 477 00000338 B90800 <1> mov cx, 8 478 <1> .loop: 479 0000033B 52 <1> push dx ; preserve dh = match_byte 480 0000033C 51 <1> push cx ; preserve loop counter 481 0000033D 49 <1> dec cx 482 0000033E D2EE <1> shr dh, cl ; match_byte >> i 483 00000340 81E20001 <1> and dx, 100h ; dh &= 1 = match_bit, dl = 0 484 00000344 52 <1> push dx 485 00000345 FEC6 <1> inc dh ; = (match_bit << 8) + 100h 486 00000347 01C2 <1> add dx, ax ; = symbol + (match_bit << 8) + 100h 487 <1> ; As symbol is below 256, this is at most 255 + 100h + 100h, 488 <1> ; which is 2FFh. As such, the bm_literal array's 489 <1> ; entries are arrays of 300h bit_model each. 490 00000349 57 <1> push di 491 0000034A 50 <1> push ax 492 <1> %if bit_model_size != 2 493 <1> %error Assuming word size for bit_model_size 494 <1> %endif 495 0000034B 01D2 <1> add dx, dx 496 <1> ; As dx was < 300h before this addition, it cannot carry. 497 0000034D 01D7 <1> add di, dx 498 <1> ; We assume that this does not carry. 499 0000034F E83DFF <1> call Range_decoder.decode_bit 500 00000352 91 <1> xchg ax, cx ; cl = result (1 or 0) 501 00000353 58 <1> pop ax ; = symbol 502 00000354 5F <1> pop di 503 00000355 5A <1> pop dx ; = match_bit << 8 504 00000356 D1D0 <1> rcl ax, 1 ; shift symbol, OR in the bit 505 <1> ; As the loop counter is initialised to 8, 506 <1> ; the symbol variable stays below 256. 507 00000358 38F1 <1> cmp cl, dh ; if( match_bit != bit ) ...- 508 0000035A 59 <1> pop cx ; = loop counter 509 0000035B 5A <1> pop dx ; = dh = match_byte 510 0000035C 7519 <1> jne .inner_next ; -... do the following --> 511 <1> .next: 512 0000035E E2DB <1> loop .loop 513 <1> .end: 514 00000360 30E4 <1> xor ah, ah ; return ax = symbol & 0FFh 515 00000362 C3 <1> retn 516 <1> 517 <1> .error_pop_2: 518 <1> .error: 519 00000363 E98C05 <1> jmp depack.error 520 <1> 521 <1> 522 <1> .inner_loop: 523 00000366 50 <1> push ax 524 <1> %if bit_model_size != 2 525 <1> %error Assuming word size for bit_model_size 526 <1> %endif 527 00000367 01C0 <1> add ax, ax 528 00000369 57 <1> push di 529 0000036A 01C7 <1> add di, ax 530 0000036C 72F5 <1> jc .error_pop_2 531 0000036E E81EFF <1> call Range_decoder.decode_bit 532 00000371 5F <1> pop di 533 00000372 58 <1> pop ax 534 00000373 D1D0 <1> rcl ax, 1 535 00000375 72EC <1> jc .error 536 <1> 537 <1> .inner_next: 538 00000377 3D0001 <1> cmp ax, 100h 539 0000037A 72EA <1> jb .inner_loop 540 0000037C EBE2 <1> jmp .end 541 <1> 542 <1> 543 <1> ; INP: ds:bx -> range_decoder structure 544 <1> ; es:di -> len_model structure 545 <1> ; ax = pos_state 546 <1> ; ss:bp -> depack stack frame 547 <1> ; OUT: ! If an error occurs, jumps to depack.error 548 <1> ; If success, 549 <1> ; dx:ax = return 550 <1> ; CHG: cx, si 551 <1> Range_decoder.decode_len: 552 0000037E 89C6 <1> mov si, ax ; = pos_state 553 00000380 57 <1> push di ; = len_model_struc (on stack) 554 <1> 555 00000381 8D3D <1> lea di, [di + len_model.choice1] 556 00000383 E809FF <1> call Range_decoder.decode_bit 557 00000386 5F <1> pop di ; reset to ?len_model_struc 558 00000387 57 <1> push di 559 00000388 7218 <1> jc .not_decode_bit_choice1_equals_zero 560 <1> 561 0000038A 8D7D04 <1> lea di, [di + len_model.bm_low] 562 0000038D B81000 <1> mov ax, len_low_symbols * bit_model_size 563 00000390 F7E6 <1> mul si 564 00000392 85D2 <1> test dx, dx 565 00000394 7546 <1> jnz .error 566 00000396 01C7 <1> add di, ax 567 00000398 7242 <1> jc .error 568 0000039A B90300 <1> mov cx, len_low_bits 569 0000039D E854FF <1> call Range_decoder.decode_tree 570 000003A0 EB38 <1> jmp .ret 571 <1> 572 <1> .not_decode_bit_choice1_equals_zero: 573 000003A2 8D7D02 <1> lea di, [di + len_model.choice2] 574 000003A5 E8E7FE <1> call Range_decoder.decode_bit 575 000003A8 5F <1> pop di ; reset to ?len_model_struc 576 000003A9 57 <1> push di 577 000003AA 721E <1> jc .not_decode_bit_choice2_equals_zero 578 <1> 579 000003AC 8D7D44 <1> lea di, [di + len_model.bm_mid] 580 000003AF B81000 <1> mov ax, len_mid_symbols * bit_model_size 581 000003B2 F7E6 <1> mul si 582 000003B4 85D2 <1> test dx, dx 583 000003B6 7524 <1> jnz .error 584 000003B8 01C7 <1> add di, ax 585 000003BA 7220 <1> jc .error 586 000003BC B90300 <1> mov cx, len_mid_bits 587 000003BF E832FF <1> call Range_decoder.decode_tree 588 000003C2 83C008 <1> add ax, len_low_symbols & 0FFFFh 589 000003C5 83D200 <1> adc dx, len_low_symbols >> 16 590 000003C8 EB10 <1> jmp .ret 591 <1> 592 <1> .not_decode_bit_choice2_equals_zero: 593 000003CA 8DBD8400 <1> lea di, [di + len_model.bm_high] 594 000003CE B90800 <1> mov cx, len_high_bits 595 000003D1 E820FF <1> call Range_decoder.decode_tree 596 000003D4 83C010 <1> add ax, (len_low_symbols + len_mid_symbols) & 0FFFFh 597 000003D7 83D200 <1> adc dx, (len_low_symbols + len_mid_symbols) >> 16 598 <1> .ret: 599 000003DA 5F <1> pop di 600 000003DB C3 <1> retn 601 <1> 602 <1> .error: 603 000003DC E91305 <1> jmp depack.error 604 <1> 605 <1> 606 <1> struc lz_decoder 607 00000000 <1> .range_decoder: resb range_decoder_size 608 0000000C ???????? <1> alignb 8 609 00000010 ???????? <1> .dictionary_size: resd 1 610 00000014 ???????? <1> .pos: resd 1 611 <1> endstruc 612 <1> 613 <1> 614 <1> ; INP: ds:bx -> lz_decoder structure, localvariables structure 615 <1> ; dx:ax = distance 616 <1> ; OUT: al = ax = byte from buffer 617 <1> ; CHG: dx, cx, di, si, es 618 <1> LZ_decoder.peek: 619 000003DF 395716 <1> cmp word [bx + lz_decoder.pos + 2], dx 620 000003E2 7503 <1> jne @F 621 000003E4 394714 <1> cmp word [bx + lz_decoder.pos], ax 622 <1> @@: 623 000003E7 760A <1> jna .not_pos_above_distance 624 <1> 625 000003E9 E80A00 <1> call calculate_peek_pointer_disi 626 <1> 627 000003EC 8EC7 <1> mov es, di ; es:si -> peek address 628 000003EE 31C0 <1> xor ax, ax 629 000003F0 26AC <1> es lodsb 630 000003F2 C3 <1> retn 631 <1> 632 <1> .not_pos_above_distance: 633 000003F3 31C0 <1> xor ax, ax 634 000003F5 C3 <1> retn 635 <1> 636 <1> 637 <1> ; INP: dx:ax = peek distance 638 <1> ; ds:bx -> local variables 639 <1> ; OUT: di:si -> peek address 640 <1> ; CHG: cx, dx, ax 641 <1> calculate_peek_pointer_disi: 642 000003F6 53 <1> push bx 643 000003F7 FF772E <1> push word [bx + destinationbuffer_constant + 2] 644 000003FA FF772C <1> push word [bx + destinationbuffer_constant] 645 <1> 646 000003FD F7DA <1> neg dx 647 000003FF F7D8 <1> neg ax 648 00000401 83DA00 <1> sbb dx, byte 0 ; neg dx:ax = - distance 649 00000404 83E801 <1> sub ax, 1 650 00000407 83DA00 <1> sbb dx, 0 ; - 1 651 0000040A 034714 <1> add ax, word [bx + lz_decoder.pos] 652 0000040D 135716 <1> adc dx, word [bx + lz_decoder.pos + 2] 653 <1> ; + pos 654 00000410 91 <1> xchg cx, ax 655 00000411 87DA <1> xchg bx, dx 656 <1> 657 00000413 E89406 <1> call normalise_pointer_with_displacement_bxcx 658 00000416 5E <1> pop si 659 00000417 5F <1> pop di ; di:si -> source 660 00000418 5B <1> pop bx 661 00000419 C3 <1> retn 662 <1> 663 <1> 664 <1> ; INP: ss:bp -> depack stack frame 665 <1> ; OUT: ! If an error occurs, jumps to depack.error 666 <1> ; If success, 667 <1> ; al = byte 668 <1> ; CHG: - 669 <1> LZ_decoder.get_byte: equ Range_decoder.get_byte 670 <1> 671 <1> 672 <1> struc localvariables 673 <1> lz_decoder_struc: 674 00000000 <1> resb lz_decoder_size 675 <1> alignb 4 676 <1> zeros_start: 677 00000018 ???????? <1> rep0: resd 1 678 0000001C ???????? <1> rep1: resd 1 679 00000020 ???????? <1> rep2: resd 1 680 00000024 ???????? <1> rep3: resd 1 681 00000028 ???? <1> state.st: resw 1 ; initialise to zero 682 0000002A ???? <1> alignb 4 683 <1> zeros_end: 684 0000002C ???????? <1> destinationbuffer_constant: resd 1 ; stays constant 685 <1> alignb 16 686 <1> bit_models_start: 687 00000030 <1> bm_match: resb bit_model_size * amount_states * pos_states 688 00000090 <1> bm_rep: resb bit_model_size * amount_states 689 000000A8 <1> bm_rep0: resb bit_model_size * amount_states 690 000000C0 <1> bm_rep1: resb bit_model_size * amount_states 691 000000D8 <1> bm_rep2: resb bit_model_size * amount_states 692 000000F0 <1> bm_literal: resb bit_model_size * (1 << literal_context_bits) * 300h 693 000030F0 <1> bm_len: resb bit_model_size * amount_states * pos_states 694 00003150 <1> bm_dis_slot: resb bit_model_size * len_states * (1 << dis_slot_bits) 695 00003350 <1> bm_dis: resb bit_model_size * (modeled_distances - end_dis_model + 1) 696 00003436 <1> bm_align: resb bit_model_size * dis_align_size 697 00003456 <1> match_len_model:resb len_model_size 698 000036DA <1> rep_len_model: resb len_model_size 699 <1> bit_models_end: 700 0000395E ???? <1> alignb 16 701 <1> endstruc 702 <1> %if lz_decoder_struc != 0 703 <1> %error Expecting lz_decoder structure at start of localvariables structure 704 <1> %endif 705 <1> %assign STRUCSIZE localvariables_size 706 <1> %warning localvariables has STRUCSIZE bytes 706 ****************** <1> warning: localvariables has 14688 bytes [-w+user] 707 <1> 708 <1> 709 0000041A 90 <1> align 4 710 <1> lzip_header_bytes: 711 <1> .: 712 0000041C 4C5A495001 <1> db "LZIP",1 713 <1> .length: equ $ - . 714 <1> 715 <1> 716 <1> ; INP: ds:si -> source 717 <1> ; dx:cx = length of source 718 <1> ; es:di -> destination (below source) 719 <1> ; if _IMAGE_EXE: 720 <1> ; bx = EXE mode flag (bit 0) 721 <1> ; else: 722 <1> ; bx = 0 723 <1> ; if _PAYLOAD_KERNEL_MAX_PARAS: 724 <1> ; ax = maximum amount in paragraphs of destination needed 725 <1> ; (-1 if full source should be decompressed) 726 <1> ; else: 727 <1> ; ax = -1 728 <1> ; OUT: NC if success 729 <1> ; CY if error, 730 <1> ; bx = ?errordata (if _DEBUG0) 731 <1> ; CHG: ax, (bx), cx, dx, es, ds, si, di 732 <1> ; STT: UP 733 <1> ; 734 <1> ; Note: The destination reaches up to below the source. 735 <1> ; Note: The input pointers need not be normalised yet. 736 <1> ; Normalised means that the offset part is below 16. 737 <1> depack: 738 <1> lframe near 739 <1> %if _SCAN 740 <1> lpar word, buffer 741 <1> lpar word, bufferparas 742 <1> lpar dword, bufferbytes 743 <1> lpar dword, progressticks 744 <1> lpar dword, maxbytesahead 745 <1> lpar dword, depackedsize 746 <1> lpar_return 747 <1> xor di, di 748 <1> mov es, di ; destination = all-zeroes (special) 749 <1> %endif 750 <1> %if _IMAGE_EXE || _COUNTER || _DEBUG0 751 00000421 5589E5 <1> lenter early 752 <1> %if _IMAGE_EXE 753 <1> lvar word, exemode ; must be bp - 2! 754 00000424 53 <1> push bx 755 <1> %if ?exemode != -2 756 <1> %error exemode variable must be directly below bp 757 <1> %endif 758 <1> %endif 759 <1> %if _COUNTER || _DEBUG0 760 00000425 31DB <1> xor bx, bx 761 <1> %endif 762 <1> %endif 763 <1> %if _COUNTER 764 <1> lvar word, counter 765 00000427 53 <1> push bx ; initialise counter to zero 766 <1> %endif 767 <1> d0 lvar word, errordata 768 <1> d0 push bx 769 <1> lvar dword, distance 770 <1> lvar dword, len 771 <1> lvar dword, dis_slot 772 <1> lvar word, len_state 773 <1> lvar word, pos_state 774 <1> %if _SCAN 775 <1> lvar dword, plusdst 776 <1> lvar dword, plussrc 777 <1> %endif 778 00000428 8D66EC <1> lenter 779 <1> 780 0000042B E84B06 <1> call normalise_both_pointers 781 <1> 782 <1> ; ! di < 16, so dih == 0 783 <1> lvar dword, src 784 0000042E 1E <1> push ds 785 0000042F 56 <1> push si 786 <1> 787 <1> %if _SCAN 788 <1> lvar dword, original_src 789 <1> push ds 790 <1> push si 791 <1> 792 <1> mov es, word [bp + ?buffer] 793 <1> xor di, di 794 <1> %endif 795 <1> lvar dword, final_dst 796 00000430 06 <1> push es 797 00000431 57 <1> push di 798 <1> lequ ?final_dst, localvariables 799 <1> ; ! offset of ?localvariables is always < 16 800 <1> ; required for State.set_char with _XLATBSEQ == 5 801 <1> lvar dword, length_of_source 802 00000432 52 <1> push dx 803 00000433 51 <1> push cx 804 <1> 805 <1> %if _PAYLOAD_KERNEL_MAX_PARAS 806 <1> cmp ax, -1 ; no maximum specified ? 807 <1> je @FF ; retain -1 in ax --> 808 <1> test di, di ; do we need an additional paragraph ? 809 <1> jz @F ; no --> 810 <1> inc ax ; es + ax => paragraph after necessary part 811 <1> @@: 812 <1> mov dx, es 813 <1> add ax, dx ; => paragraph after necessary part 814 <1> ; If the normalised destination pointer's segment grows 815 <1> ; to this segment then enough has been decompressed. 816 <1> d0 mov byte [bp + ?errordata], 40h 817 <1> jc .error_CY_a1 ; should not carry 818 <1> @@: 819 <1> lvar word, dst_max_segment 820 <1> push ax 821 <1> %endif 822 <1> 823 <1> %if _SCAN 824 <1> LENDST equ 960 * 1024 825 <1> mov bx, LENDST >> 16 826 <1> mov cx, LENDST & 0FFFFh 827 <1> %else 828 00000434 1E <1> push ds 829 00000435 56 <1> push si 830 00000436 E8A006 <1> call pointer_to_linear 831 <1> 832 00000439 87DA <1> xchg bx, dx 833 0000043B 91 <1> xchg cx, ax ; bx:cx = source linear, clobber dx:ax 834 <1> 835 0000043C 06 <1> push es 836 0000043D 57 <1> push di 837 0000043E E89806 <1> call pointer_to_linear 838 <1> 839 <1> %if _ALLOW_OVERLAPPING 840 00000441 034EE0 <1> add cx, word [bp + ?length_of_source] 841 00000444 135EE2 <1> adc bx, word [bp + ?length_of_source + 2] 842 <1> ; In case of allowing overlapping source and destination, 843 <1> ; the ?length_of_destination variable is set to 844 <1> ; ?src + ?length_of_source - ?dst, allowing to write to 845 <1> ; all of the source buffer (with the checks already in place 846 <1> ; from the default handling). Additional checks are done by 847 <1> ; calling check_pointers_not_overlapping. This is done after 848 <1> ; every change of ?dst to verify that the write pointer stays 849 <1> ; below-or-equal the read pointer. 850 <1> ; This means the remaining source data may be corrupted by a 851 <1> ; write, but nothing after the source data is written to, 852 <1> ; so the error handling (in INIT1 after the data) still works. 853 <1> %endif 854 <1> 855 00000447 29C1 <1> sub cx, ax 856 00000449 19D3 <1> sbb bx, dx ; bx:cx = source linear - destination linear 857 <1> 858 0000044B 81E96039 <1> sub cx, localvariables_size & 0FFFFh 859 0000044F 83DB00 <1> sbb bx, localvariables_size >> 16 860 00000452 7303E99B04 <1> jb .error ; make variables buffer available 861 00000457 7507 <1> jne @F 862 00000459 85C9 <1> test cx, cx 863 0000045B 7503E99204 <1> jz .error 864 <1> @@: 865 <1> %endif ; _SCAN 866 <1> 867 <1> %if _SCAN 868 <1> cmp word [bp + ?bufferparas], paras(localvariables_size) 869 <1> jb .error 870 <1> %endif 871 <1> 872 <1> lvar dword, length_of_destination 873 00000460 53 <1> push bx ; push into [bp + ?length_of_destination + 2] 874 00000461 51 <1> push cx ; push into [bp + ?length_of_destination] 875 <1> 876 <1> %if _SCAN 877 <1> xor di, di 878 <1> mov es, di ; destination = all-zeroes (special) 879 <1> %else 880 00000462 06 <1> push es 881 00000463 57 <1> push di 882 <1> %if localvariables_size >> 16 883 <1> mov bx, localvariables_size >> 16 884 <1> %else 885 00000464 31DB <1> xor bx, bx 886 <1> %endif 887 00000466 B96039 <1> mov cx, localvariables_size & 0FFFFh 888 00000469 E83E06 <1> call normalise_pointer_with_displacement_bxcx 889 0000046C 5F <1> pop di 890 0000046D 07 <1> pop es 891 <1> %endif ; _SCAN 892 <1> 893 <1> lvar dword, original_dst 894 0000046E 06 <1> push es 895 0000046F 57 <1> push di 896 <1> lvar dword, dst 897 00000470 06 <1> push es 898 00000471 57 <1> push di 899 <1> 900 <1> %if _ALLOW_OVERLAPPING 901 00000472 E8E805 <1> call check_pointers_not_overlapping 902 <1> ; Note: We initially check here that the write pointer is 903 <1> ; low enough, ie below-or-equal the read pointer. 904 <1> ; Unlike the other decompressors, this check is done 905 <1> ; after any copied match or literal too, because 906 <1> ; literals can presumably be encoded with less than 907 <1> ; one byte of source data to the range decoder. 908 <1> d0 mov byte [bp + ?errordata], 1Bh 909 <1> .error_CY_a1: 910 00000475 7243 <1> jc short .error_CY_a 911 <1> %else 912 <1> .error_CY_a1 equ .error_CY_a 913 <1> %endif 914 <1> 915 <1> 916 <1> member_min_size equ lzip_header_size + lzip_trailer_size 917 <1> 918 <1> .loop_member: 919 00000477 837EE200 <1> cmp word [bp + ?length_of_source + 2], 0 920 0000047B 7504 <1> jne @F 921 0000047D 837EE01A <1> cmp word [bp + ?length_of_source], member_min_size 922 <1> @@: 923 00000481 770F <1> ja .got_member 924 <1> 925 00000483 837EE200 <1> cmp word [bp + ?length_of_source + 2], 0 926 00000487 7504 <1> jne @F 927 00000489 837EE00F <1> cmp word [bp + ?length_of_source], 15 928 <1> @@: 929 0000048D 7710 <1> ja short .error_NZ_a ; (NZ if jumping) 930 0000048F E92C04 <1> jmp .end 931 <1> 932 <1> .got_member: 933 00000492 C576E8 <1> lds si, [bp + ?src] ; ds:si -> lzip_header.magic, .version 934 00000495 0E <1> push cs 935 00000496 07 <1> pop es 936 00000497 BF[1C04] <1> mov di, lzip_header_bytes 937 0000049A B90500 <1> mov cx, lzip_header_bytes.length 938 0000049D F3A6 <1> repe cmpsb 939 <1> .error_NZ_a: 940 0000049F 7403E94E04 <1> jne .error 941 <1> %if _COUNTER && !_PROGRESS 942 <1> mov al, '#' 943 <1> call disp_al 944 <1> %endif 945 000004A4 31C0 <1> xor ax, ax 946 000004A6 AC <1> lodsb ; ax = lzip_header.coded_dict_size 947 <1> 948 000004A7 1E <1> push ds 949 000004A8 56 <1> push si 950 000004A9 E8DC05 <1> call normalise_pointer 951 000004AC 8F46E8 <1> pop word [bp + ?src] 952 000004AF 8F46EA <1> pop word [bp + ?src + 2] 953 000004B2 836EE006 <1> sub word [bp + ?length_of_source], 6 954 000004B6 835EE200 <1> sbb word [bp + ?length_of_source + 2], 0 955 <1> .error_CY_a: 956 000004BA 7233 <1> jc short .error_CY_b 957 <1> 958 000004BC 50 <1> push ax 959 000004BD 241F <1> and al, 1Fh 960 000004BF 91 <1> xchg cx, ax ; cx = coded dict size & 1Fh, clobber ax 961 000004C0 B80100 <1> mov ax, 1 962 000004C3 31D2 <1> xor dx, dx 963 <1> @@: 964 000004C5 D1E0 <1> shl ax, 1 965 000004C7 D1D2 <1> rcl dx, 1 966 000004C9 E2FA <1> loop @B 967 <1> 968 000004CB 89D3 <1> mov bx, dx 969 000004CD 89C7 <1> mov di, ax ; bx:di = dict_size 970 000004CF B104 <1> mov cl, 4 971 <1> @@: 972 000004D1 D1EB <1> shr bx, 1 973 000004D3 D1DF <1> rcr di, 1 974 000004D5 E2FA <1> loop @B ; bx:di = dict_size / 16 975 000004D7 59 <1> pop cx 976 000004D8 88CD <1> mov ch, cl 977 000004DA B105 <1> mov cl, 5 978 000004DC D2ED <1> shr ch, cl 979 000004DE 88E9 <1> mov cl, ch 980 000004E0 B500 <1> mov ch, 0 981 <1> 982 000004E2 52 <1> push dx 983 000004E3 50 <1> push ax 984 <1> 985 000004E4 89F8 <1> mov ax, di ; ax = low word of input 986 000004E6 F7E1 <1> mul cx 987 000004E8 93 <1> xchg ax, bx ; ax = high word of input 988 000004E9 89D7 <1> mov di, dx ; di:bx = low word + first high word 989 000004EB F7E1 <1> mul cx ; = high word 990 000004ED 01C7 <1> add di, ax ; add into sum 991 <1> .error_CY_b: 992 000004EF 7217 <1> jc short .error_CY_c 993 000004F1 85D2 <1> test dx, dx ; overflows ? 994 000004F3 7403E9FA03 <1> jnz .error 995 <1> ; bx:di = dict_size / 16 * fraction 996 000004F8 58 <1> pop ax 997 000004F9 5A <1> pop dx 998 000004FA 29D8 <1> sub ax, bx 999 000004FC 19FA <1> sbb dx, di 1000 000004FE 7208 <1> jc short .error_CY_c 1001 <1> 1002 00000500 83FA00 <1> cmp dx, min_dictionary_size >> 16 1003 00000503 7503 <1> jne @F 1004 00000505 3D0010 <1> cmp ax, min_dictionary_size & 0FFFFh 1005 <1> @@: 1006 <1> .error_CY_c: 1007 00000508 7273 <1> jb short .error_CY_d 1008 <1> 1009 0000050A 81FA0020 <1> cmp dx, max_dictionary_size >> 16 1010 0000050E 7503 <1> jne @F 1011 00000510 83F800 <1> cmp ax, max_dictionary_size & 0FFFFh 1012 <1> @@: 1013 00000513 7603E9DA03 <1> ja .error 1014 <1> 1015 00000518 C55EE4 <1> lds bx, [bp + ?final_dst] 1016 0000051B FF76D6 <1> push word [bp + ?dst + 2] 1017 0000051E FF76D4 <1> push word [bp + ?dst] 1018 00000521 8F472C <1> pop word [bx + destinationbuffer_constant] 1019 00000524 8F472E <1> pop word [bx + destinationbuffer_constant + 2] 1020 <1> 1021 <1> 1022 <1> ; decode_member start (inlined) 1023 <1> ; INP: ?localvariables = ds:bx -> localvariables structure, 1024 <1> ; destinationbuffer_constant pre-initialised 1025 <1> ; dx:ax = dictionary size 1026 <1> ; Following variables of depack frame initialised: 1027 <1> ; dword [ss:bp + ?src] -> source buffer 1028 <1> ; dword [ss:bp + ?length_of_source] = remaining length 1029 <1> ; dword [ss:bp + ?dst] -> destination buffer 1030 <1> ; dword [ss:bp + ?length_of_destination] = remaining 1031 <1> ; OUT: NC if success 1032 <1> ; CY if error 1033 <1> ; CHG: all 1034 <1> ; LZ_decoder.decode_member: 1035 <1> 1036 00000527 52 <1> push dx 1037 00000528 50 <1> push ax ; preserve dictionary size 1038 00000529 1E <1> push ds 1039 0000052A 07 <1> pop es 1040 0000052B 89DF <1> mov di, bx 1041 0000052D B90C00 <1> mov cx, fromdwords(dwords(lz_decoder_size)) / 2 1042 00000530 31C0 <1> xor ax, ax 1043 00000532 F3AB <1> rep stosw ; initialise lz_decoder structure 1044 <1> 1045 00000534 E8E4FC <1> call Range_decoder.init ; initialise embedded range_decoder 1046 <1> 1047 00000537 8F4710 <1> pop word [bx + lz_decoder.dictionary_size] 1048 0000053A 8F4712 <1> pop word [bx + lz_decoder.dictionary_size + 2] 1049 <1> ; set dictionary size 1050 <1> 1051 0000053D 8D7F30 <1> lea di, [bx + bit_models_start] 1052 00000540 B9971C <1> mov cx, (bit_models_end - bit_models_start) / bit_model_size 1053 00000543 B80004 <1> mov ax, bit_model_total / 2 ; initial value for bit_model 1054 <1> %if bit_model_size != 2 1055 <1> %error Assuming word size for bit_model_size 1056 <1> %endif 1057 00000546 F3AB <1> rep stosw ; initialise this bit_model 1058 <1> ; loop for all bit_model and len_model 1059 <1> 1060 00000548 8D7F18 <1> lea di, [bx + zeros_start] 1061 0000054B 31C0 <1> xor ax, ax 1062 0000054D B10A <1> mov cl, (zeros_end - zeros_start) / 2 1063 0000054F F3AB <1> rep stosw 1064 <1> 1065 <1> .loop: 1066 <1> %if _SCAN 1067 <1> add word [bp + ?progressticks], 1 1068 <1> adc word [bp + ?progressticks + 2], 0 1069 <1> %endif 1070 <1> %if _COUNTER 1071 00000551 FE46FC <1> inc byte [bp + ?counter] 1072 00000554 F646FCFF <1> test byte [bp + ?counter], _COUNTER - 1 1073 00000558 7505 <1> jnz @F 1074 0000055A B02E <1> mov al, '.' 1075 0000055C E8DDFA <1> call disp_al_counter 1076 <1> @@: 1077 <1> %endif 1078 0000055F 8B5EE4 <1> mov bx, word [bp + ?localvariables] 1079 00000562 8B4714 <1> mov ax, word [bx + lz_decoder.pos] 1080 00000565 83E003 <1> and ax, pos_state_mask 1081 00000568 91 <1> xchg cx, ax ; cx = pos_state, ax clobbered 1082 00000569 894EEC <1> mov word [bp + ?pos_state], cx 1083 <1> 1084 0000056C 1E <1> push ds 1085 0000056D 07 <1> pop es 1086 0000056E 8D7F30 <1> lea di, [bx + bm_match] ; es:di -> bm_match 2D array 1087 00000571 B80800 <1> mov ax, bit_model_size * pos_states 1088 00000574 F76728 <1> mul word [bx + state.st] ; dx:ax = first index is state 1089 <1> ; bit_model_size = 2 1090 <1> ; pos_states = 4 1091 <1> ; state.st < 12 1092 <1> ; multiplication 2 * 4 * 11 = 88 1093 <1> %if bit_model_size != 2 1094 <1> %error Assuming word size for bit_model_size 1095 <1> %endif 1096 00000577 01C9 <1> add cx, cx ; = second index (from pos_state) 1097 <1> ; pos_state < 4 1098 <1> ; cx < 8 1099 <1> ; ax <= 88 1100 00000579 01C8 <1> add ax, cx ; = second index is pos_state 1101 0000057B 01C7 <1> add di, ax ; es:di -> bm_match[state()][pos_state] 1102 <1> .error_CY_d: 1103 0000057D 7222 <1> jc short .error_CY_1 1104 0000057F E80DFD <1> call Range_decoder.decode_bit 1105 00000582 7244 <1> jc .1st_bit_not_zero 1106 <1> 1107 <1> .1st_bit_zero: ; literal byte 1108 00000584 31C0 <1> xor ax, ax 1109 00000586 31D2 <1> xor dx, dx 1110 00000588 E854FE <1> call LZ_decoder.peek ; al = prev_byte 1111 <1> 1112 0000058B B105 <1> mov cl, 8 - literal_context_bits 1113 0000058D D2E8 <1> shr al, cl ; = literal_state 1114 0000058F 1E <1> push ds 1115 00000590 07 <1> pop es 1116 00000591 8DBFF000 <1> lea di, [bx + bm_literal] ; -> 2D array bm_literal 1117 00000595 B90006 <1> mov cx, bit_model_size * 300h 1118 00000598 F7E1 <1> mul cx ; first index is literal_state 1119 0000059A 85D2 <1> test dx, dx 1120 0000059C F9 <1> stc 1121 0000059D 7502 <1> jnz short .error_CY_1 1122 0000059F 01C7 <1> add di, ax ; es:di -> bm_literal[literal_state] 1123 <1> .error_CY_1: 1124 000005A1 7232 <1> jc short .error_CY_2 1125 <1> 1126 000005A3 E853FC <1> call State.is_char 1127 000005A6 7308 <1> jnc .not_is_char 1128 <1> .is_char: 1129 000005A8 B90800 <1> mov cx, 8 1130 000005AB E846FD <1> call Range_decoder.decode_tree 1131 000005AE EB10 <1> jmp @F 1132 <1> 1133 <1> .not_is_char: 1134 000005B0 8B4718 <1> mov ax, word [bx + rep0] 1135 000005B3 8B571A <1> mov dx, word [bx + rep0 + 2] 1136 000005B6 06 <1> push es 1137 000005B7 57 <1> push di 1138 000005B8 E824FE <1> call LZ_decoder.peek 1139 000005BB 5F <1> pop di 1140 000005BC 07 <1> pop es 1141 000005BD E873FD <1> call Range_decoder.decode_matched 1142 <1> @@: 1143 000005C0 E86703 <1> call LZ_decoder.put_byte 1144 000005C3 E838FC <1> call State.set_char 1145 000005C6 EB89 <1> jmp .loop 1146 <1> 1147 <1> 1148 <1> .1st_bit_not_zero: ; match or repeated match 1149 000005C8 1E <1> push ds 1150 000005C9 07 <1> pop es 1151 000005CA 8DBF9000 <1> lea di, [bx + bm_rep] ; es:di -> bm_rep array 1152 <1> %if bit_model_size != 2 1153 <1> %error Assuming word size for bit_model_size 1154 <1> %endif 1155 000005CE 8B4728 <1> mov ax, word [bx + state.st] 1156 000005D1 01C0 <1> add ax, ax ; ax = index is state 1157 <1> ; jc short .error_CY_2 ; (state.st is always < 12) 1158 000005D3 01C7 <1> add di, ax ; es:di -> bm_rep[state()] 1159 <1> .error_CY_2: 1160 000005D5 7230 <1> jc short .error_CY_3 1161 000005D7 E8B5FC <1> call Range_decoder.decode_bit 1162 000005DA 7203E9EA00 <1> jnc .2nd_bit_zero 1163 <1> 1164 <1> .2nd_bit_not_zero: 1165 000005DF 1E <1> push ds 1166 000005E0 07 <1> pop es 1167 000005E1 8DBFA800 <1> lea di, [bx + bm_rep0] ; es:di -> bm_rep0 array 1168 <1> %if bit_model_size != 2 1169 <1> %error Assuming word size for bit_model_size 1170 <1> %endif 1171 000005E5 8B4728 <1> mov ax, word [bx + state.st] 1172 000005E8 01C0 <1> add ax, ax ; ax = index is state 1173 <1> ; jc short .error_CY_3 ; (state.st is always < 12) 1174 000005EA 01C7 <1> add di, ax ; es:di -> bm_rep0[state()] 1175 000005EC 7219 <1> jc short .error_CY_3 1176 000005EE E89EFC <1> call Range_decoder.decode_bit 1177 000005F1 7233 <1> jc .3rd_bit_not_zero 1178 <1> 1179 <1> .3rd_bit_zero: 1180 000005F3 1E <1> push ds 1181 000005F4 07 <1> pop es 1182 000005F5 8DBFF030 <1> lea di, [bx + bm_len] ; es:di -> bm_len 2D array 1183 000005F9 B80800 <1> mov ax, bit_model_size * pos_states 1184 <1> ; (2 * 4 = 8) 1185 000005FC F76728 <1> mul word [bx + state.st]; (< 12) 1186 <1> ; dx:ax = first index is state 1187 <1> ; test dx, dx 1188 <1> ; stc 1189 <1> ; jnz short .error_CY_3 ; (dx:ax is always < 12 * 8) 1190 <1> %if bit_model_size != 2 1191 <1> %error Assuming word size for bit_model_size 1192 <1> %endif 1193 <1> %rep bit_model_size 1194 <1> add ax, word [bp + ?pos_state] 1195 <1> ; jc short .error_CY_3 ; (pos_state is always < 4 1196 <1> ; and state_st is always < 12 1197 <1> ; and ax is < 12 * 8 prior to adding) 1198 <1> %endrep 1194 000005FF 0346EC <2> add ax, word [bp + ?pos_state] 1195 <2> 1196 <2> 1197 <2> 1194 00000602 0346EC <2> add ax, word [bp + ?pos_state] 1195 <2> 1196 <2> 1197 <2> 1199 00000605 01C7 <1> add di, ax ; es:di -> bm_len[state()] 1200 <1> .error_CY_3: 1201 00000607 722A <1> jc short .error_CY_4 1202 00000609 E883FC <1> call Range_decoder.decode_bit 1203 0000060C 7303E99500 <1> jc .4th_bit_not_zero 1204 <1> 1205 <1> .4th_bit_zero: 1206 <1> ; State.set_short_rep 1207 00000611 B8090B <1> mov ax, 9 | (11 << 8) 1208 00000614 E8FBFB <1> call State.select 1209 <1> 1210 00000617 8B4718 <1> mov ax, word [bx + rep0] 1211 0000061A 8B571A <1> mov dx, word [bx + rep0 + 2] 1212 0000061D E8BFFD <1> call LZ_decoder.peek 1213 00000620 E80703 <1> call LZ_decoder.put_byte 1214 00000623 E92BFF <1> jmp .loop 1215 <1> 1216 <1> .3rd_bit_not_zero: 1217 00000626 1E <1> push ds 1218 00000627 07 <1> pop es 1219 00000628 8DBFC000 <1> lea di, [bx + bm_rep1] ; es:di -> bm_rep1 array 1220 <1> %if bit_model_size != 2 1221 <1> %error Assuming word size for bit_model_size 1222 <1> %endif 1223 0000062C 8B4728 <1> mov ax, word [bx + state.st] 1224 0000062F 01C0 <1> add ax, ax ; ax = index is state 1225 <1> ; jc short .error_CY_4 ; (state.st is always < 12) 1226 00000631 01C7 <1> add di, ax ; es:di -> bm_rep1[state()] 1227 <1> .error_CY_4: 1228 00000633 7220 <1> jc short .error_CY_4a 1229 00000635 E857FC <1> call Range_decoder.decode_bit 1230 00000638 720E <1> jc .3rd_bit_not_zero.4th_bit_not_zero 1231 <1> 1232 <1> .3rd_bit_not_zero.4th_bit_zero: 1233 0000063A FF771E <1> push word [bx + rep1 + 2] 1234 0000063D FF771C <1> push word [bx + rep1] 1235 00000640 8F46F8 <1> pop word [bp + ?distance] 1236 00000643 8F46FA <1> pop word [bp + ?distance + 2] 1237 00000646 EB46 <1> jmp .3rd_bit_not_zero.common 1238 <1> 1239 <1> .3rd_bit_not_zero.4th_bit_not_zero: 1240 00000648 1E <1> push ds 1241 00000649 07 <1> pop es 1242 0000064A 8DBFD800 <1> lea di, [bx + bm_rep2] ; es:di -> bm_rep2 array 1243 <1> %if bit_model_size != 2 1244 <1> %error Assuming word size for bit_model_size 1245 <1> %endif 1246 0000064E 8B4728 <1> mov ax, word [bx + state.st] 1247 00000651 01C0 <1> add ax, ax ; ax = index is state 1248 <1> ; jc short .error_CY_5 ; (state.st is always < 12) 1249 00000653 01C7 <1> add di, ax ; es:di -> bm_rep2[state()] 1250 <1> .error_CY_4a: 1251 00000655 7267 <1> jc short .error_CY_5 1252 00000657 E835FC <1> call Range_decoder.decode_bit 1253 0000065A 720E <1> jc .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero 1254 <1> 1255 <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_zero: 1256 0000065C FF7722 <1> push word [bx + rep2 + 2] 1257 0000065F FF7720 <1> push word [bx + rep2] 1258 00000662 8F46F8 <1> pop word [bp + ?distance] 1259 00000665 8F46FA <1> pop word [bp + ?distance + 2] 1260 00000668 EB18 <1> jmp .3rd_bit_not_zero.4th_bit_not_zero.common 1261 <1> 1262 <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero: 1263 0000066A FF7726 <1> push word [bx + rep3 + 2] 1264 0000066D FF7724 <1> push word [bx + rep3] 1265 00000670 8F46F8 <1> pop word [bp + ?distance] 1266 00000673 8F46FA <1> pop word [bp + ?distance + 2] ; distance = rep3 1267 00000676 FF7722 <1> push word [bx + rep2 + 2] 1268 00000679 FF7720 <1> push word [bx + rep2] 1269 0000067C 8F4724 <1> pop word [bx + rep3] 1270 0000067F 8F4726 <1> pop word [bx + rep3 + 2] ; rep3 = rep2 1271 <1> 1272 <1> .3rd_bit_not_zero.4th_bit_not_zero.common: 1273 00000682 FF771E <1> push word [bx + rep1 + 2] 1274 00000685 FF771C <1> push word [bx + rep1] 1275 00000688 8F4720 <1> pop word [bx + rep2] 1276 0000068B 8F4722 <1> pop word [bx + rep2 + 2] ; rep2 = rep1 1277 <1> 1278 <1> .3rd_bit_not_zero.common: 1279 0000068E FF771A <1> push word [bx + rep0 + 2] 1280 00000691 FF7718 <1> push word [bx + rep0] 1281 00000694 8F471C <1> pop word [bx + rep1] 1282 00000697 8F471E <1> pop word [bx + rep1 + 2] ; rep1 = rep0 1283 0000069A FF76FA <1> push word [bp + ?distance + 2] 1284 0000069D FF76F8 <1> push word [bp + ?distance] 1285 000006A0 8F4718 <1> pop word [bx + rep0] 1286 000006A3 8F471A <1> pop word [bx + rep0 + 2] ; rep0 = distance 1287 <1> 1288 <1> .4th_bit_not_zero: 1289 <1> ; State.set_rep 1290 000006A6 B8080B <1> mov ax, 8 | (11 << 8) 1291 000006A9 E866FB <1> call State.select 1292 <1> 1293 000006AC 8B46EC <1> mov ax, word [bp + ?pos_state] ; ax = pos_state variable 1294 000006AF 1E <1> push ds 1295 000006B0 07 <1> pop es 1296 000006B1 8DBFDA36 <1> lea di, [bx + rep_len_model] ; -> len_model to use 1297 000006B5 E8C6FC <1> call Range_decoder.decode_len ; dx:ax = length 1298 000006B8 83C002 <1> add ax, min_match_len 1299 000006BB 83D200 <1> adc dx, 0 1300 <1> .error_CY_5: 1301 000006BE 7250 <1> jc short .error_CY_6 1302 000006C0 8946F4 <1> mov word [bp + ?len], ax 1303 000006C3 8956F6 <1> mov word [bp + ?len + 2], dx 1304 000006C6 E93001 <1> jmp .handle_match 1305 <1> 1306 <1> .2nd_bit_zero: ; match 1307 000006C9 FF7722 <1> push word [bx + rep2 + 2] 1308 000006CC FF7720 <1> push word [bx + rep2] 1309 000006CF 8F4724 <1> pop word [bx + rep3] 1310 000006D2 8F4726 <1> pop word [bx + rep3 + 2] ; rep3 = rep2 1311 <1> 1312 000006D5 FF771E <1> push word [bx + rep1 + 2] 1313 000006D8 FF771C <1> push word [bx + rep1] 1314 000006DB 8F4720 <1> pop word [bx + rep2] 1315 000006DE 8F4722 <1> pop word [bx + rep2 + 2] ; rep2 = rep1 1316 <1> 1317 000006E1 FF771A <1> push word [bx + rep0 + 2] 1318 000006E4 FF7718 <1> push word [bx + rep0] 1319 000006E7 8F471C <1> pop word [bx + rep1] 1320 000006EA 8F471E <1> pop word [bx + rep1 + 2] ; rep1 = rep0 1321 <1> 1322 000006ED 8B46EC <1> mov ax, word [bp + ?pos_state] ; ax = pos_state variable 1323 000006F0 1E <1> push ds 1324 000006F1 07 <1> pop es 1325 000006F2 8DBF5634 <1> lea di, [bx + match_len_model] ; -> len_model to use 1326 000006F6 E885FC <1> call Range_decoder.decode_len ; dx:ax = length 1327 <1> 1328 000006F9 8946EE <1> mov word [bp + ?len_state], ax 1329 000006FC 85D2 <1> test dx, dx 1330 000006FE 7505 <1> jnz @F 1331 00000700 83F803 <1> cmp ax, len_states - 1 1332 00000703 7205 <1> jb @FF 1333 <1> @@: 1334 00000705 C746EE0300 <1> mov word [bp + ?len_state], len_states - 1 1335 <1> @@: 1336 <1> 1337 0000070A 83C002 <1> add ax, min_match_len 1338 0000070D 83D200 <1> adc dx, 0 1339 <1> .error_CY_6: 1340 00000710 723C <1> jc short .error_CY_7 1341 <1> 1342 00000712 8946F4 <1> mov word [bp + ?len], ax 1343 00000715 8956F6 <1> mov word [bp + ?len + 2], dx 1344 <1> 1345 00000718 1E <1> push ds 1346 00000719 07 <1> pop es 1347 0000071A 8DBF5031 <1> lea di, [bx + bm_dis_slot] ; -> 2D array bm_dis_slot 1348 <1> 1349 0000071E B88000 <1> mov ax, bit_model_size * (1 << dis_slot_bits) 1350 00000721 F766EE <1> mul word [bp + ?len_state] ; first index is len_state 1351 <1> ; bit_model_size = 2 1352 <1> ; 1 << dis_slot_bits = 1 << 6 = 64 1353 <1> ; ?len_state < 4 1354 <1> ; multiplication 2 * 64 * 3 = 384 1355 <1> ; dx:ax = first index into array 1356 00000724 01C7 <1> add di, ax ; -> 1D array at bm_dis_slot[len_state] 1357 00000726 B90600 <1> mov cx, dis_slot_bits 1358 00000729 E8C8FB <1> call Range_decoder.decode_tree 1359 0000072C 894718 <1> mov word [bx + rep0], ax 1360 0000072F 89571A <1> mov word [bx + rep0 + 2], dx 1361 <1> 1362 00000732 85D2 <1> test dx, dx ; (same flags as cmp dx, 0) 1363 00000734 7503 <1> jne @F 1364 00000736 83F804 <1> cmp ax, start_dis_model 1365 <1> @@: 1366 00000739 7303E99B00 <1> jnae .not_rep0_ae_start_dis_model 1367 <1> 1368 <1> .rep0_ae_start_dis_model: 1369 0000073E 8946F0 <1> mov word [bp + ?dis_slot], ax 1370 00000741 8956F2 <1> mov word [bp + ?dis_slot + 2], dx 1371 <1> 1372 00000744 D1EA <1> shr dx, 1 1373 00000746 D1D8 <1> rcr ax, 1 ; dis_slot >> 1 1374 00000748 83E801 <1> sub ax, 1 1375 0000074B 83DA00 <1> sbb dx, 0 ; - 1 1376 <1> .error_CY_7: 1377 <1> .error_CY_8: 1378 0000074E 7230 <1> jc short .error_CY_9 1379 00000750 F9 <1> stc 1380 00000751 752D <1> jnz short .error_CY_9 1381 00000753 91 <1> xchg cx, ax ; cx = direct_bits, clobber ax 1382 00000754 31D2 <1> xor dx, dx 1383 00000756 B80100 <1> mov ax, 1 1384 00000759 2246F0 <1> and al, byte [bp + ?dis_slot] 1385 0000075C 0C02 <1> or al, 2 1386 0000075E 51 <1> push cx 1387 0000075F E306 <1> jcxz @FF 1388 <1> @@: 1389 00000761 D1E0 <1> shl ax, 1 1390 00000763 D1D2 <1> rcl dx, 1 1391 00000765 E2FA <1> loop @B 1392 <1> @@: 1393 00000767 59 <1> pop cx 1394 00000768 894718 <1> mov word [bx + rep0], ax 1395 0000076B 89571A <1> mov word [bx + rep0 + 2], dx 1396 <1> 1397 0000076E 837EF200 <1> cmp word [bp + ?dis_slot + 2], 0 1398 00000772 7504 <1> jne @F 1399 00000774 837EF00E <1> cmp word [bp + ?dis_slot], end_dis_model 1400 <1> @@: 1401 00000778 7328 <1> jnb .not_dis_slot_below_end_dis_model 1402 <1> 1403 <1> .dis_slot_below_end_dis_model: 1404 0000077A 2B46F0 <1> sub ax, word [bp + ?dis_slot] 1405 0000077D 1B56F2 <1> sbb dx, word [bp + ?dis_slot + 2] 1406 <1> ; dx:ax = index into bm_dis array 1407 <1> ; = rep0 - dis_slot 1408 <1> .error_CY_9: 1409 00000780 722D <1> jc short .error_CY_10 1410 <1> 1411 <1> %if bit_model_size != 2 1412 <1> %error Assuming word size for bit_model_size 1413 <1> %endif 1414 00000782 01C0 <1> add ax, ax 1415 00000784 11D2 <1> adc dx, dx ; dx:ax *= 2 1416 00000786 7227 <1> jc short .error_CY_10 1417 00000788 F9 <1> stc 1418 00000789 7524 <1> jnz short .error_CY_10 ; if dx != 0 --> 1419 0000078B 1E <1> push ds 1420 0000078C 07 <1> pop es 1421 0000078D 8DBF5033 <1> lea di, [bx + bm_dis] ; es:di -> bm_dis array 1422 00000791 01C7 <1> add di, ax ; index into the array 1423 00000793 721A <1> jc short .error_CY_10 1424 00000795 E888FB <1> call Range_decoder.decode_tree_reversed 1425 00000798 014718 <1> add word [bx + rep0], ax 1426 0000079B 11571A <1> adc word [bx + rep0 + 2], dx 1427 0000079E 720F <1> jc short .error_CY_10 1428 000007A0 EB37 <1> jmp .after_dis_slot_below 1429 <1> 1430 <1> .not_dis_slot_below_end_dis_model: 1431 000007A2 83E904 <1> sub cx, dis_align_bits 1432 000007A5 E8B4FA <1> call Range_decoder.decode 1433 000007A8 B90400 <1> mov cx, dis_align_bits 1434 <1> @@: 1435 000007AB D1E0 <1> shl ax, 1 1436 000007AD D1D2 <1> rcl dx, 1 1437 <1> .error_CY_10: 1438 000007AF 721A <1> jc short .error_CY_11 1439 000007B1 E2F8 <1> loop @B 1440 000007B3 014718 <1> add word [bx + rep0], ax 1441 000007B6 11571A <1> adc word [bx + rep0 + 2], dx 1442 <1> 1443 000007B9 B90400 <1> mov cx, dis_align_bits 1444 000007BC 1E <1> push ds 1445 000007BD 07 <1> pop es 1446 000007BE 8DBF3634 <1> lea di, [bx + bm_align] 1447 000007C2 E85BFB <1> call Range_decoder.decode_tree_reversed 1448 000007C5 014718 <1> add word [bx + rep0], ax 1449 000007C8 11571A <1> adc word [bx + rep0 + 2], dx 1450 <1> .error_CY_11: 1451 000007CB 727D <1> jc .error_CY_12 1452 <1> 1453 000007CD 837F1AFF <1> cmp word [bx + rep0 + 2], -1 ; rep0 = 0FFFF_FFFFh ? 1454 000007D1 7504 <1> jne @F 1455 000007D3 837F18FF <1> cmp word [bx + rep0], -1 1456 <1> @@: 1457 000007D7 7479 <1> je .end_member ; yes, end (marker found) --> 1458 <1> 1459 <1> .after_dis_slot_below: 1460 <1> 1461 <1> .not_rep0_ae_start_dis_model: 1462 <1> 1463 <1> ; State.set_match 1464 000007D9 B8070A <1> mov ax, 7 | (10 << 8) 1465 000007DC E833FA <1> call State.select 1466 <1> 1467 000007DF 8B571A <1> mov dx, word [bx + rep0 + 2] 1468 000007E2 8B4718 <1> mov ax, word [bx + rep0] 1469 <1> 1470 000007E5 3B5712 <1> cmp dx, word [bx + lz_decoder.dictionary_size + 2] 1471 000007E8 7503 <1> jne @F 1472 000007EA 3B4710 <1> cmp ax, word [bx + lz_decoder.dictionary_size] 1473 <1> @@: 1474 000007ED 7308 <1> jae short .error_AE_1 1475 <1> 1476 <1> ; check for (rep0 >= pos && !pos_wrapped) 1477 <1> ; (pos_wrapped is always false for us) 1478 000007EF 3B5716 <1> cmp dx, word [bx + lz_decoder.pos + 2] 1479 000007F2 7503 <1> jne @F 1480 000007F4 3B4714 <1> cmp ax, word [bx + lz_decoder.pos] 1481 <1> @@: 1482 <1> .error_AE_1: 1483 000007F7 7356 <1> jae short .error_1 1484 <1> 1485 <1> .handle_match: 1486 000007F9 8B571A <1> mov dx, word [bx + rep0 + 2] 1487 000007FC 8B4718 <1> mov ax, word [bx + rep0] 1488 <1> 1489 000007FF E8F4FB <1> call calculate_peek_pointer_disi 1490 <1> 1491 00000802 8B46F4 <1> mov ax, word [bp + ?len] 1492 00000805 8B56F6 <1> mov dx, word [bp + ?len + 2] ; dx:ax = length 1493 <1> 1494 <1> 1495 <1> ; INP: dx:ax = length of match 1496 <1> ; di:si -> source (normalised) 1497 <1> ; ds:bx -> local variables structure 1498 <1> ; ss:bp -> depack stack frame, 1499 <1> ; with ?length_of_destination, ?dst 1500 <1> ; OUT: NC if success, 1501 <1> ; ?length_of_destination and ?dst updated 1502 <1> ; CY if error 1503 <1> ; (destination buffer too small or overlap error) 1504 <1> ; ! may jump to depack.end if ?dst_max_segment reached 1505 <1> ; CHG: ax, cx, dx, di, si, es 1506 <1> ; handle_match: 1507 00000808 014714 <1> add word [bx + lz_decoder.pos], ax 1508 0000080B 115716 <1> adc word [bx + lz_decoder.pos + 2], dx 1509 0000080E 723A <1> jc short .error_CY_12 ; (CY) --> 1510 <1> 1511 00000810 2946DC <1> sub word [bp + ?length_of_destination], ax 1512 00000813 1956DE <1> sbb word [bp + ?length_of_destination + 2], dx 1513 <1> ; enough space left ? 1514 00000816 7232 <1> jb short .error_CY_12 ; no --> (below == CY) 1515 <1> 1516 00000818 1E <1> push ds 1517 <1> 1518 00000819 8EDF <1> mov ds, di ; ds:si -> source 1519 0000081B C47ED4 <1> les di, [bp + ?dst] ; es:di -> destination 1520 <1> .hm_loop: 1521 0000081E B9F0FF <1> mov cx, 64 * 1024 - 16 ; block size 1522 <1> ; If both pointers are normalised, moving 0FFF0h bytes is 1523 <1> ; valid and results in a maximum offset of 0FFFFh in either. 1524 <1> 1525 00000821 85D2 <1> test dx, dx ; >= 1_0000h ? 1526 00000823 7508 <1> jnz @F ; yes, full block --> 1527 00000825 85C0 <1> test ax, ax ; == 0 ? 1528 00000827 7415 <1> jz .hm_end ; yes, done --> 1529 00000829 39C8 <1> cmp ax, cx ; can move in one (last) block ? 1530 0000082B 7607 <1> jbe .hm_last ; yes --> 1531 <1> @@: 1532 <1> ; no, move one block and continue 1533 0000082D 29C8 <1> sub ax, cx 1534 0000082F 83DA00 <1> sbb dx, 0 ; left over remaining 1535 00000832 EB03 <1> jmp .hm_copy 1536 <1> 1537 <1> .hm_last: 1538 00000834 91 <1> xchg cx, ax ; cx = remaining length 1539 00000835 31C0 <1> xor ax, ax ; no more remaining 1540 <1> 1541 <1> .hm_copy: 1542 <1> %if _SCAN 1543 <1> call scan_rep_movsb 1544 <1> %else 1545 00000837 F3A4 <1> rep movsb ; move one block (full or partial) 1546 <1> %endif 1547 <1> 1548 00000839 E83D02 <1> call normalise_both_pointers 1549 0000083C EBE0 <1> jmp .hm_loop 1550 <1> 1551 <1> .hm_end: 1552 0000083E 897ED4 <1> mov word [bp + ?dst], di 1553 00000841 8C46D6 <1> mov word [bp + ?dst + 2], es 1554 <1> %if _PAYLOAD_KERNEL_MAX_PARAS 1555 <1> mov ax, es 1556 <1> cmp ax, word [bp + ?dst_max_segment] 1557 <1> jae depack.end 1558 <1> ; note that we have the depack stack frame pointed to by 1559 <1> ; ss:bp here, which is needed for running depack.end 1560 <1> %endif 1561 00000844 1F <1> pop ds 1562 <1> %if _ALLOW_OVERLAPPING 1563 00000845 53 <1> push bx 1564 00000846 E81402 <1> call check_pointers_not_overlapping 1565 00000849 5B <1> pop bx ; returns CF 1566 <1> .error_CY_12: 1567 0000084A 7203 <1> jc short .error_1 1568 <1> %endif 1569 0000084C E902FD <1> jmp .loop 1570 <1> 1571 <1> %if ! _ALLOW_OVERLAPPING 1572 <1> .error_CY_12: 1573 <1> %endif 1574 <1> .error_1: 1575 0000084F E9A000 <1> jmp .error 1576 <1> 1577 <1> 1578 <1> .end_member: ; End Of Stream marker 1579 00000852 837EF600 <1> cmp word [bp + ?len + 2], min_match_len >> 16 1580 00000856 7504 <1> jne @F 1581 00000858 837EF402 <1> cmp word [bp + ?len], min_match_len & 0FFFFh 1582 <1> @@: 1583 0000085C 75F1 <1> jne short .error_1 1584 <1> 1585 <1> ; decode_member succeeded 1586 <1> 1587 0000085E C55EE4 <1> lds bx, [bp + ?final_dst] ; -> localvariables 1588 <1> 1589 00000861 836EE014 <1> sub word [bp + ?length_of_source], lzip_trailer_size 1590 00000865 835EE200 <1> sbb word [bp + ?length_of_source + 2], 0 1591 00000869 7303E98400 <1> jc .error 1592 <1> 1593 0000086E C476E8 <1> les si, [bp + ?src] ; es:si -> lzip_trailer.uncompressed_checksum 1594 00000871 83C604 <1> add si, 4 ; skip CRC 1595 <1> 1596 <1> ; es:si -> lzip_trailer.uncompressed_size 1597 00000874 26AD <1> es lodsw ; does the destination length match ? 1598 00000876 3B4714 <1> cmp ax, word [bx + lz_decoder.pos] 1599 00000879 7577 <1> jne .error 1600 0000087B 26AD <1> es lodsw 1601 0000087D 3B4716 <1> cmp ax, word [bx + lz_decoder.pos + 2] 1602 00000880 7570 <1> jne .error ; if no --> 1603 00000882 26AD <1> es lodsw 1604 00000884 85C0 <1> test ax, ax 1605 00000886 756A <1> jnz .error 1606 00000888 26AD <1> es lodsw 1607 0000088A 85C0 <1> test ax, ax 1608 0000088C 7564 <1> jnz .error 1609 <1> 1610 0000088E 830714 <1> add word [bx + lz_decoder.range_decoder + range_decoder.member_pos], lzip_trailer_size 1611 00000891 83570200 <1> adc word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2], 0 1612 00000895 725B <1> jc .error 1613 <1> 1614 <1> ; es:si -> lzip_trailer.member_size 1615 00000897 26AD <1> es lodsw ; does the source length match ? 1616 00000899 3B07 <1> cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos] 1617 0000089B 7555 <1> jne .error 1618 0000089D 26AD <1> es lodsw 1619 0000089F 3B4702 <1> cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2] 1620 000008A2 754E <1> jne .error 1621 000008A4 26AD <1> es lodsw 1622 000008A6 85C0 <1> test ax, ax 1623 000008A8 7548 <1> jnz .error 1624 000008AA 26AD <1> es lodsw 1625 000008AC 85C0 <1> test ax, ax 1626 000008AE 7542 <1> jnz .error 1627 <1> 1628 <1> ; es:si -> behind lzip_trailer 1629 000008B0 06 <1> push es 1630 000008B1 56 <1> push si 1631 000008B2 E8D301 <1> call normalise_pointer 1632 000008B5 8F46E8 <1> pop word [bp + ?src] 1633 000008B8 8F46EA <1> pop word [bp + ?src + 2] 1634 <1> 1635 000008BB E9B9FB <1> jmp .loop_member 1636 <1> 1637 <1> .end: 1638 <1> 1639 <1> .final: 1640 <1> %if _COUNTER && !_PROGRESS 1641 <1> mov al, '%' 1642 <1> call disp_al 1643 <1> %endif 1644 000008BE C47EE4 <1> les di, [bp + ?final_dst] 1645 <1> ; -> destination 1646 000008C1 C576D8 <1> lds si, [bp + ?original_dst] 1647 <1> ; -> source 1648 000008C4 1E <1> push ds 1649 000008C5 56 <1> push si 1650 000008C6 E81002 <1> call pointer_to_linear ; dx:ax = linear ?original_dst 1651 000008C9 91 <1> xchg cx, ax 1652 000008CA 87DA <1> xchg bx, dx ; bx:cx = linear ?original_dst, clobber dx:ax 1653 000008CC FF76D6 <1> push word [bp + ?dst + 2] 1654 000008CF FF76D4 <1> push word [bp + ?dst] 1655 000008D2 E80402 <1> call pointer_to_linear 1656 000008D5 29C8 <1> sub ax, cx 1657 000008D7 19DA <1> sbb dx, bx ; = linear dst minus linear original_dst 1658 <1> %if _SCAN 1659 <1> mov word [bp + ?depackedsize], ax 1660 <1> mov word [bp + ?depackedsize + 2], dx 1661 <1> add word [bp + ?maxbytesahead], localvariables_size & 0FFFFh 1662 <1> adc word [bp + ?maxbytesahead + 2], localvariables_size >> 16 1663 <1> %endif 1664 <1> 1665 000008D9 B90400 <1> mov cx, 4 1666 000008DC 83C00F <1> add ax, 15 1667 000008DF 83D200 <1> adc dx, 0 1668 <1> @@: 1669 000008E2 D1EA <1> shr dx, 1 1670 000008E4 D1D8 <1> rcr ax, 1 1671 000008E6 E2FA <1> loop @B 1672 000008E8 89C1 <1> mov cx, ax 1673 000008EA 85D2 <1> test dx, dx 1674 <1> d0 mov byte [bp + ?errordata], 84h 1675 000008EC 7504 <1> jnz .error 1676 <1> 1677 <1> %ifn _SCAN 1678 000008EE E8D400 <1> call x_mov_p 1679 <1> %endif 1680 <1> 1681 000008F1 A8 <1> db __TEST_IMM8 ; (NC) 1682 <1> .error: 1683 000008F2 F9 <1> stc 1684 <1> 1685 <1> %if _COUNTER 1686 000008F3 9F <1> lahf 1687 000008F4 B00D <1> mov al, 13 1688 000008F6 E8B7F8 <1> call disp_al_for_progress 1689 000008F9 B00A <1> mov al, 10 1690 000008FB E8B2F8 <1> call disp_al_for_progress 1691 000008FE 9E <1> sahf 1692 <1> %endif 1693 <1> d0 mov bx, word [bp + ?errordata] 1694 000008FF 89EC5D <1> lleave code 1695 00000902 C3 <1> lret 1696 <1> 1697 <1> 1698 <1> ; INP: ds:bx -> range_decoder structure 1699 <1> ; ss:bp -> depack stack frame 1700 <1> ; OUT: ! If an error occurs, jumps to depack.error 1701 <1> ; If success, 1702 <1> ; al = byte read 1703 <1> ; CHG: - 1704 <1> Range_decoder.get_byte: 1705 00000903 830701 <1> add word [bx + range_decoder.member_pos], 1 1706 00000906 83570200 <1> adc word [bx + range_decoder.member_pos + 2], 0 1707 0000090A 72E6 <1> jc short .error 1708 <1> 1709 <1> ; INP: ds:bx -> range_decoder structure 1710 <1> ; ss:bp -> depack stack frame 1711 <1> ; OUT: ! If an error occurs, jumps to depack.error 1712 <1> ; If success, 1713 <1> ; al = value read 1714 <1> ; CHG: - 1715 <1> ; get_byte: 1716 0000090C 1E <1> push ds 1717 0000090D 56 <1> push si 1718 <1> 1719 0000090E 836EE001 <1> sub word [bp + ?length_of_source], 1 1720 00000912 835EE200 <1> sbb word [bp + ?length_of_source + 2], 0 1721 00000916 72DA <1> jc short .error 1722 <1> 1723 00000918 C576E8 <1> lds si, [bp + ?src] 1724 0000091B AC <1> lodsb 1725 0000091C 1E <1> push ds 1726 0000091D 56 <1> push si 1727 0000091E E86701 <1> call normalise_pointer 1728 00000921 8F46E8 <1> pop word [bp + ?src] 1729 00000924 8F46EA <1> pop word [bp + ?src + 2] 1730 00000927 5E <1> pop si 1731 00000928 1F <1> pop ds 1732 00000929 C3 <1> retn 1733 <1> 1734 <1> .error: equ depack.error 1735 <1> 1736 <1> 1737 <1> ; INP: ds:bx -> lz_decoder structure 1738 <1> ; al = byte to write to buffer 1739 <1> ; ss:bp -> depack stack frame 1740 <1> ; OUT: ! If an error occurs, jumps to depack.error 1741 <1> ; CHG: cx, dx, ax, di, es 1742 <1> LZ_decoder.put_byte: 1743 0000092A C47ED4 <1> les di, [bp + ?dst] 1744 <1> 1745 0000092D 83471401 <1> add word [bx + lz_decoder.pos], 1 1746 00000931 83571600 <1> adc word [bx + lz_decoder.pos + 2], 0 1747 00000935 72BB <1> jc short .error 1748 <1> 1749 00000937 836EDC01 <1> sub word [bp + ?length_of_destination], 1 1750 0000093B 835EDE00 <1> sbb word [bp + ?length_of_destination + 2], 0 1751 0000093F 72B1 <1> jb short .error 1752 <1> 1753 <1> %if _SCAN 1754 <1> inc di 1755 <1> %else 1756 00000941 AA <1> stosb 1757 <1> %endif 1758 00000942 06 <1> push es 1759 00000943 57 <1> push di 1760 00000944 E84101 <1> call normalise_pointer 1761 00000947 8F46D4 <1> pop word [bp + ?dst] 1762 0000094A 8F46D6 <1> pop word [bp + ?dst + 2] 1763 <1> 1764 <1> %if _ALLOW_OVERLAPPING 1765 0000094D 53 <1> push bx 1766 0000094E E80C01 <1> call check_pointers_not_overlapping 1767 00000951 5B <1> pop bx ; returns CF 1768 00000952 729E <1> jc short .error 1769 <1> %endif 1770 00000954 C3 <1> retn 1771 <1> 1772 <1> .error: equ depack.error 1773 <1> 1774 <1> 1775 <1> ; INP: ds:si = pointer 1776 <1> ; es:di = pointer 1777 <1> ; OUT: ds:si anti normalised 1778 <1> ; es:di anti normalised 1779 <1> anti_normalise_both_pointers: 1780 00000955 1E <1> push ds 1781 00000956 56 <1> push si 1782 00000957 E80A00 <1> call anti_normalise_pointer 1783 0000095A 5E <1> pop si 1784 0000095B 1F <1> pop ds 1785 <1> 1786 0000095C 06 <1> push es 1787 0000095D 57 <1> push di 1788 0000095E E80300 <1> call anti_normalise_pointer 1789 00000961 5F <1> pop di 1790 00000962 07 <1> pop es 1791 00000963 C3 <1> retn 1792 <1> 1793 <1> 1794 <1> ; INP: word [ss:sp + 2] = segment 1795 <1> ; word [ss:sp] = offset 1796 <1> ; 1797 <1> ; Note: Does not work correctly with pointers that point to 1798 <1> ; a HMA location. Do not use then! 1799 <1> anti_normalise_pointer: 1800 <1> lframe near, nested 1801 <1> lpar word, segment 1802 <1> lpar word, offset 1803 <1> lpar_return 1804 00000964 5589E5 <1> lenter 1805 00000967 53 <1> push bx 1806 00000968 51 <1> push cx 1807 <1> 1808 00000969 31DB <1> xor bx, bx 1809 0000096B 31C9 <1> xor cx, cx 1810 0000096D FF7606 <1> push word [bp + ?segment] 1811 00000970 FF7604 <1> push word [bp + ?offset] 1812 00000973 E80A00 <1> call anti_normalise_pointer_with_displacement_bxcx 1813 00000976 8F4604 <1> pop word [bp + ?offset] 1814 00000979 8F4606 <1> pop word [bp + ?segment] 1815 <1> 1816 0000097C 59 <1> pop cx 1817 0000097D 5B <1> pop bx 1818 0000097E 5D <1> lleave 1819 0000097F C3 <1> lret 1820 <1> 1821 <1> 1822 <1> ; INP: word [ss:sp + 2] = segment 1823 <1> ; word [ss:sp] = offset 1824 <1> ; bx:cx = add/sub displacement 1825 <1> ; OUT: dword [ss:sp] = anti-normalised address 1826 <1> ; 1827 <1> ; An anti-normalised pointer has an offset as high as possible, 1828 <1> ; which is in the range 0FFF0h to 0FFFFh unless the pointed-to 1829 <1> ; location is in the first 64 KiB of memory. 1830 <1> anti_normalise_pointer_with_displacement_bxcx: 1831 <1> lframe near, nested 1832 <1> lpar word, segment 1833 <1> lpar word, offset 1834 <1> lpar_return 1835 00000980 5589E5 <1> lenter 1836 00000983 50 <1> push ax 1837 00000984 52 <1> push dx 1838 <1> 1839 00000985 FF7606 <1> push word [bp + ?segment] 1840 00000988 FF7604 <1> push word [bp + ?offset] 1841 0000098B E84B01 <1> call pointer_to_linear 1842 <1> 1843 0000098E 01C8 <1> add ax, cx 1844 00000990 11DA <1> adc dx, bx ; dx:ax += bx:cx 1845 <1> 1846 00000992 83FA01 <1> cmp dx, 1 1847 00000995 7223 <1> jb @F 1848 <1> 1849 00000997 50 <1> push ax 1850 00000998 83C8F0 <1> or ax, 0FFF0h 1851 0000099B 894604 <1> mov word [bp + ?offset], ax 1852 0000099E 58 <1> pop ax 1853 <1> 1854 0000099F 83E8F0 <1> sub ax, 0FFF0h 1855 000009A2 83DA00 <1> sbb dx, 0 1856 <1> 1857 <1> %rep 4 1858 <1> shr dx, 1 1859 <1> rcr ax, 1 1860 <1> %endrep 1858 000009A5 D1EA <2> shr dx, 1 1859 000009A7 D1D8 <2> rcr ax, 1 1858 000009A9 D1EA <2> shr dx, 1 1859 000009AB D1D8 <2> rcr ax, 1 1858 000009AD D1EA <2> shr dx, 1 1859 000009AF D1D8 <2> rcr ax, 1 1858 000009B1 D1EA <2> shr dx, 1 1859 000009B3 D1D8 <2> rcr ax, 1 1861 000009B5 894606 <1> mov word [bp + ?segment], ax 1862 <1> 1863 000009B8 EB07 <1> jmp .return 1864 <1> 1865 <1> ; dx:ax = 0000:offset 1866 <1> @@: 1867 000009BA 894604 <1> mov word [bp + ?offset], ax 1868 000009BD 83660600 <1> and word [bp + ?segment], 0 1869 <1> 1870 <1> .return: 1871 000009C1 5A <1> pop dx 1872 000009C2 58 <1> pop ax 1873 000009C3 5D <1> lleave 1874 000009C4 C3 <1> lret 1875 <1> 1876 <1> 1877 <1> %ifn _SCAN 1878 <1> ; Move paragraphs 1879 <1> ; 1880 <1> ; INP: ds:si -> source 1881 <1> ; es:di -> destination 1882 <1> ; cx = number of paragraphs 1883 <1> ; CHG: ax, bx, cx, dx 1884 <1> ; OUT: ds:si -> after source (normalised) 1885 <1> ; es:di -> after destination (normalised) 1886 <1> ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 1887 <1> ; Do not provide a wrapped/HMA source or destination! 1888 <1> x_mov_p: 1889 000009C5 E8B100 <1> call normalise_both_pointers 1890 000009C8 8CD8 <1> mov ax, ds 1891 000009CA 8CC2 <1> mov dx, es 1892 <1> 1893 000009CC 85C9 <1> test cx, cx 1894 000009CE 7503E98800 <1> jz .return 1895 <1> 1896 000009D3 39D0 <1> cmp ax, dx ; source above destination ? 1897 000009D5 7716 <1> ja .up ; yes, move up (forwards) --> 1898 000009D7 7206 <1> jb .check_down 1899 <1> 1900 000009D9 39FE <1> cmp si, di 1901 000009DB 7710 <1> ja .up 1902 000009DD 747C <1> je .return ; pointers are the same, no need to move --> 1903 <1> .check_down: 1904 000009DF 50 <1> push ax 1905 000009E0 01C8 <1> add ax, cx ; (expected not to carry) 1906 000009E2 39D0 <1> cmp ax, dx ; end of source is above destination ? 1907 000009E4 58 <1> pop ax 1908 000009E5 7726 <1> ja .down ; yes, move from top down --> 1909 000009E7 7204 <1> jb .up 1910 000009E9 39FE <1> cmp si, di 1911 000009EB 7720 <1> ja .down 1912 <1> 1913 <1> ; Here, the end of source is below-or-equal the destination, 1914 <1> ; so they do not overlap. In this case we prefer moving up. 1915 <1> .up: 1916 <1> .uploop: 1917 000009ED 81E9FF0F <1> sub cx, 0FFFh ; 64 KiB - 16 B left ? 1918 000009F1 760C <1> jbe .uplast ; no --> 1919 000009F3 51 <1> push cx 1920 000009F4 B9F87F <1> mov cx, 0FFF0h /2 1921 000009F7 F3A5 <1> rep movsw ; move 64 KiB - 16 B 1922 000009F9 59 <1> pop cx 1923 000009FA E87C00 <1> call normalise_both_pointers 1924 000009FD EBEE <1> jmp short .uploop ; proceed for more --> 1925 <1> .uplast: 1926 000009FF 81C1FF0F <1> add cx, 0FFFh ; restore counter 1927 00000A03 D1E1 <1> shl cx, 1 1928 00000A05 D1E1 <1> shl cx, 1 1929 00000A07 D1E1 <1> shl cx, 1 ; *8, paragraphs to words 1930 00000A09 F3A5 <1> rep movsw ; move last part 1931 00000A0B EB4E <1> jmp short .return 1932 <1> 1933 <1> .down: 1934 00000A0D FD <1> std ; _AMD_ERRATUM_109_WORKAROUND as below 1935 <1> 1936 00000A0E 89C8 <1> mov ax, cx 1937 00000A10 31DB <1> xor bx, bx 1938 00000A12 51 <1> push cx 1939 00000A13 B90400 <1> mov cx, 4 1940 <1> @@: 1941 00000A16 D1E0 <1> shl ax, 1 1942 00000A18 D1D3 <1> rcl bx, 1 1943 00000A1A E2FA <1> loop @B 1944 00000A1C 83E802 <1> sub ax, 2 1945 00000A1F 83DB00 <1> sbb bx, 0 ; -> point at last word 1946 <1> ; (Cannot borrow here because we checked that cx 1947 <1> ; was nonzero at the intro to this function, so 1948 <1> ; bx:ax is at least 16 prior to this subtraction.) 1949 00000A22 91 <1> xchg ax, cx ; bx:cx = displacement to point to last word 1950 00000A23 1E <1> push ds 1951 00000A24 56 <1> push si 1952 00000A25 E858FF <1> call anti_normalise_pointer_with_displacement_bxcx 1953 00000A28 5E <1> pop si 1954 00000A29 1F <1> pop ds ; -> last word of source 1955 00000A2A 06 <1> push es 1956 00000A2B 57 <1> push di 1957 00000A2C E851FF <1> call anti_normalise_pointer_with_displacement_bxcx 1958 00000A2F 5F <1> pop di 1959 00000A30 07 <1> pop es ; -> last word of destination 1960 00000A31 59 <1> pop cx 1961 <1> 1962 <1> .dnloop: 1963 00000A32 81E9FF0F <1> sub cx, 0FFFh ; 64 KiB - 16 B left ? 1964 00000A36 760C <1> jbe .dnlast ; no --> 1965 00000A38 51 <1> push cx 1966 00000A39 B9F87F <1> mov cx, 0FFF0h /2 1967 00000A3C F3A5 <1> rep movsw ; move 64 KiB - 16 B 1968 00000A3E 59 <1> pop cx 1969 00000A3F E813FF <1> call anti_normalise_both_pointers 1970 00000A42 EBEE <1> jmp short .dnloop ; proceed for more --> 1971 <1> .dnlast: 1972 00000A44 81C1FF0F <1> add cx, 0FFFh ; restore counter 1973 00000A48 D1E1 <1> shl cx, 1 1974 00000A4A D1E1 <1> shl cx, 1 1975 00000A4C D1E1 <1> shl cx, 1 ; *8, paragraphs to words 1976 <1> 1977 <1> 1978 <1> numdef AMD_ERRATUM_109_WORKAROUND, 1 1979 <1> %if 0 1980 <1> 1981 <1> Jack R. Ellis pointed out this erratum: 1982 <1> 1983 <1> Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69: 1984 <1> 1985 <1> 109 Certain Reverse REP MOVS May Produce Unpredictable Behavior 1986 <1> 1987 <1> Description 1988 <1> 1989 <1> In certain situations a REP MOVS instruction may lead to 1990 <1> incorrect results. An incorrect address size, data size 1991 <1> or source operand segment may be used or a succeeding 1992 <1> instruction may be skipped. This may occur under the 1993 <1> following conditions: 1994 <1> 1995 <1> * EFLAGS.DF=1 (the string is being moved in the reverse direction). 1996 <1> 1997 <1> * The number of items being moved (RCX) is between 1 and 20. 1998 <1> 1999 <1> * The REP MOVS instruction is preceded by some microcoded instruction 2000 <1> that has not completely retired by the time the REP MOVS begins 2001 <1> execution. The set of such instructions includes BOUND, CLI, LDS, 2002 <1> LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions. 2003 <1> 2004 <1> Potential Effect on System 2005 <1> 2006 <1> Incorrect results may be produced or the system may hang. 2007 <1> 2008 <1> Suggested Workaround 2009 <1> 2010 <1> Contact your AMD representative for information on a BIOS update. 2011 <1> 2012 <1> %endif 2013 <1> 2014 <1> %if _AMD_ERRATUM_109_WORKAROUND 2015 00000A4E E308 <1> jcxz @FF 2016 00000A50 83F914 <1> cmp cx, 20 2017 00000A53 7703 <1> ja @FF 2018 <1> @@: 2019 00000A55 A5 <1> movsw 2020 00000A56 E2FD <1> loop @B 2021 <1> @@: 2022 <1> %endif 2023 00000A58 F3A5 <1> rep movsw ; move first part 2024 00000A5A FC <1> cld 2025 <1> .return: 2026 00000A5B EB1C <1> jmp normalise_both_pointers 2027 <1> %endif 1865 %endif 1866 1867 1868 %if _LZO 1869 %include "lzo.asm" 1870 %endif 1871 1872 1873 %if _LZSA2 1874 %include "lzsa2.asm" 1875 %endif 1876 1877 1878 %if _APL 1879 %include "apl.asm" 1880 %endif 1881 1882 1883 %if _BZP 1884 %include "bzp.asm" 1885 %endif 1886 1887 1888 %if _ZEROCOMP 1889 %include "zerocomp.asm" 1890 %endif 1891 1892 1893 %if _MVCOMP 1894 %include "mvcomp.asm" 1895 %endif 1896 1897 1898 %if _LZEXEDAT 1899 %include "lzexedat.asm" 1900 %endif 1901 1902 1903 %if _ZX0 1904 %include "zx0.asm" 1905 %endif 1906 1907 1908 %if _SCAN && ! SCAN_SUPPORTED 1909 %error Scan not supported by this depacker method 1910 %endif 1911 1912 1913 %if _ALLOW_OVERLAPPING 1914 ; INP: ?src, ?dst 1915 ; OUT: CY if error (?src < ?dst) 1916 ; NC if success 1917 ; CHG: ax, bx, cx, dx 1918 check_pointers_not_overlapping: 1919 1920 %if _SCAN 1921 push word [bp + ?original_dst + 2] 1922 push word [bp + ?original_dst] 1923 call pointer_to_linear 1924 xchg cx, ax 1925 xchg bx, dx ; bx:cx = linear ?original_dst 1926 %endif 1927 1928 %if CHECK_POINTERS_VARIABLE_DST 1929 00000A5D FF76D6 push word [bp + ?dst + 2] 1930 00000A60 FF76D4 push word [bp + ?dst] 1931 %else 1932 push es 1933 push di 1934 %endif 1935 00000A63 E87300 call pointer_to_linear ; dx:ax = linear ?dst 1936 1937 %if _SCAN 1938 sub ax, cx 1939 sbb dx, bx 1940 mov word [bp + ?plusdst], ax 1941 mov word [bp + ?plusdst + 2], dx 1942 1943 push word [bp + ?original_src + 2] 1944 push word [bp + ?original_src] 1945 call pointer_to_linear 1946 xchg cx, ax 1947 xchg bx, dx ; bx:cx = linear ?original_src 1948 %else 1949 00000A66 91 xchg cx, ax 1950 00000A67 87DA xchg bx, dx ; bx:cx = linear ?dst after write 1951 %endif 1952 1953 %if CHECK_POINTERS_VARIABLE_SRC 1954 00000A69 FF76EA push word [bp + ?src + 2] 1955 00000A6C FF76E8 push word [bp + ?src] 1956 %else 1957 push ds 1958 push si 1959 %endif 1960 00000A6F E86700 call pointer_to_linear ; dx:ax = linear ?src before next read 1961 1962 %if _SCAN 1963 sub ax, cx 1964 sbb dx, bx 1965 mov word [bp + ?plussrc], ax 1966 mov word [bp + ?plussrc + 2], dx; = plussrc 1967 1968 mov bx, word [bp + ?plusdst + 2] 1969 mov cx, word [bp + ?plusdst] ; = plusdst 1970 1971 %if 0 1972 plusdst = dst - dstbuffer; 1973 plussrc = src - srcbuffer; 1974 if (plusdst > plussrc) { 1975 bytesahead = plusdst - plussrc; 1976 if (bytesahead > *maxbytesahead) { 1977 *maxbytesahead = bytesahead; 1978 } 1979 } 1980 %endif 1981 1982 cmp bx, dx 1983 jne @F 1984 cmp cx, ax ; plusdst > plussrc ? 1985 @@: 1986 jna .ret ; no --> 1987 1988 sub cx, ax 1989 sbb bx, dx ; bytesahead = plusdst - plussrc 1990 1991 cmp bx, word [bp + ?maxbytesahead + 2] 1992 jne @F 1993 cmp cx, word [bp + ?maxbytesahead] 1994 @@: ; bytesahead > maxbytesahead ? 1995 jna .ret ; no --> 1996 1997 mov word [bp + ?maxbytesahead + 2], bx 1998 mov word [bp + ?maxbytesahead], cx 1999 ; update maxbytesahead 2000 2001 .ret: 2002 clc ; NC 2003 %else 2004 00000A72 39DA cmp dx, bx ; ?src >= ?dst ? 2005 00000A74 7502 jne @F 2006 00000A76 39C8 cmp ax, cx 2007 @@: 2008 ; (CY) if error (src < dst) 2009 ; (NC) if no error 2010 %endif 2011 00000A78 C3 retn 2012 %endif 2013 2014 ; This leaves the lframe context created within the 2015 ; specific depacker's file. The above function 2016 ; check_pointers_not_overlapping uses the frame. 2017 lleave ctx 2018 2019 2020 %if _SCAN 2021 ; Pretend to copy data for scan mode. Don't actually 2022 ; read or write the data, just adjust registers as if. 2023 ; 2024 ; INP: ds:si -> source 2025 ; es:di -> destination 2026 ; cx = amount of bytes to copy 2027 ; OUT: si incremented 2028 ; di incremented 2029 ; cx = 0 2030 ; CHG: (not even flags) 2031 scan_rep_movsb: 2032 pushf 2033 add si, cx 2034 add di, cx 2035 xor cx, cx 2036 popf 2037 disp_al_for_progress: 2038 disp_al_counter: 2039 disp_al: 2040 retn 2041 %endif 2042 2043 2044 ; INP: ds:si = pointer 2045 ; es:di = pointer 2046 ; OUT: ds:si normalised 2047 ; es:di normalised 2048 %if NEED_NORMALISE_BOTH_POINTERS 2049 normalise_both_pointers: 2050 00000A79 06 push es 2051 00000A7A 57 push di 2052 00000A7B E80A00 call normalise_pointer 2053 00000A7E 5F pop di 2054 00000A7F 07 pop es 2055 %endif 2056 2057 normalise_dssi_pointer: 2058 00000A80 1E push ds 2059 00000A81 56 push si 2060 00000A82 E80300 call normalise_pointer 2061 00000A85 5E pop si 2062 00000A86 1F pop ds 2063 00000A87 C3 retn 2064 2065 2066 ; INP: word [ss:sp + 2] = segment 2067 ; word [ss:sp] = offset 2068 ; 2069 ; Note: Does not work correctly with pointers that point to 2070 ; a HMA location. Do not use then! 2071 normalise_pointer: 2072 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2073 lframe near 2074 lpar word, segment 2075 lpar word, offset 2076 lpar_return 2077 00000A88 5589E5 lenter 2078 2079 00000A8B 837E040F cmp word [bp + ?offset], 15 2080 00000A8F 7617 jbe .ret 2081 2082 00000A91 53 push bx 2083 00000A92 51 push cx 2084 2085 00000A93 31DB xor bx, bx 2086 00000A95 31C9 xor cx, cx 2087 00000A97 FF7606 push word [bp + ?segment] 2088 00000A9A FF7604 push word [bp + ?offset] 2089 00000A9D E80A00 call normalise_pointer_with_displacement_bxcx 2090 00000AA0 8F4604 pop word [bp + ?offset] 2091 00000AA3 8F4606 pop word [bp + ?segment] 2092 2093 00000AA6 59 pop cx 2094 00000AA7 5B pop bx 2095 .ret: 2096 00000AA8 5D lleave 2097 00000AA9 C3 lret 2098 2099 2100 ; INP: word [ss:sp + 2] = segment 2101 ; word [ss:sp] = offset 2102 ; bx:cx = add/sub displacement 2103 ; OUT: CY if the displacement carries 2104 ; NC if not 2105 normalise_pointer_with_displacement_bxcx: 2106 %endif 2107 lframe near 2108 lpar word, segment 2109 lpar word, offset 2110 lpar_return 2111 00000AAA 5589E5 lenter 2112 2113 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2114 cmp word [bp + ?offset], 15 2115 jbe .ret 2116 %endif 2117 2118 00000AAD 50 push ax 2119 00000AAE 51 push cx 2120 00000AAF 52 push dx 2121 2122 00000AB0 FF7606 push word [bp + ?segment] 2123 00000AB3 FF7604 push word [bp + ?offset] 2124 00000AB6 E82000 call pointer_to_linear 2125 2126 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2127 ; push bx 2128 ; ; sign-extend cx into bx:cx 2129 ; cmp cx, 8000h ; CY if < 8000h (NC if negative) 2130 ; cmc ; NC if positive 2131 ; sbb bx, bx ; 0 if was NC, -1 if was CY 2132 2133 00000AB9 01C1 add cx, ax 2134 00000ABB 11DA adc dx, bx ; dx:cx = dx:ax + bx:cx 2135 ; pop bx 2136 00000ABD 9F lahf ; ah = flags 2137 %else 2138 xchg ax, cx 2139 %endif 2140 2141 %if 0 2142 ; Adds in HMA support for this function. Not currently used. 2143 cmp dx, 10h ; dx:ax >= 10_0000h ? 2144 jb @F ; no, linear-to-pointer normally --> 2145 ; ja .error 2146 2147 add cx, 10h 2148 ; jc .error 2149 mov word [bp + ?offset], cx 2150 or word [bp + ?segment], -1 2151 jmp .return 2152 @@: 2153 %endif 2154 2155 00000ABE 53 push bx 2156 00000ABF 89CB mov bx, cx 2157 00000AC1 83E10F and cx, 15 2158 00000AC4 894E04 mov word [bp + ?offset], cx 2159 2160 00000AC7 B104 mov cl, 4 2161 @@: 2162 00000AC9 D1EA shr dx, 1 2163 00000ACB D1DB rcr bx, 1 2164 00000ACD E2FA loop @B 2165 2166 00000ACF 895E06 mov word [bp + ?segment], bx 2167 00000AD2 5B pop bx 2168 2169 ; test dx, dx 2170 ; jnz .error 2171 2172 .return: 2173 2174 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2175 00000AD3 9E sahf ; restore flags from ah 2176 %endif 2177 00000AD4 5A pop dx 2178 00000AD5 59 pop cx 2179 00000AD6 58 pop ax 2180 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2181 .ret: 2182 %endif 2183 00000AD7 5D lleave 2184 00000AD8 C3 lret 2185 2186 2187 ; INP: word [ss:sp + 2] = segment 2188 ; word [ss:sp] = offset 2189 ; OUT: dx:ax = linear address 2190 pointer_to_linear: 2191 lframe near 2192 lpar word, segment 2193 lpar word, offset 2194 00000AD9 5589E5 lenter 2195 2196 00000ADC 8B4606 mov ax, word [bp + ?segment] 2197 00000ADF 31D2 xor dx, dx 2198 00000AE1 51 push cx 2199 00000AE2 B90400 mov cx, 4 2200 @@: 2201 00000AE5 D1E0 shl ax, 1 2202 00000AE7 D1D2 rcl dx, 1 2203 00000AE9 E2FA loop @B 2204 2205 00000AEB 034604 add ax, word [bp + ?offset] 2206 00000AEE 11CA adc dx, cx ; cx = 0 here 2207 00000AF0 59 pop cx 2208 2209 00000AF1 5D lleave 2210 00000AF2 C20400 lret 2211 2212 2213 [list -] 2216 2217 %if _PASSLCFG 2218 align 16 2219 transfer_lcfg_block: 2220 times lcfg.size nop 2221 %endif 2222 00000AF5 90 align 16 2223 init1_end: 2224 2225 2226 usesection INIT0 2226 ------------------ note: usesection INIT0 2227 %if _TEST_PROGRAM 2228 init0_msg: 2229 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 2230 00000202 4572726F723A20556E- .error_stderr_file: db "Error: Unable to open own executable file.",13,10 2230 0000020B 61626C6520746F206F- 2230 00000214 70656E206F776E2065- 2230 0000021D 786563757461626C65- 2230 00000226 2066696C652E0D0A 2231 .error_stderr_file.length equ $ - .error_stderr_file 2232 %endif 2233 0000022E 4572726F723A204E6F- .error_stderr: db "Error: Not enough memory allocated.",13,10 2233 00000237 7420656E6F75676820- 2233 00000240 6D656D6F727920616C- 2233 00000249 6C6F63617465642E0D- 2233 00000252 0A 2234 .error_stderr.length: equ $ - .error_stderr 2235 .error_c_stdout: 2236 00000253 30 .error_stdout: db "0" 2237 %if 0 2238 _autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE + (payload_end - payload) + (init1_end - init1_start) + ADDITIONAL_MEMORY ) 2243 %endif 2244 00000254 0D0A db 13,10 2245 .error_c_stdout.length: equ $ - .error_c_stdout 2246 .error_stdout.length: equ $ - .error_stdout 2247 2248 00000256 90 align 1024 2249 %if ($ - $$) != 1024 2250 %error Wrong INIT0 size 2251 %endif 2252 %endif 2253 2254 align 16 2255 init0_end: 2256 2257 2258 %assign num (init1_end - init1_start) + (init0_end - init0_start) 2259 %if _BRIEFLZ 2260 %define which iniblz 2261 %elif _LZ4 2262 %define which inilz4 2263 %elif _SNAPPY 2264 %define which inisz 2265 %elif _EXODECR 2266 %define which iniexo 2267 %elif _X 2268 %define which inix 2269 %elif _HEATSHRINK 2270 %define which inihs 2271 %elif _LZD 2272 %define which inilz 2273 %elif _LZO 2274 %define which inilzo 2275 %elif _LZSA2 2276 %define which inilzsa2 2277 %elif _APL 2278 %define which iniapl 2279 %elif _BZP 2280 %define which inibzp 2281 %elif _ZEROCOMP 2282 %define which inizero 2283 %elif _MVCOMP 2284 %define which inimv 2285 %elif _LZEXEDAT 2286 %define which inilzexe 2287 %elif _ZX0 2288 %define which inizx0 2289 %endif 2290 %warning which: num bytes used for depacker 2290 ****************** warning: inilz: 3840 bytes used for depacker [-w+user] 2291 2292 2293 %if _TEST_PROGRAM 2294 addsection INIT2, align=16 follows=INIT1 vstart=0 2294 ------------------ note: usesection INIT2 2295 init2_start: 2296 2297 %if _USESCAN 2298 scan: 2299 00000000 noteincbin _SCANBINARY, "scan.lst" 2299 ------------------ note: include listing file './tmp/lz/scan.lst' 2300 2301 init2_entry: 2302 %endif 2303 2304 2305 ; si => after PSP 2306 ; cs => INIT2 2307 ; psp, free, payload, init1, init2, payload space, stack 2308 ; 2309 ; The correct allocation for the test program 2310 ; is image size (init0, payload, init1, init2) 2311 ; minus init0 plus compressed payload size 2312 ; plus decompressed size plus stack. For 2313 ; simplicity, init0 subtraction may be skipped. 2314 2315 ; ss:sp -> word amount repetitions, word ax 2316 ; bx = 1 if A mode test, 2317 ; 8001h if B mode test, 2318 ; 4001h if C mode test 2319 000008B6 53 push bx ; push into ?whichtest 2320 2321 lframe 0 2322 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 2323 lpar word, handle 2324 %endif 2325 lpar word, repetitions 2326 lpar word, whichtest 2327 %if _RELOAD_XMS 2328 lvar dword, xmsentry 2329 lvar word, xmshandle 2330 %endif 2331 %if _INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2332 lequ 128, buffersize 2333 lvar ?buffersize, buffer 2334 %endif 2335 000008B7 5589E58DA67AFF lenter 2336 2337 %if _RELOAD_FILE && _RELOAD_XMS 2338 000008BE 834EFAFF or word [bp + ?xmshandle], -1 2339 %endif 2340 2341 %if _USESCAN 2342 doscan: 2343 000008C2 56 push si 2344 000008C3 8CC8 mov ax, cs 2345 000008C5 2DB500 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2348 000008C8 8ED8 mov ds, ax ; => source 2349 2350 lframe 0, nested 2351 000008CA 5589E5 lenter 2352 lvar word, buffer 2353 000008CD 56 push si ; => buffer 2354 2355 000008CE 29F0 sub ax, si ; = amount paragraphs 2356 lvar word, bufferparas 2357 000008D0 50 push ax 2358 2359 000008D1 31D2 xor dx, dx 2360 000008D3 B90400 mov cx, 4 2361 @@: 2362 000008D6 D1E0 shl ax, 1 2363 000008D8 D1D2 rcl dx, 1 2364 000008DA E2FA loop @B 2365 lvar dword, bufferbytes 2366 000008DC 52 push dx 2367 000008DD 50 push ax 2368 2369 000008DE 31F6 xor si, si 2370 lvar dword, progressticks 2371 000008E0 56 push si 2372 000008E1 56 push si 2373 lvar dword, maxbytesahead 2374 000008E2 56 push si 2375 000008E3 56 push si 2376 lvar dword, depackedsize 2377 000008E4 56 push si 2378 000008E5 56 push si ; stack variables used by scan 2379 2380 000008E6 BB0100 mov bx, 1 ; pretend exe mode 2381 000008E9 B94A00 mov cx, (payload.end - payload) & 0FFFFh 2382 %if (payload.end - payload) >> 16 2383 mov dx, (payload.end - payload) >> 16 ; = length of source 2384 %else 2385 000008EC 31D2 xor dx, dx 2386 %endif 2387 000008EE B8FFFF mov ax, -1 ; pretend no kernel clamp 2388 000008F1 E80CF7 call scan 2389 ; CF, stack variables written 2390 000008F4 0E push cs 2391 000008F5 1F pop ds 2392 000008F6 7269 jc .fail 2393 2394 000008F8 BB[3C0D] mov bx, init2_msg.scan.success 2395 000008FB E86B03 call init2_error_disp_counted 2396 2397 000008FE 58 pop ax 2398 000008FF 5A pop dx ; depacked size 2399 00000900 E88503 call init2_error_decdword 2400 2401 00000903 BB[4F0D] mov bx, init2_msg.scan.1 2402 00000906 E86003 call init2_error_disp_counted 2403 2404 00000909 B84A00 mov ax, (payload.end - payload) & 0FFFFh 2405 %if (payload.end - payload) >> 16 2406 mov dx, (payload.end - payload) >> 16 ; = length of source 2407 %else 2408 0000090C 31D2 xor dx, dx 2409 %endif 2410 0000090E E87703 call init2_error_decdword 2411 2412 00000911 BB[560D] mov bx, init2_msg.scan.2 2413 00000914 E85203 call init2_error_disp_counted 2414 2415 00000917 58 pop ax 2416 00000918 5A pop dx ; maxbytesahead 2417 00000919 E86C03 call init2_error_decdword 2418 0000091C 83C00F add ax, 15 2419 0000091F 83D200 adc dx, 0 ; += 15 2420 00000922 B90400 mov cx, 4 2421 @@: 2422 00000925 D1EA shr dx, 1 2423 00000927 D1D8 rcr ax, 1 2424 00000929 E2FA loop @B ; >>= 4 2425 2426 0000092B 85D2 test dx, dx 2427 0000092D 7403 jz @F 2428 0000092F B8FFFF mov ax, -1 2429 @@: 2430 00000932 96 xchg si, ax ; si = maximum paras ahead 2431 2432 00000933 BB[5E0D] mov bx, init2_msg.scan.3 2433 00000936 E83003 call init2_error_disp_counted 2434 2435 00000939 89F0 mov ax, si 2436 0000093B E84203 call init2_error_decword 2437 2438 0000093E BB[650D] mov bx, init2_msg.scan.4 2439 00000941 E82503 call init2_error_disp_counted 2440 2441 00000944 81C6B500 add si, paras( (init1_end - init1_start) + (payload_end - payload) ) 2443 00000948 89F0 mov ax, si ; = decompression size 2444 0000094A E83303 call init2_error_decword 2445 2446 0000094D BB[6D0D] mov bx, init2_msg.scan.5 2447 00000950 E81603 call init2_error_disp_counted 2448 2449 00000953 58 pop ax 2450 00000954 5A pop dx ; progress ticks 2451 00000955 E83003 call init2_error_decdword 2452 2453 00000958 BB[740D] mov bx, init2_msg.scan.6 2454 0000095B E80B03 call init2_error_disp_counted 2455 2456 0000095E 96 xchg ax, si ; ax = decompression size 2457 0000095F EB09 jmp @F 2458 2459 .fail: 2460 00000961 BB[770D] mov bx, init2_msg.scan.fail 2461 00000964 E80203 call init2_error_disp_counted 2462 2463 00000967 B8FFFF mov ax, -1 2464 @@: 2465 2466 0000096A 89EC5D lleave 2467 0000096D 5E pop si 2468 2469 init2_scan_done: 2470 lvar word, scansizeresult 2471 0000096E 50 push ax 2472 %endif 2473 2474 0000096F 8B5604 mov dx, word [bp + ?repetitions] 2475 00000972 83FAFF cmp dx, -1 2476 00000975 7509 jne @F 2477 2478 .cmdline_error: 2479 %if _DEBUG0 2480 mov bx, -1 2481 %endif 2482 00000977 BA[460E] mov dx, init2_msg.cmdline_error 2483 0000097A B92400 mov cx, init2_msg.cmdline_error.length 2484 0000097D E97402 jmp init2_error 2485 2486 2487 @@: 2488 00000980 F6460340 testopt [bp + ?whichtest], 4000h 2489 00000984 750C jnz .a_or_c 2490 00000986 F6460380 testopt [bp + ?whichtest], 8000h 2491 0000098A 7406 jz .a_or_c 2492 .b: 2493 0000098C 85D2 test dx, dx 2494 0000098E 74E7 jz .cmdline_error 2495 00000990 EB04 jmp @F 2496 2497 .a_or_c: 2498 00000992 85D2 test dx, dx 2499 00000994 75E1 jnz .cmdline_error 2500 @@: 2501 2502 %if _RELOAD_XMS 2503 00000996 56 push si 2504 00000997 B80043 mov ax, 4300h 2505 0000099A CD2F int 2Fh 2506 0000099C 3C80 cmp al, 80h 2507 %if _RELOAD_FILE 2508 0000099E 7538 jne .noxms 2509 %else 2510 jne init2_error_xms 2511 %endif 2512 000009A0 B81043 mov ax, 4310h 2513 000009A3 CD2F int 2Fh 2514 000009A5 895EFC mov word [bp + ?xmsentry], bx 2515 000009A8 8C46FE mov word [bp + ?xmsentry + 2], es 2516 000009AB B409 mov ah, 09h 2517 000009AD BA0100 mov dx, KiB(payload_end - payload) 2518 000009B0 FF5EFC call far [bp + ?xmsentry] 2519 000009B3 83F801 cmp ax, 1 2520 %if _RELOAD_FILE 2521 000009B6 7520 jne .noxms 2522 %else 2523 jne init2_error_xms 2524 %endif 2525 000009B8 8956FA mov word [bp + ?xmshandle], dx 2526 000009BB 8CC8 mov ax, cs 2527 000009BD 2DB500 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2530 000009C0 0E push cs 2531 000009C1 1F pop ds 2532 000009C2 BE[3C0F] mov si, init2_xmsm_to_save 2533 000009C5 89540A mov word [si + XMSM.dsthdl], dx 2534 000009C8 894408 mov word [si + XMSM.srcadr + 2], ax 2535 %ifn _RELOAD_FILE 2536 push ax 2537 %endif 2538 000009CB B40B mov ah, 0Bh 2539 000009CD FF5EFC call far [bp + ?xmsentry] 2540 000009D0 83F801 cmp ax, 1 2541 000009D3 7403E90802 jne init2_error_xms_free 2542 %ifn _RELOAD_FILE 2543 pop ax ; => payload 2544 %else 2545 .noxms: 2546 000009D8 8CC8 mov ax, cs 2547 000009DA 2DB500 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2550 @@: 2551 %endif 2552 000009DD 5E pop si 2553 %elif _RELOAD_FILE 2554 mov ax, cs 2555 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2558 %else 2559 mov dx, cs 2560 add dx, (init2_end - init2_start) >> 4 2561 ; => payload saving area 2562 mov ax, cs 2563 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2566 mov cx, (payload_end - payload) >> 4 2567 call init2_movp ; copy payload to payload saving area 2568 %endif 2569 ; We save away the payload here because a failure 2570 ; to decompress generally overwrites part of that 2571 ; payload which was used as source. 2572 2573 000009DE 89C2 mov dx, ax ; dx => payload source to use 2574 000009E0 8CC8 mov ax, cs 2575 000009E2 2DB000 sub ax, (init1_end - init1_start) >> 4 2576 ; ax => INIT1 2577 000009E5 BB0100 mov bx, 1 ; say we're in EXE mode 2578 000009E8 52 push dx 2579 000009E9 50 push ax 2580 000009EA 56 push si ; si => target 2581 000009EB 0E push cs 2582 000009EC E88F01 call .transfer ; call decompression 2583 000009EF 5E pop si 2584 000009F0 58 pop ax 2585 000009F1 5A pop dx 2586 ; Returns here after decompression. 2587 ; CY if error. 2588 000009F2 7309 jnc @F 2589 2590 000009F4 BA[970D] mov dx, init2_msg.initial_error 2591 000009F7 B93C00 mov cx, init2_msg.initial_error.length 2592 000009FA E9F401 jmp init2_error_free 2593 2594 @@: 2595 %if _INCLUDE_UNCOMPRESSED 2596 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2597 payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed 2598 %else 2599 payload_uncompressed_size equ _TEST_PROGRAM_DECOMPRESSED_SIZE 2600 %endif 2601 000009FD E88401 call checkdecompressed 2602 00000A00 7409 je @F 2603 2604 %if _WRITE_WRONG_FILE 2605 call writefiles 2606 %endif 2607 2608 %if _DEBUG0 2609 mov bx, -1 2610 %endif 2611 00000A02 BA[D30D] mov dx, init2_msg.initial_error_2 2612 00000A05 B93C00 mov cx, init2_msg.initial_error_2.length 2613 00000A08 E9E601 jmp init2_error_free 2614 2615 @@: 2616 %endif 2617 2618 00000A0B F6460340 testopt [bp + ?whichtest], 4000h 2619 00000A0F 7420 jz @F 2620 00000A11 8CC8 mov ax, cs 2621 00000A13 2DB000 sub ax, (init1_end - init1_start) >> 4 2622 ; ax => INIT1 2623 00000A16 8EC0 mov es, ax 2624 00000A18 26A1[4200] mov ax, word [es:init1_c_mode_counter] 2625 00000A1C E8D402 call init2_disp_ax_dec 2626 00000A1F B00D mov al, 13 2627 00000A21 E83A02 call init2_disp_al 2628 00000A24 B00A mov al, 10 2629 00000A26 E83502 call init2_disp_al 2630 %if _RELOAD_XMS 2631 00000A29 E89D01 call freexms 2632 %endif 2633 00000A2C B8004C mov ax, 4C00h 2634 00000A2F CD21 int 21h 2635 2636 @@: 2637 lvar word, upperbound 2638 00000A31 52 push dx 2639 lvar word, lowerbound 2640 00000A32 56 push si 2641 lvar word, current_init1 2642 00000A33 50 push ax 2643 2644 %if _TEST_PROGRESS 2645 00000A34 BA[8C0D] mov dx, init2_msg.progress.1 2646 00000A37 B90700 mov cx, init2_msg.progress.1.length 2647 .loop: 2648 00000A3A 0E push cs 2649 00000A3B 1F pop ds 2650 00000A3C BB0200 mov bx, 2 2651 00000A3F B440 mov ah, 40h 2652 00000A41 CD21 int 21h 2653 %else 2654 .loop: 2655 %endif 2656 2657 00000A43 8B9676FF mov dx, [bp + ?upperbound] 2658 2659 00000A47 F6460380 testopt [bp + ?whichtest], 8000h 2660 00000A4B 741C jz @F 2661 2662 00000A4D FF4E04 dec word [bp + ?repetitions] 2663 00000A50 7526 jnz .test_b_skip_bound 2664 2665 %if _TEST_PROGRESS 2666 00000A52 0E push cs 2667 00000A53 1F pop ds 2668 00000A54 BA[950D] mov dx, init2_msg.progress.linebreak 2669 00000A57 B90200 mov cx, init2_msg.progress.linebreak.length 2670 00000A5A BB0200 mov bx, 2 2671 00000A5D B440 mov ah, 40h 2672 00000A5F CD21 int 21h 2673 %endif 2674 %if _RELOAD_XMS 2675 00000A61 E86501 call freexms 2676 %endif 2677 00000A64 B8004C mov ax, 4C00h 2678 00000A67 CD21 int 21h 2679 2680 2681 @@: 2682 00000A69 2B9674FF sub dx, [bp + ?lowerbound] 2683 00000A6D 7503E9DF00 jz .found 2684 00000A72 D1EA shr dx, 1 2685 ; Rounding down, so that we never retry upper bound. 2686 ; The upper bound is known to be working. 2687 00000A74 039674FF add dx, [bp + ?lowerbound] 2688 2689 .test_b_skip_bound: 2690 00000A78 52 push dx 2691 00000A79 83C205 add dx, (payload_end - payload) >> 4 2692 00000A7C 8B8672FF mov ax, [bp + ?current_init1] 2693 00000A80 B9B000 mov cx, (init1_end - init1_start) >> 4 2694 00000A83 E81704 call init2_movp 2695 00000A86 899672FF mov [bp + ?current_init1], dx 2696 00000A8A 5A pop dx 2697 2698 %if _RELOAD_XMS 2699 00000A8B 8B46FA mov ax, [bp + ?xmshandle] 2700 %if _RELOAD_FILE 2701 00000A8E 83F8FF cmp ax, -1 2702 00000A91 741C je .restore_no_xms 2703 %endif 2704 00000A93 56 push si 2705 00000A94 0E push cs 2706 00000A95 1F pop ds 2707 00000A96 BE[2C0F] mov si, init2_xmsm_from_save 2708 00000A99 894404 mov word [si + XMSM.srchdl], ax 2709 00000A9C 89540E mov word [si + XMSM.dstadr + 2], dx 2710 00000A9F B40B mov ah, 0Bh 2711 00000AA1 FF5EFC call far [bp + ?xmsentry] 2712 00000AA4 83F801 cmp ax, 1 2713 00000AA7 7403E93401 jne init2_error_xms_free 2714 00000AAC 5E pop si 2715 %if _RELOAD_FILE 2716 00000AAD EB53 jmp .restore_done 2717 %endif 2718 %endif 2719 %if _RELOAD_FILE 2720 .restore_no_xms: 2721 size_compressed equ (payload.end - payload) 2722 00000AAF 52 push dx 2723 00000AB0 8EDA mov ds, dx 2724 00000AB2 B9FFFF mov cx, ((- size_compressed) >> 16) & 0FFFFh 2725 00000AB5 BAB6FF mov dx, (- size_compressed) & 0FFFFh 2726 00000AB8 B80242 mov ax, 4202h 2727 00000ABB 8B5E06 mov bx, [bp + ?handle] 2728 00000ABE CD21 int 21h 2729 00000AC0 7303E92601 jc init2_error_file 2730 00000AC5 BA0000 mov dx, size_compressed >> 16 2731 00000AC8 B84A00 mov ax, size_compressed & 0FFFFh 2732 @@: 2733 00000ACB B900FF mov cx, 0FF00h 2734 00000ACE 85D2 test dx, dx 2735 00000AD0 7506 jnz @F 2736 00000AD2 39C8 cmp ax, cx 2737 00000AD4 7302 jae @F 2738 00000AD6 89C1 mov cx, ax 2739 @@: 2740 00000AD8 29C8 sub ax, cx 2741 00000ADA 83DA00 sbb dx, 0 2742 00000ADD 52 push dx 2743 00000ADE 50 push ax 2744 00000ADF 31D2 xor dx, dx 2745 00000AE1 B43F mov ah, 3Fh 2746 00000AE3 CD21 int 21h 2747 00000AE5 7303E90101 jc init2_error_file 2748 00000AEA 39C8 cmp ax, cx 2749 00000AEC 7403E9FA00 jne init2_error_file 2750 00000AF1 8CDA mov dx, ds 2751 00000AF3 81C2F00F add dx, 0FF0h 2752 00000AF7 8EDA mov ds, dx 2753 00000AF9 58 pop ax 2754 00000AFA 5A pop dx 2755 00000AFB 89C1 mov cx, ax 2756 00000AFD 09D1 or cx, dx 2757 00000AFF 75CA jnz @BB 2758 00000B01 5A pop dx 2759 .restore_done: 2760 %endif 2761 %ifn _RELOAD_XMS || _RELOAD_FILE 2762 mov ax, cs 2763 add ax, (init2_end - init2_start) >> 4 2764 ; => payload in saving area 2765 mov cx, (payload_end - payload) >> 4 2766 call init2_movp ; copy payload from payload saving area 2767 %endif 2768 ; dx => source 2769 00000B02 8B8672FF mov ax, [bp + ?current_init1] 2770 00000B06 BB0100 mov bx, 1 2771 00000B09 52 push dx 2772 00000B0A 56 push si 2773 00000B0B 0E push cs 2774 00000B0C E86F00 call .transfer 2775 00000B0F 5E pop si 2776 00000B10 5A pop dx 2777 ; Returns here after decompression. 2778 ; CY if error. 2779 00000B11 7314 jnc @F 2780 2781 00000B13 F6460380 testopt [bp + ?whichtest], 8000h 2782 00000B17 7513 jnz .test_b_fail 2783 2784 ; error: this attempt is one below the new lower bound 2785 00000B19 42 inc dx 2786 00000B1A 899674FF mov word [bp + ?lowerbound], dx 2787 2788 %if _TEST_PROGRESS 2789 00000B1E BA[930D] mov dx, init2_msg.progress.fail 2790 00000B21 B90100 mov cx, init2_msg.progress.fail.length 2791 %endif 2792 00000B24 E913FF jmp .loop 2793 2794 @@: 2795 %if _INCLUDE_UNCOMPRESSED 2796 00000B27 E85A00 call checkdecompressed 2797 00000B2A 7418 je @F 2798 2799 %if _WRITE_WRONG_FILE 2800 call writefiles 2801 %endif 2802 2803 .test_b_fail: 2804 %if _TEST_PROGRESS 2805 00000B2C 0E push cs 2806 00000B2D 1F pop ds 2807 00000B2E BA[950D] mov dx, init2_msg.progress.linebreak 2808 00000B31 B90200 mov cx, init2_msg.progress.linebreak.length 2809 00000B34 BB0200 mov bx, 2 2810 00000B37 B440 mov ah, 40h 2811 00000B39 CD21 int 21h 2812 %endif 2813 %if _DEBUG0 2814 mov bx, -2 2815 %endif 2816 00000B3B BA[0F0E] mov dx, init2_msg.subsequent_error_2 2817 00000B3E B93700 mov cx, init2_msg.subsequent_error_2.length 2818 00000B41 E9AD00 jmp init2_error_free 2819 2820 @@: 2821 %endif 2822 ; success: this attempt is the new upper bound 2823 00000B44 899676FF mov word [bp + ?upperbound], dx 2824 %if _TEST_PROGRESS 2825 00000B48 BA[940D] mov dx, init2_msg.progress.success 2826 00000B4B B90100 mov cx, init2_msg.progress.success.length 2827 %endif 2828 00000B4E E9E9FE jmp .loop 2829 2830 .found: 2831 %if _TEST_PROGRESS 2832 00000B51 0E push cs 2833 00000B52 1F pop ds 2834 00000B53 BA[950D] mov dx, init2_msg.progress.linebreak 2835 00000B56 B90200 mov cx, init2_msg.progress.linebreak.length 2836 00000B59 BB0200 mov bx, 2 2837 00000B5C B440 mov ah, 40h 2838 00000B5E CD21 int 21h 2839 %endif 2840 00000B60 8B8676FF mov ax, word [bp + ?upperbound] 2841 00000B64 29F0 sub ax, si ; = how many paragraphs in buffer before source 2842 00000B66 05B500 add ax, paras( (init1_end - init1_start) + (payload_end - payload) ) 2844 ; = how many paragraphs needed for process 2845 00000B69 E88701 call init2_disp_ax_dec 2846 00000B6C B00D mov al, 13 2847 00000B6E E8ED00 call init2_disp_al 2848 00000B71 B00A mov al, 10 2849 00000B73 E8E800 call init2_disp_al 2850 %if _RELOAD_XMS 2851 00000B76 E85000 call freexms 2852 %endif 2853 00000B79 B8004C mov ax, 4C00h 2854 00000B7C CD21 int 21h 2855 2856 2857 .transfer: 2858 00000B7E 31FF xor di, di 2859 00000B80 57 push di ; placeholder ax value on stack 2860 00000B81 50 push ax ; INIT1 segment 2861 00000B82 57 push di ; zero = init1_start 2862 00000B83 CB retf ; transfer to INIT1:init1_start 2863 2864 2865 %if _INCLUDE_UNCOMPRESSED 2866 2867 2868 %if _WRITE_WRONG_FILE 2869 ; INP: si => decompressed image 2870 ; payload_uncompressed_size = size 2871 ; ! _INCLUDE_UNCOMPRESSED_IN_IMAGE: 2872 ; word [bp + ?handle] = file handle 2873 ; [bp + ?buffer] = ?buffersize buffer 2874 ; OUT: WRONG.BIN contains what we decompressed 2875 ; WRONG2.BIN contains expected payload 2876 ; CHG: ds, si, ax, bx, cx, dx 2877 ; STT: UP 2878 writefiles: 2879 push cs 2880 pop ds 2881 mov dx, init2_msg.wrong_file_name 2882 xor cx, cx 2883 mov ah, 3Ch 2884 int 21h 2885 jc .notfile 2886 2887 mov bx, ax 2888 mov cx, payload_uncompressed_size >> 4 2889 xor dx, dx 2890 .loopfile: 2891 mov ds, si 2892 mov ah, 40h 2893 push cx 2894 mov cx, 16 2895 int 21h 2896 pop cx 2897 inc si 2898 loop .loopfile 2899 2900 mov ds, si 2901 mov cx, payload_uncompressed_size & 15 2902 mov ah, 40h 2903 int 21h 2904 2905 mov ah, 3Eh 2906 int 21h 2907 2908 .notfile: 2909 2910 push cs 2911 pop ds 2912 mov dx, init2_msg.wrong_file_name2 2913 xor cx, cx 2914 mov ah, 3Ch 2915 int 21h 2916 jc .notfile2 2917 2918 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2919 mov bx, ax 2920 mov cx, payload_uncompressed_size >> 4 2921 mov si, cs 2922 add si, (payload_uncompressed - init2_start) >> 4 2923 xor dx, dx 2924 .loopfile2: 2925 mov ds, si 2926 mov ah, 40h 2927 push cx 2928 mov cx, 16 2929 int 21h 2930 pop cx 2931 inc si 2932 loop .loopfile2 2933 2934 mov ds, si 2935 mov cx, payload_uncompressed_size & 15 2936 mov ah, 40h 2937 int 21h 2938 2939 mov ah, 3Eh 2940 int 21h 2941 %else 2942 xchg si, ax 2943 2944 %if _RELOAD_FILE 2945 mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh 2946 mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh 2947 %else 2948 mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh 2949 mov dx, (- payload_uncompressed_size) & 0FFFFh 2950 %endif 2951 mov ax, 4202h 2952 mov bx, [bp + ?handle] 2953 int 21h 2954 jc .closefile2 2955 2956 push ss 2957 pop ds 2958 lea dx, [bp + ?buffer] 2959 2960 %if payload_uncompressed_size == 0 2961 %error Empty payload not allowed 2962 %endif 2963 %if (payload_uncompressed_size / ?buffersize) != 0 2964 mov cx, payload_uncompressed_size / ?buffersize 2965 %if ?buffersize == 0 || (?buffersize & 15) != 0 2966 %error Unexpected layout 2967 %endif 2968 .loop: 2969 push cx 2970 mov cx, ?buffersize 2971 call transferchunk 2972 pop cx 2973 jc .closefile2 2974 loop .loop 2975 %endif 2976 %if (payload_uncompressed_size % ?buffersize) != 0 2977 mov cx, payload_uncompressed_size % ?buffersize 2978 call transferchunk 2979 %endif 2980 2981 .closefile2: 2982 mov bx, si 2983 mov ah, 3Eh 2984 int 21h 2985 %endif 2986 2987 .notfile2: 2988 retn 2989 2990 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2991 ; INP: ds:dx -> buffer 2992 ; cx = size to transfer, must fit in buffer 2993 ; ?handle = source file handle 2994 ; si = destination file handle 2995 ; OUT: NC if success 2996 ; CY if error 2997 ; CHG: ax, bx 2998 ; STT: UP 2999 transferchunk: 3000 mov bx, word [bp + ?handle] 3001 mov ah, 3Fh 3002 int 21h 3003 jc .ret 3004 cmp ax, cx 3005 stc 3006 jne .ret ; if partial read --> (CY) 3007 mov bx, si 3008 mov ah, 40h 3009 int 21h 3010 jc .ret 3011 cmp ax, cx 3012 je .ret ; if not partial write --> (NC) 3013 stc 3014 .ret: 3015 retn 3016 %endif 3017 3018 %endif 3019 3020 3021 ; INP: si => decompressed image 3022 ; payload_uncompressed_size = size 3023 ; ! _INCLUDE_UNCOMPRESSED_IN_IMAGE: 3024 ; word [bp + ?handle] = file handle 3025 ; [bp + ?buffer] = ?buffersize buffer 3026 ; OUT: ZR if matching 3027 ; NZ if mismatching 3028 ; CHG: es, ds, di, bx, cx 3029 ; STT: UP 3030 checkdecompressed: 3031 00000B84 50 push ax 3032 00000B85 52 push dx 3033 00000B86 56 push si 3034 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 3035 %if _PAYLOAD_KERNEL_MAX_PARAS 3036 mov cx, _PAYLOAD_KERNEL_MAX_PARAS 3037 mov bx, 0 3038 %else 3039 mov cx, payload_uncompressed_size >> 4 3040 mov bx, payload_uncompressed_size & 15 3041 %endif 3042 mov di, cs 3043 add di, (payload_uncompressed - init2_start) >> 4 3044 jcxz .end 3045 .loop: 3046 push cx 3047 mov cx, 8 3048 mov ds, si 3049 mov es, di 3050 inc si 3051 inc di 3052 push si 3053 push di 3054 xor si, si 3055 xor di, di 3056 repe cmpsw 3057 pop di 3058 pop si 3059 pop cx 3060 jne .ret 3061 loop .loop 3062 .end: 3063 mov ds, si 3064 mov es, di 3065 xor si, si 3066 xor di, di ; (ZR) 3067 mov cx, bx 3068 repe cmpsb 3069 %else 3070 %if _RELOAD_FILE 3071 size_compressed_plus_uncompressed equ payload_uncompressed_size + (payload.end - payload) 3073 00000B87 B9FFFF mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh 3074 00000B8A BA86FF mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh 3075 %else 3076 mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh 3077 mov dx, (- payload_uncompressed_size) & 0FFFFh 3078 %endif 3079 00000B8D B80242 mov ax, 4202h 3080 00000B90 8B5E06 mov bx, [bp + ?handle] 3081 00000B93 CD21 int 21h 3082 00000B95 720A jc .error 3083 %if payload_uncompressed_size == 0 3084 %error Empty payload not allowed 3085 %endif 3086 %if (payload_uncompressed_size / ?buffersize) != 0 3087 mov cx, payload_uncompressed_size / ?buffersize 3088 %if ?buffersize == 0 || (?buffersize & 15) != 0 3089 %error Unexpected layout 3090 %endif 3091 .loop: 3092 push cx 3093 mov cx, ?buffersize 3094 call comparechunk 3095 pop cx 3096 jne .ret 3097 loop .loop 3098 %endif 3099 %if (payload_uncompressed_size % ?buffersize) != 0 3100 00000B97 B93000 mov cx, payload_uncompressed_size % ?buffersize 3101 00000B9A E80800 call comparechunk 3102 %endif 3103 %endif 3104 .ret: 3105 00000B9D 5E pop si 3106 00000B9E 5A pop dx 3107 00000B9F 58 pop ax 3108 00000BA0 C3 retn 3109 3110 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 3111 .error: 3112 00000BA1 0C01 or al, 1 ; NZ 3113 00000BA3 EBF8 jmp .ret 3114 %endif 3115 %endif 3116 3117 3118 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 3119 ; INP: ?buffer -> ?buffersize buffer 3120 ; cx = amount of bytes, 0 < cx <= ?buffersize 3121 ; si => chunk 3122 ; ?handle = handle 3123 ; seek -> chunk 3124 ; OUT: NZ if mismatch or error 3125 ; ZR else, 3126 ; si => next chunk (assumes full chunk) 3127 ; CHG: ds, es, di, ax, bx, cx, dx 3128 ; STT: UP 3129 comparechunk: 3130 00000BA5 16 push ss 3131 00000BA6 1F pop ds 3132 00000BA7 8D967AFF lea dx, [bp + ?buffer] 3133 00000BAB 8B5E06 mov bx, [bp + ?handle] 3134 00000BAE B43F mov ah, 3Fh 3135 00000BB0 CD21 int 21h 3136 00000BB2 7212 jc .error 3137 00000BB4 39C8 cmp ax, cx 3138 00000BB6 750E jne .error 3139 00000BB8 8EC6 mov es, si 3140 00000BBA 83C608 add si, ?buffersize / 16 3141 00000BBD 56 push si 3142 00000BBE 31FF xor di, di 3143 00000BC0 89D6 mov si, dx 3144 00000BC2 F3A6 repe cmpsb 3145 00000BC4 5E pop si 3146 .ret: 3147 00000BC5 C3 retn 3148 3149 .error: 3150 00000BC6 0C01 or al, 1 ; NZ 3151 00000BC8 C3 retn 3152 %endif 3153 3154 %if _RELOAD_XMS 3155 freexms: 3156 00000BC9 50 push ax 3157 00000BCA 53 push bx 3158 00000BCB 52 push dx 3159 00000BCC BAFFFF mov dx, -1 3160 00000BCF 8756FA xchg dx, [bp + ?xmshandle] 3161 %if _RELOAD_FILE 3162 00000BD2 83FAFF cmp dx, -1 3163 00000BD5 7405 je @F 3164 %endif 3165 00000BD7 B40A mov ah, 0Ah 3166 00000BD9 FF5EFC call far [bp + ?xmsentry] 3167 @@: 3168 00000BDC 5A pop dx 3169 00000BDD 5B pop bx 3170 00000BDE 58 pop ax 3171 00000BDF C3 retn 3172 3173 init2_error_xms_free: 3174 00000BE0 E8E6FF call freexms 3175 init2_error_xms: 3176 00000BE3 BA[6A0E] mov dx, init2_msg.xms_error 3177 00000BE6 B91500 mov cx, init2_msg.xms_error.length 3178 00000BE9 EB09 jmp init2_error 3179 %endif 3180 3181 %if _RELOAD_FILE 3182 init2_error_file: 3183 00000BEB BA[7F0E] mov dx, init2_msg.file_error 3184 00000BEE B91B00 mov cx, init2_msg.file_error.length 3185 %endif 3186 3187 init2_error_free: 3188 %if _RELOAD_XMS 3189 00000BF1 E8D5FF call freexms 3190 %endif 3191 init2_error: 3192 %if _DEBUG0 3193 push bx 3194 %endif 3195 00000BF4 0E push cs 3196 00000BF5 1F pop ds 3197 00000BF6 BB0200 mov bx, 2 3198 00000BF9 B440 mov ah, 40h 3199 00000BFB CD21 int 21h 3200 3201 %if _DEBUG0 3202 mov dx, init2_msg.rc 3203 mov cx, init2_msg.rc.length 3204 mov bx, 2 3205 mov ah, 40h 3206 int 21h 3207 pop ax 3208 call init2_error_disp_ax_hex 3209 mov dx, init2_msg.linebreak 3210 mov cx, init2_msg.linebreak.length 3211 mov bx, 2 3212 mov ah, 40h 3213 int 21h 3214 %endif 3215 3216 00000BFD F6460340 testopt [bp + ?whichtest], 4000h 3217 00000C01 7408 jz @F 3218 00000C03 BA[9A0E] mov dx, init2_msg.error_c_stdout 3219 00000C06 B90300 mov cx, init2_msg.error_c_stdout.length 3220 00000C09 EB0C jmp @FF 3221 @@: 3222 00000C0B F6460380 testopt [bp + ?whichtest], 8000h 3223 00000C0F 750D jnz @FF 3224 00000C11 BA[9A0E] mov dx, init2_msg.error_stdout 3225 00000C14 B90300 mov cx, init2_msg.error_stdout.length 3226 @@: 3227 00000C17 BB0100 mov bx, 1 3228 00000C1A B440 mov ah, 40h 3229 00000C1C CD21 int 21h 3230 @@: 3231 00000C1E B8FF4C mov ax, 4CFFh 3232 00000C21 CD21 int 21h 3233 3234 lleave ctx 3235 3236 3237 %if _DEBUG0 || _USESCAN 3238 init2_error_disp_ax_hex: ; ax 3239 00000C23 86C4 xchg al,ah 3240 00000C25 E80200 call init2_error_disp_al_hex ; display former ah 3241 00000C28 86C4 xchg al,ah ; and fall trough for al 3242 init2_error_disp_al_hex: ; al 3243 00000C2A 51 push cx 3244 00000C2B B104 mov cl,4 3245 00000C2D D2C8 ror al,cl 3246 00000C2F E80300 call init2_error_disp_al_lownibble_hex 3247 ; display former high-nibble 3248 00000C32 D2C0 rol al,cl 3249 00000C34 59 pop cx 3250 ; and fall trough for low-nibble 3251 init2_error_disp_al_lownibble_hex: 3252 00000C35 50 push ax ; save ax for call return 3253 00000C36 240F and al,00001111b ; high nibble must be zero 3254 00000C38 0430 add al,'0' ; if number is 0-9, now it's the correct character 3255 00000C3A 3C39 cmp al,'9' 3256 00000C3C 7602 jna .decimalnum ; if we get decimal number with this, ok --> 3257 00000C3E 0407 add al,7 ; otherwise, add 7 and we are inside our alphabet 3258 .decimalnum: 3259 00000C40 E80200 call init2_error_disp_al 3260 00000C43 58 pop ax 3261 00000C44 C3 retn 3262 3263 3264 init2_error_disp_al: 3265 00000C45 52 push dx 3266 00000C46 51 push cx 3267 00000C47 53 push bx 3268 00000C48 50 push ax 3269 00000C49 89E2 mov dx, sp 3270 00000C4B 1E push ds 3271 00000C4C 16 push ss 3272 00000C4D 1F pop ds 3273 00000C4E B90100 mov cx, 1 3274 00000C51 BB0200 mov bx, 2 3275 00000C54 B440 mov ah, 40h 3276 00000C56 CD21 int 21h 3277 00000C58 1F pop ds 3278 00000C59 58 pop ax 3279 00000C5A 5B pop bx 3280 00000C5B 59 pop cx 3281 00000C5C 5A pop dx 3282 00000C5D C3 retn 3283 %endif 3284 3285 3286 init2_disp_al: 3287 00000C5E 52 push dx 3288 00000C5F 50 push ax 3289 00000C60 88C2 mov dl, al 3290 00000C62 B402 mov ah, 2 3291 00000C64 CD21 int 21h 3292 00000C66 58 pop ax 3293 00000C67 5A pop dx 3294 00000C68 C3 retn 3295 3296 3297 %if _USESCAN 3298 init2_error_disp_counted: 3299 00000C69 50 push ax 3300 00000C6A 53 push bx 3301 00000C6B 51 push cx 3302 00000C6C 52 push dx 3303 00000C6D 31C9 xor cx, cx 3304 00000C6F 8A0F mov cl, [bx] 3305 00000C71 8D5701 lea dx, [bx + 1] 3306 00000C74 B440 mov ah, 40h 3307 00000C76 BB0200 mov bx, 2 3308 00000C79 CD21 int 21h 3309 00000C7B 5A pop dx 3310 00000C7C 59 pop cx 3311 00000C7D 5B pop bx 3312 00000C7E 58 pop ax 3313 00000C7F C3 retn 3314 3315 3316 init2_error_decword: 3317 00000C80 52 push dx 3318 00000C81 31D2 xor dx, dx 3319 00000C83 E80200 call init2_error_decdword 3320 00000C86 5A pop dx 3321 00000C87 C3 retn 3322 3323 3324 init2_error_decdword: 3325 00000C88 51 push cx 3326 00000C89 31C9 xor cx, cx 3327 00000C8B E80200 call init2_error_dec_dword_minwidth 3328 00000C8E 59 pop cx 3329 00000C8F C3 retn 3330 3331 3332 ; Dump dword as decimal number string 3333 ; 3334 ; INP: dx:ax = dword 3335 ; cx = minimum width (<= 1 for none, must be < 10) 3336 ; es:di -> where to store 3337 ; OUT: es:di -> behind variable-length string 3338 ; CHG: - 3339 ; STT: UP 3340 init2_error_dec_dword_minwidth: 3341 lframe near 3342 lequ 10, bufferlen 3343 lvar ?bufferlen,buffer 3344 00000C90 5589E58D66F6 lenter 3345 lvar dword, dividend 3346 00000C96 52 push dx 3347 00000C97 50 push ax 3348 00000C98 49 dec cx 3349 lvar word, minwidth 3350 00000C99 51 push cx 3351 00000C9A 41 inc cx 3352 3353 00000C9B 50 push ax 3354 00000C9C 53 push bx 3355 00000C9D 51 push cx 3356 00000C9E 52 push dx 3357 00000C9F 56 push si 3358 00000CA0 57 push di 3359 00000CA1 06 push es 3360 3361 00000CA2 16 push ss 3362 00000CA3 07 pop es 3363 3364 00000CA4 8D7EFF lea di, [bp + ?buffer + ?bufferlen - 1] 3365 00000CA7 89FB mov bx, di 3366 00000CA9 FD std ; _AMD_ERRATUM_109_WORKAROUND does not apply 3367 3368 ; dword [bp + ?dividend] = number to display 3369 00000CAA B90A00 mov cx, 10 ; divisor 3370 .loop_write: 3371 3372 00000CAD 31D2 xor dx, dx 3373 00000CAF 57 push di 3374 00000CB0 BF0400 mov di, 4 3375 .loop_divide: 3376 00000CB3 8B43F0 mov ax, [bp + ?dividend - 2 + di] 3377 00000CB6 F7F1 div cx 3378 00000CB8 8943F0 mov word [bp + ?dividend - 2 + di], ax 3379 00000CBB 4F dec di 3380 00000CBC 4F dec di 3381 00000CBD 75F4 jnz .loop_divide 3382 ; dx = last remainder 3383 00000CBF 5F pop di 3384 00000CC0 92 xchg ax, dx ; ax = remainder (next digit) 3385 ; dword [bp + ?dividend] = result of div 3386 00000CC1 0430 add al, '0' 3387 00000CC3 AA stosb 3388 00000CC4 FF4EF0 dec word [bp + ?minwidth] 3389 00000CC7 79E4 jns .loop_write 3390 3391 00000CC9 837EF400 cmp word [bp + ?dividend + 2], 0 3392 00000CCD 75DE jnz .loop_write 3393 00000CCF 837EF200 cmp word [bp + ?dividend], 0 3394 ; any more ? 3395 00000CD3 75D8 jnz .loop_write ; loop --> 3396 3397 00000CD5 FC cld 3398 3399 00000CD6 29FB sub bx, di 3400 00000CD8 89D9 mov cx, bx 3401 00000CDA 89FA mov dx, di 3402 00000CDC 42 inc dx 3403 3404 00000CDD B440 mov ah, 40h 3405 00000CDF BB0200 mov bx, 2 ; stderr 3406 00000CE2 1E push ds 3407 00000CE3 16 push ss 3408 00000CE4 1F pop ds 3409 00000CE5 CD21 int 21h 3410 00000CE7 1F pop ds 3411 3412 00000CE8 07 pop es 3413 00000CE9 5F pop di 3414 3415 00000CEA 5E pop si 3416 00000CEB 5A pop dx 3417 00000CEC 59 pop cx 3418 00000CED 5B pop bx 3419 00000CEE 58 pop ax 3420 3421 00000CEF 89EC5D lleave 3422 00000CF2 C3 retn 3423 %endif 3424 3425 3426 ; Display number in ax decimal 3427 ; 3428 ; INP: ax = number 3429 ; OUT: displayed using Int21.02 3430 ; CHG: none 3431 init2_disp_ax_dec: ; ax (no leading zeros) 3432 00000CF3 53 push bx 3433 00000CF4 31DB xor bx, bx 3434 .pushax: 3435 00000CF6 52 push dx 3436 00000CF7 50 push ax 3437 00000CF8 08DB or bl, bl 3438 00000CFA 7405 jz .nobl 3439 00000CFC 80EB05 sub bl, 5 3440 00000CFF F6DB neg bl 3441 .nobl: 3442 00000D01 51 push cx 3443 00000D02 B91027 mov cx, 10000 3444 00000D05 E81B00 call .divide_out 3445 00000D08 B9E803 mov cx, 1000 3446 00000D0B E81500 call .divide_out 3447 00000D0E B96400 mov cx, 100 3448 00000D11 E80F00 call .divide_out 3449 00000D14 B10A mov cl, 10 3450 00000D16 E80A00 call .divide_out 3451 ; (Divisor 1 is useless) 3452 00000D19 0430 add al, '0' 3453 00000D1B E840FF call init2_disp_al 3454 00000D1E 59 pop cx 3455 00000D1F 58 pop ax 3456 00000D20 5A pop dx 3457 00000D21 5B pop bx ; Caller's register 3458 00000D22 C3 retn 3459 3460 3461 ; INP: ax = number 3462 ; cx = divisor 3463 ; OUT: ax = remainder of operation 3464 ; result displayed 3465 .divide_out: 3466 00000D23 52 push dx 3467 00000D24 31D2 xor dx, dx 3468 00000D26 F7F1 div cx ; 0:ax / cx 3469 00000D28 52 push dx ; remainder 3470 00000D29 FECB dec bl 3471 00000D2B 7503 jnz .nobl2 3472 00000D2D 80CF01 or bh, 1 3473 .nobl2: 3474 00000D30 08C7 or bh, al 3475 00000D32 7405 jz .leadingzero 3476 00000D34 0430 add al, '0' 3477 00000D36 E825FF call init2_disp_al ; display result 3478 .leadingzero: 3479 00000D39 58 pop ax ; remainder 3480 00000D3A 5A pop dx 3481 00000D3B C3 retn 3482 3483 3484 init2_msg: 3485 %if _USESCAN 3486 00000D3C 124E6F74653A205363- .scan.success: counted "Note: Scan depack=" 3486 00000D45 616E2064657061636B- 3486 00000D4E 3D 3487 00000D4F 06207061636B3D .scan.1: counted " pack=" 3488 00000D56 072061686561643D .scan.2: counted " ahead=" 3489 00000D5E 062C706172613D .scan.3: counted ",para=" 3490 00000D65 0720616C6C6F633D .scan.4: counted " alloc=" 3491 00000D6D 06207469636B3D .scan.5: counted " tick=" 3492 00000D74 020D0A .scan.6: counted 13,10 3493 00000D77 144E6F74653A205363- .scan.fail: counted "Note: Scan failure",13,10 3493 00000D80 616E206661696C7572- 3493 00000D89 650D0A 3494 %endif 3495 %if _TEST_PROGRESS 3496 00000D8C 496E666F3A2031 .progress.1: db "Info: 1" 3497 .progress.1.length: equ $ - .progress.1 3498 00000D93 46 .progress.fail: db "F" 3499 .progress.fail.length: equ $ - .progress.fail 3500 00000D94 53 .progress.success: db "S" 3501 .progress.success.length: equ $ - .progress.success 3502 00000D95 0D0A .progress.linebreak: db 13,10 3503 .progress.linebreak.length: equ $ - .progress.linebreak 3504 %endif 3505 %if _WRITE_WRONG_FILE 3506 .wrong_file_name: asciz "WRONG.BIN" 3507 .wrong_file_name2: asciz "WRONG2.BIN" 3508 %endif 3509 00000D97 4572726F723A205465- .initial_error: db "Error: Test program failed to decompress with full buffer." 3509 00000DA0 73742070726F677261- 3509 00000DA9 6D206661696C656420- 3509 00000DB2 746F206465636F6D70- 3509 00000DBB 726573732077697468- 3509 00000DC4 2066756C6C20627566- 3509 00000DCD 6665722E 3510 00000DD1 0D0A .linebreak: db 13,10 3511 .initial_error.length: equ $ - .initial_error 3512 .linebreak.length: equ $ - .linebreak 3513 %if _DEBUG0 3514 .rc: db "Error: Failure code=" 3515 .rc.length: equ $ - .rc 3516 %endif 3517 %if _INCLUDE_UNCOMPRESSED 3518 00000DD3 4572726F723A205465- .initial_error_2: db "Error: Test program decompressed wrongly with full buffer.",13,10 3518 00000DDC 73742070726F677261- 3518 00000DE5 6D206465636F6D7072- 3518 00000DEE 65737365642077726F- 3518 00000DF7 6E676C792077697468- 3518 00000E00 2066756C6C20627566- 3518 00000E09 6665722E0D0A 3519 .initial_error_2.length: equ $ - .initial_error_2 3520 00000E0F 4572726F723A205465- .subsequent_error_2: db "Error: Test program decompressed wrongly during test.",13,10 3520 00000E18 73742070726F677261- 3520 00000E21 6D206465636F6D7072- 3520 00000E2A 65737365642077726F- 3520 00000E33 6E676C792064757269- 3520 00000E3C 6E6720746573742E0D- 3520 00000E45 0A 3521 .subsequent_error_2.length: equ $ - .subsequent_error_2 3522 %endif 3523 00000E46 4572726F723A20496E- .cmdline_error: db "Error: Invalid command line input.",13,10 3523 00000E4F 76616C696420636F6D- 3523 00000E58 6D616E64206C696E65- 3523 00000E61 20696E7075742E0D0A 3524 .cmdline_error.length: equ $ - .cmdline_error 3525 %if _RELOAD_XMS 3526 00000E6A 4572726F723A20584D- .xms_error: db "Error: XMS failure.",13,10 3526 00000E73 53206661696C757265- 3526 00000E7C 2E0D0A 3527 .xms_error.length: equ $ - .xms_error 3528 %endif 3529 %if _RELOAD_FILE 3530 00000E7F 4572726F723A204669- .file_error: db "Error: File read failure.",13,10 3530 00000E88 6C6520726561642066- 3530 00000E91 61696C7572652E0D0A 3531 .file_error.length: equ $ - .file_error 3532 %endif 3533 3534 .error_c_stdout: 3535 00000E9A 30 .error_stdout: db "0" 3536 %if 0 3537 _autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE + (payload_end - payload) + (init1_end - init1_start) + ADDITIONAL_MEMORY ) 3542 %endif 3543 00000E9B 0D0A db 13,10 3544 .error_c_stdout.length: equ $ - .error_c_stdout 3545 .error_stdout.length: equ $ - .error_stdout 3546 3547 3548 ; Move paragraphs 3549 ; 3550 ; INP: ax => source 3551 ; dx => destination 3552 ; cx = number of paragraphs 3553 ; CHG: - 3554 ; OUT: ax and dx unchanged 3555 ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 3556 ; Do not provide a wrapped/HMA source or destination! 3557 init2_movp: 3558 00000E9D 51 push cx 3559 00000E9E 1E push ds 3560 00000E9F 56 push si 3561 00000EA0 06 push es 3562 00000EA1 57 push di 3563 3564 00000EA2 39D0 cmp ax, dx ; source above destination ? 3565 00000EA4 770A ja .up ; yes, move up (forwards) --> 3566 00000EA6 747B je .return ; same, no need to move --> 3567 00000EA8 50 push ax 3568 00000EA9 01C8 add ax, cx ; (expected not to carry) 3569 00000EAB 39D0 cmp ax, dx ; end of source is above destination ? 3570 00000EAD 58 pop ax 3571 00000EAE 7730 ja .down ; yes, move from top down --> 3572 ; Here, the end of source is below-or-equal the destination, 3573 ; so they do not overlap. In this case we prefer moving up. 3574 3575 .up: 3576 00000EB0 50 push ax 3577 00000EB1 52 push dx 3578 .uploop: 3579 00000EB2 8ED8 mov ds, ax 3580 00000EB4 8EC2 mov es, dx 3581 00000EB6 31FF xor di, di 3582 00000EB8 31F6 xor si, si ; -> start of segment 3583 00000EBA 81E90010 sub cx, 1000h ; 64 KiB left ? 3584 00000EBE 7610 jbe .uplast ; no --> 3585 00000EC0 51 push cx 3586 00000EC1 B90080 mov cx, 10000h /2 3587 00000EC4 F3A5 rep movsw ; move 64 KiB 3588 00000EC6 59 pop cx 3589 00000EC7 050010 add ax, 1000h 3590 00000ECA 81C20010 add dx, 1000h ; -> next segment 3591 00000ECE EBE2 jmp short .uploop ; proceed for more --> 3592 .uplast: 3593 00000ED0 81C10010 add cx, 1000h ; restore counter 3594 00000ED4 D1E1 shl cx, 1 3595 00000ED6 D1E1 shl cx, 1 3596 00000ED8 D1E1 shl cx, 1 ; *8, paragraphs to words 3597 00000EDA F3A5 rep movsw ; move last part 3598 00000EDC 5A pop dx 3599 00000EDD 58 pop ax 3600 00000EDE EB43 jmp short .return 3601 3602 .down: 3603 00000EE0 FD std ; _AMD_ERRATUM_109_WORKAROUND as below 3604 .dnloop: 3605 00000EE1 81E90010 sub cx, 1000h ; 64 KiB left ? 3606 00000EE5 761A jbe .dnlast ; no --> 3607 00000EE7 50 push ax 3608 00000EE8 52 push dx 3609 00000EE9 01C8 add ax, cx 3610 00000EEB 01CA add dx, cx 3611 00000EED 8ED8 mov ds, ax ; -> 64 KiB not yet moved 3612 00000EEF 8EC2 mov es, dx 3613 00000EF1 5A pop dx 3614 00000EF2 58 pop ax 3615 00000EF3 BFFEFF mov di, -2 3616 00000EF6 89FE mov si, di ; moved from last word down 3617 00000EF8 51 push cx 3618 00000EF9 B90080 mov cx, 10000h /2 3619 00000EFC F3A5 rep movsw ; move 64 KiB 3620 00000EFE 59 pop cx 3621 00000EFF EBE0 jmp short .dnloop ; proceed for more --> 3622 .dnlast: 3623 00000F01 81C10010 add cx, 1000h ; restore counter 3624 00000F05 D1E1 shl cx, 1 3625 00000F07 D1E1 shl cx, 1 3626 00000F09 D1E1 shl cx, 1 ; *8, paragraphs to words 3627 00000F0B 89CF mov di, cx 3628 00000F0D 4F dec di 3629 00000F0E D1E7 shl di, 1 ; words to offset, -> last word 3630 00000F10 89FE mov si, di 3631 00000F12 8ED8 mov ds, ax 3632 00000F14 8EC2 mov es, dx ; first segment correct 3633 3634 ; Refer to comment in init0_movp. 3635 %if _AMD_ERRATUM_109_WORKAROUND 3636 00000F16 E308 jcxz @FF 3637 00000F18 83F914 cmp cx, 20 3638 00000F1B 7703 ja @FF 3639 @@: 3640 00000F1D A5 movsw 3641 00000F1E E2FD loop @B 3642 @@: 3643 %endif 3644 00000F20 F3A5 rep movsw ; move first part 3645 00000F22 FC cld 3646 .return: 3647 00000F23 5F pop di 3648 00000F24 07 pop es 3649 00000F25 5E pop si 3650 00000F26 1F pop ds 3651 00000F27 59 pop cx 3652 00000F28 C3 retn 3653 3654 3655 00000F29 90 align 4 3656 %if _RELOAD_XMS 3657 init2_xmsm_from_save: 3658 istruc XMSM 3659 00000F2C 50000000 at XMSM.size_, dd payload_end - payload 3660 00000F30 00 iend 3661 init2_xmsm_to_save: 3662 istruc XMSM 3663 00000F3C 50000000 at XMSM.size_, dd payload_end - payload 3664 00000F40 00 iend 3665 %endif 3666 3667 00000F4C 90 align 16 3668 3669 %if _INCLUDE_UNCOMPRESSED && _INCLUDE_UNCOMPRESSED_IN_IMAGE 3670 strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN" 3671 payload_uncompressed: 3672 incbin _UNCOMPRESSED_FILE 3673 .end: 3674 db 38 3675 align 16, db 38 3676 %endif 3677 init2_end: 3678 %endif 3679 3680 3681 %endif ; _SCAN 3682 [list +]