From 4d13f37091c488ca4ecfcf9c4d7145301be55d78 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sat, 3 Aug 2024 13:12:30 +0800 Subject: [PATCH] First draft of construct tree (infinite loop bug for now) --- src/bss/huffman.asm | 6 ++ src/data/huffman.asm | 16 +++ src/huffman/construct_tree.asm | 174 ++++++++++++++++++++++++++++++ src/logger.asm | 7 +- tests/huffman_decompress_test.asm | 1 + 5 files changed, 203 insertions(+), 1 deletion(-) diff --git a/src/bss/huffman.asm b/src/bss/huffman.asm index c848d61..3413219 100644 --- a/src/bss/huffman.asm +++ b/src/bss/huffman.asm @@ -1,6 +1,12 @@ ; m_aNodes array of CNODE structs huff_nodes resb HUFF_CNODE_SIZE * HUFFMAN_MAX_NODES +; aNodesLeftStorage[HUFFMAN_MAX_SYMBOLS]; +huff_nodes_left_storage resb HUFF_CNODE_SIZE * HUFFMAN_MAX_SYMBOLS + +; *apNodesLeft[HUFFMAN_MAX_SYMBOLS]; +huff_nodes_left resb 4 * HUFFMAN_MAX_SYMBOLS + ; m_apDecodeLut array of CNODE structs huff_decode_lut resb HUFFMAN_LUTSIZE * 8 diff --git a/src/data/huffman.asm b/src/data/huffman.asm index 7eb6505..250b742 100644 --- a/src/data/huffman.asm +++ b/src/data/huffman.asm @@ -33,3 +33,19 @@ HUFF_CCONSTRUCTION_NODE_NODE_ID_OFFSET equ 0 HUFF_CCONSTRUCTION_NODE_FREQUENCY_OFFSET equ 2 HUFF_CCONSTRUCTION_NODE_SIZE equ 6 +HUFF_FREQ_TABLE dd 1073741824,4545,2657,431,1950,919,444,482,2244,617,838,542,715,1814,304,240,754,212,647,186, \ + 283,131,146,166,543,164,167,136,179,859,363,113,157,154,204,108,137,180,202,176, \ + 872,404,168,134,151,111,113,109,120,126,129,100,41,20,16,22,18,18,17,19, \ + 16,37,13,21,362,166,99,78,95,88,81,70,83,284,91,187,77,68,52,68, \ + 59,66,61,638,71,157,50,46,69,43,11,24,13,19,10,12,12,20,14,9, \ + 20,20,10,10,15,15,12,12,7,19,15,14,13,18,35,19,17,14,8,5, \ + 15,17,9,15,14,18,8,10,2173,134,157,68,188,60,170,60,194,62,175,71, \ + 148,67,167,78,211,67,156,69,1674,90,174,53,147,89,181,51,174,63,163,80, \ + 167,94,128,122,223,153,218,77,200,110,190,73,174,69,145,66,277,143,141,60, \ + 136,53,180,57,142,57,158,61,166,112,152,92,26,22,21,28,20,26,30,21, \ + 32,27,20,17,23,21,30,22,22,21,27,25,17,27,23,18,39,26,15,21, \ + 12,18,18,27,20,18,15,19,11,17,33,12,18,15,19,18,16,26,17,18, \ + 9,10,25,22,22,17,20,16,6,16,15,20,14,18,24,335,1517 +HUFF_FREQ_TABLE_SIZE equ ($ - HUFF_FREQ_TABLE) / 4 +; print_int32_array HUFF_FREQ_TABLE, HUFF_FREQ_TABLE_SIZE + diff --git a/src/huffman/construct_tree.asm b/src/huffman/construct_tree.asm index a5e6dd7..beb77d6 100644 --- a/src/huffman/construct_tree.asm +++ b/src/huffman/construct_tree.asm @@ -11,5 +11,179 @@ ; huff_num_nodes resb 4 _huff_construct_tree: + push_registers + mov rbp, rsp + + sub rsp, 4 + ; int NumNodesLeft = HUFFMAN_MAX_SYMBOLS + mov dword [rbp-4], HUFFMAN_MAX_SYMBOLS + + mov rcx, 0 + ; for(int i = 0; i < HUFFMAN_MAX_SYMBOLS; i++) +._huff_construct_tree_for_loop: + cmp rcx, HUFFMAN_MAX_SYMBOLS + jge ._huff_construct_tree_for_loop_end + + mov rbx, rcx + imul rbx, HUFF_CNODE_SIZE + ; m_aNodes[i].m_NumBits = 0xFFFFFFFF; + mov dword [huff_nodes + rbx + HUFF_CNODE_NUM_BITS_OFFSET], 0xFFFF_FFFF + ; m_aNodes[i].m_Symbol = i; + mov byte [huff_nodes + rbx + HUFF_CNODE_SYMBOL_OFFSET], cl + mov word [huff_nodes + rbx + HUFF_CNODE_LEAF_0_OFFSET], 0xffff + mov word [huff_nodes + rbx + HUFF_CNODE_LEAF_1_OFFSET], 0xffff + + ; get i offset into aNodesLeftStorage[i] + mov rbx, rcx + imul rbx, HUFF_CCONSTRUCTION_NODE_SIZE + + ; if(i == HUFFMAN_EOF_SYMBOL) + cmp rcx, HUFFMAN_EOF_SYMBOL + jne ._huff_construct_tree_i_not_eof + mov dword [huff_nodes_left_storage + rbx + HUFF_CCONSTRUCTION_NODE_FREQUENCY_OFFSET], 1 + jmp ._huff_construct_tree_for_loop_if_end +._huff_construct_tree_i_not_eof: + ; eax = pFrequencies[i] + ; r9 = i + mov r9, rcx + ; 4 is the size of int / unsigned int + ; which is the element size in the freq table array + imul r9, 4 + mov rax, 0 + mov eax, [HUFF_FREQ_TABLE + r9] + mov dword [huff_nodes_left_storage + rbx + HUFF_CCONSTRUCTION_NODE_FREQUENCY_OFFSET], eax +._huff_construct_tree_for_loop_if_end: + + ; aNodesLeftStorage[i].m_NodeId = i; + ; rbx is still the correct [i] offset + mov word [huff_nodes_left_storage + rbx + HUFF_CCONSTRUCTION_NODE_NODE_ID_OFFSET], cx + + ; rax = &aNodesLeftStorage[i]; + lea rax, [huff_nodes_left_storage + rbx] + + mov rbx, rcx + ; 8 is the size of a pointer on 64 bit machines + ; huff_nodes_left is an array of pointers + imul rbx, 8 + mov qword [huff_nodes_left + rbx], rax + + inc rcx + jmp ._huff_construct_tree_for_loop +._huff_construct_tree_for_loop_end: + + ; m_NumNodes = HUFFMAN_MAX_SYMBOLS; + mov dword [huff_num_nodes], HUFFMAN_MAX_SYMBOLS + + ; while(NumNodesLeft > 1) +._huff_construct_tree_while_loop: + cmp dword [rbp-4], 1 + jle ._huff_construct_tree_while_loop_end + + ; rax = **ppList + mov rax, huff_nodes_left + ; rdi = Size + ; rbp-4 is NumNodesLeft + mov rdi, 0 + mov edi, [rbp-4] + call _huff_bubble_sort + + ; m_aNodes[m_NumNodes].m_NumBits = 0; + mov rbx, [rbp-4] + imul rbx, HUFF_CNODE_SIZE + mov dword [huff_nodes + rbx + HUFF_CNODE_NUM_BITS_OFFSET], 0 + + ; r9 is the offset NumNodesLeft into apNodesLeft + mov r9, 0 + mov r9d, [rbp-4] + ; apNodesLeft is an array of pointers + ; so the offset is 8 (pointer size) + imul r9, 8 + + ; m_aNodes[m_NumNodes].m_aLeafs[0] = apNodesLeft[NumNodesLeft-1]->m_NodeId; + ; rax = apNodesLeft[NumNodesLeft-1]->m_NodeId; + ; NumNodesLeft - 1 + mov rsi, [huff_nodes_left + r9 - (1 * 8)] ; get pointer from array + ; get 2 byte field from struct at dereferenced value + ; ax = unsigned int NodeId + mov rax, 0 + mov ax, [rsi + HUFF_CCONSTRUCTION_NODE_NODE_ID_OFFSET] + mov word [huff_nodes + rbx + HUFF_CNODE_LEAF_0_OFFSET], ax + + ; m_aNodes[m_NumNodes].m_aLeafs[1] = apNodesLeft[NumNodesLeft-2]->m_NodeId; + ; rax = apNodesLeft[NumNodesLeft-2]->m_NodeId; + ; NumNodesLeft - 2 + mov rsi, [huff_nodes_left + r9 - (2 * 8)] ; get pointer from array + ; get 2 byte field from struct at dereferenced value + ; ax = unsigned int NodeId + mov rax, 0 + mov ax, [rsi + HUFF_CCONSTRUCTION_NODE_NODE_ID_OFFSET] + mov word [huff_nodes + rbx + HUFF_CNODE_LEAF_1_OFFSET], ax + + ; apNodesLeft[NumNodesLeft-2]->m_NodeId = m_NumNodes; + mov rax, [huff_nodes_left + r9 - (2 * 8)] ; get pointer from array + add rax, HUFF_CCONSTRUCTION_NODE_NODE_ID_OFFSET ; ->m_NodeId + mov si, [huff_num_nodes] + mov word [rax], si + + + ; apNodesLeft[NumNodesLeft-2]->m_Frequency = apNodesLeft[NumNodesLeft-1]->m_Frequency + apNodesLeft[NumNodesLeft-2]->m_Frequency; + + ; r10 = apNodesLeft[NumNodesLeft-1]->m_Frequency + ; NumNodesLeft - 1 + mov rax, [huff_nodes_left + r9 - (1 * 8)] ; get pointer from array + ; get 4 byte field from struct at dereferenced value + ; r10d = int m_Frequency + mov r10, 0 + mov r10d, [rax + HUFF_CCONSTRUCTION_NODE_NODE_ID_OFFSET] + + ; r11 = apNodesLeft[NumNodesLeft-2]->m_Frequency + ; NumNodesLeft - 2 + mov rax, [huff_nodes_left + r9 - (2 * 8)] ; get pointer from array + ; get 4 byte field from struct at dereferenced value + ; r10d = int m_Frequency + mov r11, 0 + mov r11d, [rax + HUFF_CCONSTRUCTION_NODE_NODE_ID_OFFSET] + + ; apNodesLeft[NumNodesLeft-1]->m_Frequency + apNodesLeft[NumNodesLeft-2]->m_Frequency; + add r10, r11 + + ; apNodesLeft[NumNodesLeft-2]->m_Frequency = r10 + mov rax, [huff_nodes_left + r9 - (2 * 8)] ; get pointer from array + add rax, HUFF_CCONSTRUCTION_NODE_FREQUENCY_OFFSET ; ->m_Frequency + mov dword [rax], r10d + + ; m_NumNodes++ + mov rax, 0 + mov eax, [huff_num_nodes] + inc eax + mov [huff_num_nodes], eax + + ; NumNodesLeft-- + dec dword [rbp-4] + + jmp ._huff_construct_tree_while_loop +._huff_construct_tree_while_loop_end: + + ; ebx = m_NumNodes - 1 + mov rbx, 0 + mov ebx, [huff_num_nodes] + dec ebx + + ; rax = &m_aNodes[m_NumNodes-1] + imul ebx, HUFF_CNODE_SIZE + lea rax, [huff_nodes + ebx] + ; m_pStartNode = &m_aNodes[m_NumNodes-1]; + mov qword [huff_start_node], rax + + ; rax = *pNode (still set) + ; rdi = int Bits + mov rdi, 0 + ; rsi = unsigned Depth + mov rsi, 0 + call _huff_setbits_r + + + mov rsp, rbp + pop_registers ret diff --git a/src/logger.asm b/src/logger.asm index 3c7fc12..f1f44e2 100644 --- a/src/logger.asm +++ b/src/logger.asm @@ -75,7 +75,7 @@ print_any_int: sub rsp, 16 ; buffer - mov [rbp-16], %1 + mov qword [rbp-16], %1 ; this matches so the pointer move worked fine ; mov rax, [rbp-14] @@ -121,6 +121,11 @@ print_any_int: pop_registers %endmacro +%macro print_int32_array 2 + ; print_int32_array [array buffer] [array size] + print_int_array %1, 4, %2 +%endmacro + print_newline: push_registers diff --git a/tests/huffman_decompress_test.asm b/tests/huffman_decompress_test.asm index 2f97410..0d95ef5 100644 --- a/tests/huffman_decompress_test.asm +++ b/tests/huffman_decompress_test.asm @@ -1,5 +1,6 @@ %include "tests/assert.asm" _start: + ; call _huff_construct_tree exit 0