; ------------------------------------------------------------------------ ; HeavyThing x86_64 assembly language library and showcase programs ; Copyright © 2015-2018 2 Ton Digital ; Homepage: https://2ton.com.au/ ; Author: Jeff Marrison <email@example.com> ; ; This file is part of the HeavyThing library. ; ; HeavyThing is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License, or ; (at your option) any later version. ; ; HeavyThing is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License along ; with the HeavyThing library. If not, see <http://www.gnu.org/licenses/>. ; ------------------------------------------------------------------------ ; minigzip.asm: HeavyThing gzip demo ; ; with one arguments, will compress whatever filename it is passed and ; send the compressed results to stdout ; ; with two arguments, will uncompress the last argument and ; send the uncompressed results to stdout ; ; NOTE: our compression level is a compile-time constant for ; the HeavyThing library and defaults to 6, same as the real gzip ; ; first things first, include the library defaults, and the ; library main include: include '../../ht_defaults.inc' include '../../ht.inc' public _start _start: ; every HeavyThing program needs to start with a call to initialise it call ht$init cmp dword [argc], 1 je .needinputfile ; regardless of whether we are inflating or deflating, last arg must be ; our input file (noting here we could go through a lot more effort for ; argument parsing of course, but for a minigzip, simple works fine) mov rdi, [argv] call list$pop_back ; pass that straight to privmapped to get a private mmap of it mov rdi, rax xor esi, esi call privmapped$new test rax, rax jz .badinputfile ; save our privmapped object mov rbx, rax ; the HeavyThing zlib requires buffer objects for its i/o ; since we don't really need/want to read the entire file from our ; privmapped object into a separate buffer object, we'll create a ; "fake" buffer object, since we know the zlib routines do not actually ; modify the input call buffer$new ; save our buffer object mov r12, rax ; get our privmapped base and size mov rdx, [rbx+privmapped_base_ofs] mov rcx, [rbx+privmapped_size_ofs] ; save the actual buffer object for later retrieval mov r13, [rax+buffer_itself_ofs] ; now set the buffer object's goods to our privmapped object's mov [rax+buffer_itself_ofs], rdx mov [rax+buffer_length_ofs], rcx mov [rax+buffer_size_ofs], rcx ; additionally, we need an output buffer call buffer$new ; hangon to our output buffer object as well mov r14, rax ; now determine whether we are inflating or deflating cmp dword [argc], 2 jne .inflate ; otherwise, deflate it is, use the stack for our zlib_stream sub rsp, zlib_stream_size mov rdi, rsp ; zlib requires a wrap level to determine what headers if any to use ; wrap == 2 == gzip mov esi, 2 call zlib$deflateInit ; set the inbuf and outbuf mov [rsp+zlib_inbuf_ofs], r12 mov [rsp+zlib_outbuf_ofs], r14 ; do the deflate deed mov rdi, rsp mov esi, zlib_finish call zlib$deflate ; cleanup our zlib state mov rdi, rsp call zlib$deflateEnd add rsp, zlib_stream_size ; cleanup the rest and output the results jmp .allgood calign .inflate: sub rsp, zlib_stream_size mov rdi, rsp ; zlib requires a wrap level to determine what headers if any to use ; wrap == 2 == gzip mov esi, 2 call zlib$inflateInit ; set the inbuf and outbuf mov [rsp+zlib_inbuf_ofs], r12 mov [rsp+zlib_outbuf_ofs], r14 ; do the inflate deed mov rdi, rsp mov esi, zlib_finish call zlib$inflate ; cleanup our zlib state mov rdi, rsp call zlib$inflateEnd add rsp, zlib_stream_size calign .allgood: ; restore the buffer's original pointer mov [r12+buffer_itself_ofs], r13 ; cleanup the buffer and privmapped objects mov rdi, r12 call buffer$destroy mov rdi, rbx call privmapped$destroy ; all thats left is our output mov eax, syscall_write mov edi, 1 mov rsi, [r14+buffer_itself_ofs] mov rdx, [r14+buffer_length_ofs] syscall mov rdi, r14 call buffer$destroy mov eax, syscall_exit xor edi, edi syscall calign .badinputfile: mov rdi, .badinput call string$to_stderrln mov eax, syscall_exit mov edi, 1 syscall cleartext .badinput, 'unable to open input file' calign .needinputfile: mov rdi, .inputfile call string$to_stderrln mov eax, syscall_exit mov edi, 1 syscall cleartext .inputfile, 'input filename required.' ; include the global data segment: include '../../ht_data.inc'