;LZ6KUN: Unpacker para el proyecto de fin de carrera ; (M‚todo 1 - LZ6K > LZ greedy con diccionario de 6K) ; ; Versi¢n 1.0 ; ; Realizado en lenguaje ensamblador, se compila con NASM ; ; - El programa maestro de Windows, recibe por el puerto serie el nombre del ; archivo y permite elegir la localizaci¢n del directorio de salida ; visualmente. Entonces graba el nombre del archivo con su path y acabado en ; 0 en otro archivo llamado SALIDA.ARC, que se coloca en el mismo path del ; programa, donde tambi‚n est situado este m¢dulo de descompresi¢n. ; ; - Este modulo de compresi¢n tiene como misi¢n abrir el archivo comprimido ; ENTRADA.CMP y descomprimir el archivo comprimido en el path y con el nombre ; que han sido indicados en SALIDA.ARC org 256 mov ax,3d00h ;Funci¢n para abrir archivo mov dx,namein ;Nombre del archivo a abrir int 33 ;Abrir ENTRADA.CMP jnc noerror01 ;Si no hay error, continuar mov ax,4c01h ;C¢digo de error 1 int 33 ;Salir a Windows noerror01 mov [handlein],ax ;Salvar handle de ENTRADA.CMP mov ax,3d00h ;Funci¢n para abrir archivo mov dx,namepath ;Nombre del archivo a abrir int 33 ;Abrir SALIDA.ARC jnc noerror02 ;Si no hay error, continuar mov ax,4c02h ;C¢digo de error 2 int 33 ;Salir a Windows noerror02 xchg ax,bx ;Handle de SALIDA.ARC en bx mov ah,3fh ;Funci¢n para leer de archivo mov cx,400 ;N£mero m ximo de bytes a leer mov dx,pathbuffer ;Posici¢n donde se escriben los bytes int 33 ;Leer bytes jnc noerror03 ;Si no hay error, continuar mov ax,4c03h ;C¢digo de error 3 int 33 ;Salir a Windows noerror03 mov si,dx ;Apuntar al nombre de archivo con path mov dx,18 ;Crear o truncar archivo existente mov bx,1 ;Modo de acceso solo escritura xor cx,cx ;Sin atributos mov ax,716ch ;Funci¢n para crear o abrir archivo ; usando nombres largos int 33 ;Crear archivo de salida jnc noerror05 ;Si no hay error, continuar mov ax,4c05h ;C¢digo de error 5 int 33 ;Salir a Windows noerror05 mov [handleout],ax ;Salvar handle del archivo de salida mov dx,inbuff ;Posici¢n en la que se lee mov cx,32768 ;Bytes a leer mov bx,[handlein] ;Handle del archivo de entrada mov ah,3fh ;Funci¢n de lectura int 33 ;Leer hasta 32K de datos comprimidos mov si,dx ;Puntero de lectura mov di,outbuff ;Puntero de escritura mov dl,128 ;Marker bit bucle xor bp,bp ;N£mero de bytes que se retroceden ; en el puntero de lectura al ; escribir 128 bytes = 0 call getbit ;Tomar un bit jnc literalbyte ;Si es 0, ir a literalbyte mov cx,4 ;Si no, prepararse para leer 4 bits xor bx,bx ;Borrar registro de destino call getbits ;Leer 4 bits en bx cmp bx,13 ;Si el resultado es < 13 jc codepair ; es un codepair ;Si no, es una cadena de litarales literalchain and bx,3 ;Guardar los dos £ltimos bits inc cx ;Completar YYY con otro bit call getbits ;Leerlo inc cx ;Primer bit del n£mero de bytes - 4 xchg bx,cx ;Se leen cx bits en bx call getbits ;bx=numero de bytes encadenados - 4 add bx,4 ;Completar n£mero de bytes mov cx,bx ;Colocar en cx chain call get_si ;Tomar un literal byte de la cadena call put_di ;Colocarlo en el buffer de salida loop chain ;Repetir hasta que cx=0 jmp bucle ;Seguir descomprimiendo literalbyte call get_si ;Tomar un literal call put_di ;Colocarlo en el buffer de salida jmp bucle ;Seguir descomprimiendo codepair inc cx ;Primer bit de la distancia xchg bx,cx ;Se leen cx bits en bx call getbits ;Leer distancia en bx push bx ;Guardar distancia en la pila mov cl,3 ;Leer 3 bits xor bx,bx ;Borrar registro de destino call getbits ;Leer n£mero de bits de la longitud inc cx ;Primer bit de la longitud cmp bx,7 ;Si el n£mero es 7, hemos alcanzado jz EOF ; el final del archivo > salir xchg bx,cx ;Se leen cx bits en bx call getbits ;bx=numero de bytes repetidos - 1 inc bx ;Completar longitud de la coincidencia mov cx,bx ;Colocar en cx pop bx ;Distancia en bx push si ;Guardar si mov si,di ;Hacer que si apunte a la parte que sub si,bx ; va a repetirse, = puntero de ; escritura - distancia mov bp,128 ;N£mero de bytes que se retroceden ; en el puntero de lectura al ; escribir 128 bytes uncomp_match lodsb ;Leer un byte call put_di ;Escribirlo loop uncomp_match ;Repetir cx veces pop si ;Restaurar si jmp bucle ;Seguir descomprimiendo EOF pop bx ;(sacar distancia de la pila) mov ah,40h ;Funci¢n para escribir en archivo mov dx,outbuff ;Escribir desde el comienzo del buffer mov cx,di ;Todos los bytes que haya sub cx,dx ;CX = DI-DX mov bx,[handleout] ;Handle del archivo de salida int 33 ;Vaciar buffer de escritura exit mov ax,4c00h ;C¢digo de error 0 (sin problemas) int 33 ;Salir a Windows getbits jcxz nobitstotake ;Si no hay bits que tomar, saltar getbitsl call getbit ;Tomar un bit adc bx,bx ;Colocarlo en bx loop getbitsl ;Repetir nobitstotake ret getbit add dl,dl ;Sacar bit por el flag C jnz gotten ;Si el tag-byte es 0, hay que xchg ax,dx ; tomar otro call get_si ;Leer byte en AL xchg ax,dx ; pasar byte a DL stc ;Flag C para poner el bit de marca adc dl,dl ;Sacar bit y poner la marca gotten ret get_si cmp si,inbuffend ;¨Estamos en el borde? jnz dontread ; si no: no leer pusha ;Guardar registros mov ah,3fh ;Funci¢n para leer de archivo mov cx,32768 ;N£mero m ximo de bytes a leer mov bx,[handlein] ;Handle del archivo comprimido mov dx,inbuff ;Leer en el buffer de entrada int 33 ;Leer hasta otros 32K de datos jnc noerror04 ;Si no hay error, continuar mov ax,4c04h ;C¢digo de error 4 int 33 ;Salir a Windows noerror04 popa mov si,inbuff ;Colocar puntero al comienzo de los ; nuevos datos dontread lodsb ;Leer un byte ret put_di stosb ;Guardar byte en el diccionario cmp di,outbuffend ;Si no llegamos al tope jnz dontwrite ;No escribir nada pusha ;Hemos llegado al final del buffer mov dx,outbuff ;Escribir la primera parte de los mov cx,128 ; datos descomprimidos, 128 bytes mov ah,40h ;Funci¢n para escribir archivo mov bx,[handleout] ;Handle del archivo de salida int 33 ;Escribir jnc noerror06 ;Si no hay error, continuar mov ax,4c06h ;C¢digo de error 6 int 33 ;Salir a Windows noerror06 mov di,dx ;Destino mov si,outbuff+128 ;Origen mov cx,3008 ;N£mero de bytes a mover / 2 rep movsw ;Mover al comienzo del buffer popa ;Restaurar registros sub di,128 ;Retroceder puntero de escritura sub si,bp ;Y el de lectura solo si es necesario dontwrite ret namein db "ENTRADA.CMP",0 namepath db "SALIDA.ARC",0 section .bss handleout resw 1 handlein resw 1 pathbuffer resb 400 outbuff EQU 8192 outbuffend EQU outbuff+6144 inbuff EQU 16384 inbuffend EQU inbuff+32768 ;errorlevels: ; ; 0 - OK, no error ; 1 - No se puede abrir ENTRADA.CMP ; 2 - No se puede abrir SALIDA.ARC ; 3 - No se puede leer SALIDA.ARC ; 4 - Error de lectura ; 5 - No se puede crear el archivo de salida ; 6 - Error de escritura ;CODIFICACIàN: ;0 - Byte literal ; Se copia el siguiente byte. ; ;1XXXX - Repetici¢n de bloque previo. ; (XXXX de 0000 hasta 1100) - se toman XXXX bits para formar la ; distancia (poniendole un uno delante), los siguientes 3 bits forman ; YYY, y se toman YYY bits para formar la longitud (se pone un uno ; delante y se le suma 1). Si YYY=111, fin de archivo ;Rango: distancia > 1 a 8191 (se usa hasta 6016). ; longitud > 2 a 128 ; ;111YYY - Cadena de bytes literales. ; (YYY de 010 a 111) - se toman YYY bits para formar el n£mero de bytes ; que se copian directamente, poniendo uno delante y sumando 4.