Jump to content
Tuts 4 You

HashTable Library for MASM32


diablo2oo2

Recommended Posts

I was missing a comfortable way to manage complex data structures in MASM.

Java coders will know the HashTable class, which is very useful to store data.

i coded something similar with more functions for MASM and other programming languages.

features:

-it will organize memory itself (will use the windows Heap functions)

-like in java you can access items via a key which can be a String or an integer

-support for nested hashtables (so you can create very easy complex data trees)

-save/load the hashtable to disk or memory (with nested hashtables)

the example will show how to create following hashtable structure:


; ht_1
; |
; +-0-->"hello 1"
; +-1-->"hello 2"
; +-2-->"hello 3"
; +-"string key"-->"hello 4"
; |
; +-"ht_2"--->ht_2
; |
; +-0-->"i am in the second hashtable"
; +-123->binary_data

hashtable.zip

Edited by diablo2oo2
  • Like 1
Link to comment

Congratulations on reinventing the wheel I guess whistling.gif

hehe, sure its nothing new. but i really missed this feature when i was cooding with MASM. so now you i have a library to save very easy project data structures.

Link to comment

Nice.

With adding binary data, do we need to check the size of binary data when retrieving, or does your library return size when getting the data?

Link to comment

i have to admit its not a real hashtable, but its still useful.

With adding binary data, do we need to check the size of binary data when retrieving, or does your library return size when getting the data?

there are two functions to get the data from the table.


;this one copy the data to a destination buffer and returns the size
ht_copy_item_data proc public uses ebx _ht,_key,_options,_dest fn ht_get_item,_ht,_key,_options
.if eax
mov ebx,eax .if [ebx].HT_ITEM.i_options & ITEM_DWORD
mov edx,_dest
m2m [edx],[ebx].HT_ITEM.i_data
.else
fn RtlMoveMemory,_dest,[ebx].HT_ITEM.i_data,[ebx].HT_ITEM.i_size
.endif mov eax,[ebx].HT_ITEM.i_size ;return size
.endif
ret
ht_copy_item_data endp;and this one just returns a pointer to the data,which is stored in the table
;if the data is just a dword value (it will return directly the value and not a pointer)
ht_get_item_data proc public uses ebx _ht,_key,_options fn ht_get_item,_ht,_key,_options
.if eax
mov ebx,eax
mov eax,[ebx].HT_ITEM.i_data .endif
ret
ht_get_item_data endp
Edited by diablo2oo2
Link to comment

Brilliant biggrin.png

Any chance of a C header?

hmm , can do it, but i cant promise that it works. i think your c is better than mine.

i would like to translate. but how to handle different returntypes and function parameters? i know in java its possible, but i have no idea about c.

Edited by diablo2oo2
Link to comment

so far the header.

/* NOT WORKING ! NOT FINISHED !
* to do:
* handle different return types & parameters
*/#define ITEM_STRING_KEY 1HANDLE __stdcall ht_create();
void __stdcall ht_close(HANDLE);
void __stdcall ht_close_all(HANDLE);
HANDLE __stdcall ht_clone(HANDLE);
DWORD __stdcall ht_size(HANDLE);void __stdcall ht_put(HANDLE,DWORD,LPBYTE,DWORD,DWORD);
void __stdcall ht_put_string(HANDLE,DWORD,LPSTR,DWORD);
void __stdcall ht_put_dword(HANDLE,DWORD,DWORD,DWORD);
void __stdcall ht_put_hashtable(HANDLE,DWORD,HANDLE,DWORD);
void* __stdcall ht_get_item_data(HANDLE,DWORD,DWORD);
DWORD __stdcall ht_get_item_size(HANDLE,DWORD,DWORD);
DWORD __stdcall ht_copy_item_data(HANDLE,DWORD,DWORD,LPBYTE);
void __stdcall ht_remove(HANDLE,DWORD,DWORD);
void* __stdcall ht_memorydump_create(HANDLE,LPDWORD);
void __stdcall ht_memorydump_close(HANDLE);
HANDLE __stdcall ht_create_from_memorydump(LPVOID);
DWORD __stdcall ht_write_to_file(HANDLE,LPSTR);
HANDLE __stdcall ht_read_from_file(LPSTR);

not sure how to define the functions for different parameters:

ht_put(table_1,123,data,datasize,NULL);

or

ht_put(table_1,"123",data,datasize,ITEM_STRING_KEY);

here you can use DWORD or a String for the second parameter!

Link to comment
  • 2 weeks later...

Something like this should help you out diablo, this is how I would convert your inc to C/C++


typedef struct _MD5_CHECKSUM {
DWORD dword_1;
DWORD dword_2;
DWORD dword_3;
DWORD dword_4;
} MD5_CHECKSUM, *LPMD5_CHECKSUM;typedef struct _HT_HEADER {
DWORD ht_head_sig_1;
DWORD ht_head_sig_2;
DWORD ht_heap;
DWORD ht_items;
DWORD ht_itemcount;
DWORD ht_itemsize;
DWORD ht_compareto;
MD5_CHECKSUM ht_las_md5;
} HT_HEADER, *LPHT_HEADER;HT_HEADER* __stdcall ht_create( void );
void __stdcall ht_close( HT_HEADER* );
void __stdcall ht_close_all( HT_HEADER* );

That's just for the first few calls, but from there it should be easy to figure out the rest. I tested these functions and they worked properly for me using my method posted here. :)

Link to comment

Something like this should help you out diablo, this is how I would convert your inc to C/C++


typedef struct _MD5_CHECKSUM {
DWORD dword_1;
DWORD dword_2;
DWORD dword_3;
DWORD dword_4;
} MD5_CHECKSUM, *LPMD5_CHECKSUM;typedef struct _HT_HEADER {
DWORD ht_head_sig_1;
DWORD ht_head_sig_2;
DWORD ht_heap;
DWORD ht_items;
DWORD ht_itemcount;
DWORD ht_itemsize;
DWORD ht_compareto;
MD5_CHECKSUM ht_las_md5;
} HT_HEADER, *LPHT_HEADER;HT_HEADER* __stdcall ht_create( void );
void __stdcall ht_close( HT_HEADER* );
void __stdcall ht_close_all( HT_HEADER* );

That's just for the first few calls, but from there it should be easy to figure out the rest. I tested these functions and they worked properly for me using my method posted here. smile.png

but the HT_HEADER structure is not public, so just define it as HANDLE is enough.

Link to comment

Just a heads up, the build lib/dll don't export ht_close_all, it's missing from the .def file.

Here's a full C/C++ header finished and tested:

#ifndef __HASHTABLE_H_INCLUDED__
#define __HASHTABLE_H_INCLUDED__#pragma comment( lib, "hashtable.lib" )
#include <Windows.h>#define ITEM_STRING_KEY 1
#define ITEM_DWORD 2
#define ITEM_HASHTABLE 4
#define ITEM_MD5_KEY 8
#define ITEM_DATA_POINT 16#ifdef USE_HASH_STRUCTURES typedef struct _MD5_CHECKSUM {
DWORD dword_1;
DWORD dword_2;
DWORD dword_3;
DWORD dword_4;
} MD5_CHECKSUM, *LPMD5_CHECKSUM; typedef struct _HT_HEADER {
DWORD ht_head_sig_1;
DWORD ht_head_sig_2;
DWORD ht_heap;
DWORD ht_items;
DWORD ht_itemcount;
DWORD ht_itemsize;
DWORD ht_compareto;
MD5_CHECKSUM ht_las_md5;
} HT_HEADER, *LPHT_HEADER; #define HASHHANDLE HT_HEADER*#else #define HASHHANDLE HANDLE#endifHASHHANDLE __stdcall ht_create( void );
void __stdcall ht_close( HASHHANDLE );
void __stdcall ht_close_all( HASHHANDLE );HASHHANDLE __stdcall ht_clone( HASHHANDLE );
DWORD __stdcall ht_size( HASHHANDLE );void __stdcall ht_put( HASHHANDLE, DWORD, LPVOID, DWORD, DWORD );
void __stdcall ht_put_string( HASHHANDLE, LPVOID, const char*, DWORD );
void __stdcall ht_put_dword( HASHHANDLE, DWORD, DWORD, DWORD );
void __stdcall ht_put_hashtable( HASHHANDLE, const char*, HASHHANDLE, DWORD );LPVOID __stdcall ht_get_item_data( HASHHANDLE, LPVOID, DWORD );
void __stdcall ht_get_item_size( HASHHANDLE, LPVOID, DWORD );
void __stdcall ht_copy_item_data( HASHHANDLE, DWORD, DWORD, LPVOID );LPVOID __stdcall ht_memorydump_create( HASHHANDLE, DWORD );
void __stdcall ht_memorydump_close( LPVOID );
void __stdcall ht_create_from_memorydump( LPVOID );void __stdcall ht_write_to_file( HASHHANDLE, const char* );
HASHHANDLE __stdcall ht_read_from_file( const char* );#endif // __HASHTABLE_H_INCLUDED__

Example converted to C:

// This is optional, to use the actual structures
// for debugging purposes..
#define USE_HASH_STRUCTURES#include <Windows.h>
#include <stdio.h>
#include "hashtable.h"BYTE btBinaryData[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };int __cdecl main( int argc, char* argv[] )
{
HASHHANDLE ht_1;
HASHHANDLE ht_2;
LPVOID lpData; ht_1 = ht_create();
ht_2 = ht_create(); printf( "creating a hashtable and saving to file..\r\n" ); ht_put_string( ht_1, (LPVOID) 0, "hello 1", NULL );
ht_put_string( ht_1, (LPVOID) 1, "hello 2", NULL );
ht_put_string( ht_1, (LPVOID) 2, "hello 3", NULL );
ht_put_string( ht_1, "string key", "hello 4", ITEM_STRING_KEY ); ht_put_hashtable( ht_1, "ht_2", ht_2, ITEM_STRING_KEY ); ht_put_string( ht_2, (LPVOID) 0, "i am in the second hashtable", NULL );
ht_put( ht_2, 123, &btBinaryData, sizeof( btBinaryData ), NULL ); ht_write_to_file( ht_1, "file.bin" ); ht_close( ht_1 );
ht_close( ht_2 );
printf( "opening hashtable from saved file..\r\n" ); ht_1 = ht_read_from_file( "file.bin" ); lpData = ht_get_item_data( ht_1, (LPVOID) 0, NULL );
printf( (const char*) lpData );
printf( "\r\n" ); lpData = ht_get_item_data( ht_1, (LPVOID) 1, NULL );
printf( (const char*) lpData );
printf( "\r\n" ); lpData = ht_get_item_data( ht_1, (LPVOID) 2, NULL );
printf( (const char*) lpData );
printf( "\r\n" ); lpData = ht_get_item_data( ht_1, "string key", ITEM_STRING_KEY );
printf( (const char*) lpData );
printf( "\r\n" ); ht_2 = ht_get_item_data( ht_1, "ht_2", ITEM_STRING_KEY ); lpData = ht_get_item_data( ht_2, (LPVOID) 0, NULL );
printf( (const char*) lpData );
printf( "\r\n" ); lpData = ht_get_item_data( ht_2, (LPVOID) 123, NULL );
printf( (const char*) lpData );
printf( "\r\n" ); //ht_close_all( ht_1 ); // This wont work at the moment since the lib doesn't export it. return 0;
}
Edited by atom0s
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...