· Начало · Статистика · WASM.RU · Noir.Ru ·

 WASM Phorum (Оффлайн - 24.11.2003) —› WASM.A&O —› Вот и хеши пошли...

<< . 1 . 2 . 3 . 4 . 5 . >>

Посл.отвђт Сообщенiе


Дата: Авг 29, 2003 06:49:55

volodya
Теперь всё ясно. Попробую заполнить этот массив статически (раз можно на асме, можно и на С).

Слушай, а зачем тебе qsort? Массив-то можно отсортировать заранее (в самих сорсах). Кстати, CRC32 быстрее подсчитывать с помощью таблицы.

Сейчас высплюсь и завтра поизвращаюсь над C :)


Дата: Авг 29, 2003 07:58:34 · Поправил: Artem

Можно сделать все вызываемые функции такого типа:
int (*)(const void* InBuf,int InSize,void* OutBuf)
(возвращается размер записанных в OutBuf данных).
А копмилятор будет сам определять размер указателя в зависимости от платформы.


Дата: Авг 29, 2003 11:52:34

Я бы посоветовал использовать уже давно проверенные подходы к решению задач подобного типа. А именно использовать функции какого-нибудь компилятора для работы с таблицей символов.

Обычно там используют примерно такой подход. Берут некую простенькую (хеш?) функцию, которая допускает коллизии. К примеру она может просто складывать все символы в имени подпрограммы по модулю 256.
Далее для всех функций считается этот хеш и создается таблица указателей. Каждый элемент таблицы соответствует некоторому множеству функций, которые имеют данный хеш.
Указатели в таблице указывают, например на массив, который содержит имена функций с данным хешем.

Для поиска нужной функции мы считаем ее хеш. Далее, используя его в качестве индекса в таблице получаем указатель на массив, который содержит имена всех функций с данным хешем (а таких функций из 300 может быть всего 10). И далее просто просматриваем этот массив в поисках информации о нужной нам функции.

Т.е. получается, что этот хеш с коллизиями как бы делит все множество функций на небольшие подмножества, так что поиск нужного нам подмножества и конкретной функции в нем занимает гораздо меньше времени, чем перебор всех функций.

Тут все зависит от выбранной функции (она должна как можно равномернее делить множество функций на подмножества). Та, которую привел я довольно хреновая, это только иллюстрация.

Вообще, чувствую, я довольно дико все объяснил. :) Но ты почитай любую книжку по теории компиляторов, раздел, где рассматриваются таблицы символов. Кстати, я недавно тебе реквест на одну такую книгу присылал. ;)
В дракончике это точно есть. Только там напряг с конкретной реализацией будет.

Да, насчет параметров к функции ничего посоветовать не могу, т.к. я пока не понял, откуда эти параметры беруться.


Дата: Авг 29, 2003 12:57:32

IMHO, в данном случае достаточно использовать бинарный поиск имен, врядли имен будут тысячи, так что использовать хэшы не логично, а по отсортированным таблицам поиск будет очень быстрым. Беите пример с таблицы экспорта. Вот.


Дата: Авг 29, 2003 16:57:25

Если таблица соответствий функция -- адрес постоянна, то можно упортебить бинарный поиск.

Один из таких алгоритмов (кстати для XASM) у меня лежит под названием Однонаправленный древовидный словарь.
Тут так же может употреблятся хеширование.. Но я им не пользуюсь...

Структура древовидного словаря.

(Для Асма я использую её оптимизированный вариант, для С я это опускаю)

Древовидный словарь представляет собой совокупность блоков символов, где каждый блок -- это положение символа в слове.

Блоки имеют разный формат, в зависимости от назначения

Вот типичный

Формат блока - это список:

[код символа][указатель][код символа][указатель]

То есть каждому коду символа соответствует указатель на другой блок.

И так далее, пока не кончится словарь.

Теперь подробней.

Понятно, что в словаре содержится несколько слов.
Предположим, что есть несколько слов на первые "a" на "b" вторые, третие в слове...

Тогда будет несколько веток на "a" на "b"

А начале блока идёт байт флагов.
Если он = 0, то значит больше ветвлений нет, и остальные байты -- это символы, которые остались.

Если не ноль -- значит идёт ветвление и это символ.

Если == 1 значит это не ветвление а например адрес функции...

Извините, но дописывая эти строки я бегуууу.....


Дата: Авг 29, 2003 17:59:08

Ребята, спасибо, конечно вам всем за ответы. Тут же никто и не спорит. Только к компилятору привязываться никто не будет - это компиляторо-зависимо - я же говорил, код будет компилироваться минимум под 3-4 осями - а это значит cl/gcс/черт в ступе и т.д. Самое важное - НИКТО ТАК И НЕ СКАЗАЛ, что делать ПОСЛЕ того, как я нашел хеш, имя или что-то там еще. Сейчас мне реально видится только одна вещь:
hugefunction(char *func_name)
{
   switch(strCRC(func_name))
   {
       case(12345)
            do_this();
            break;
       case(45769)
            do_that();
            break;
       //и т.д.
   }
}


Я не скажу, ни что это элегантно, ни действительно быстро, но это будет работать под любой осью и что бы там функция не вернула - список, массив, int, указатель на char, опять таки, черта в ступе...
Разумеется, вариант с массивом, который отсортирован и бинарным поиском в нем звучит классно, но как туда положить адрес функции - это пытался сделать только Quantum, да и то...


Дата: Авг 29, 2003 18:00:49

Sten

Да, написано диковато, если честно. Общую канву можно ухватить только после того, как почитал статью на RSDN по хещированию и применению хеша в качестве индекса. А потом выстраиваются односвязанные списки, да... Тут представляю... Но ЧТО мне хранить в тех списках...


Дата: Авг 29, 2003 21:28:17

volodya
Может я что-то не так понял, но нельзя ли сделать так,
За именами функций закрепить номер и
Получаем имя функции определяем ее номер суем в eax и делаем так:
        call dword ptr func_name[eax*4]
        jmp ....

func_name dd offset func1, offset func2
          dd offset funk3, offset func4


Дата: Авг 29, 2003 21:58:59

KiNDeR

Оптимизирующий компилятор под Intel-архитектуру даст тебе точно такой же код для switch/case. И это будет платформенно-независимо. Правда, если честно, я не знаю, будет ли что-то похожее под солярисовским асмом - там же RISC :(


Дата: Авг 29, 2003 22:09:13

volodya
Ну тады извеняй, что то ближе к сентябрю я за собой замечаю, что начинаю притормаживать...


Дата: Авг 29, 2003 22:42:38

KiNDeR
Да за что извинятся! Ты помочь хотел. Наоборот, спасибо!


Дата: Авг 29, 2003 22:43:53

volodya
:-)


Дата: Авг 29, 2003 23:00:19

volodya
но как туда положить адрес функции - это пытался сделать только Quantum, да и то...
Сорри, только что с работы вернулся :) Так вот:
#include <stdio.h>
// Define all protos:
void f0(char*);  // 'f' + '0' = 102 + 48 = 150
void f1(char*);  // 151
void f2(char*);  // 152
void f3(char*);  // 153
void f4(char*);  // 154
void f5(char*);  // 155
void f6(char*);  // 156
void f7(char*);  // 157
void f8(char*);  // 158
void f9(char*);  // 159
void call(char*);

typedef void function (char*);

struct token{
   int hash;
   function *address;
};

token hashtable[] = {
   {150,f0},{151,f1},{152,f2},{153,f3},{154,f4},
   {155,f5},{156,f6},{157,f7},{158,f8},{159,f9},
   {0,0} // <- GND
};

// calculate checksum and call corresponding function
void call(char* name){
   int checksum = 0;
   // calculate checksum
   while(*name) checksum += *(name++);
   // parse hashtable
   for(token *cursor = hashtable; cursor->hash; cursor++)
       if(cursor->hash == checksum)
           // finally call that function
           cursor->address("test");
}

int main(int argc, char* argv[]){
   call("f0");
   call("f9");
   call("f5");
   return 0;
}

void f0(char* param){ printf("f0: %s\n", param); }
void f1(char* param){ printf("f1: %s\n", param); }
void f2(char* param){ printf("f2: %s\n", param); }
void f3(char* param){ printf("f3: %s\n", param); }
void f4(char* param){ printf("f4: %s\n", param); }
void f5(char* param){ printf("f5: %s\n", param); }
void f6(char* param){ printf("f6: %s\n", param); }
void f7(char* param){ printf("f7: %s\n", param); }
void f8(char* param){ printf("f8: %s\n", param); }
void f9(char* param){ printf("f9: %s\n", param); }

Я тут использовал тупой парсинг всего массива, но организовать бинарный поиск не составит особого труда (у тебя, наверное, уже есть готовый код). Ну, и CRC я поменял на обычную сумму... спешил :)


Дата: Авг 30, 2003 00:01:47 · Поправил: volodya

Quantum

Сперва нескомпилилось. Ща поправил и разбираюсь.

typedef void function (char*); - ну и? Функция может быть только void? А если нет? А если и char * она не будет принимать, а, скажем, int? Или что-то вроде ValNodePtr?

В общем и в частности, насколько я догоняю. Проблема не может быть решена для общего случая на С, лишь для частных случаев. На С++ - возможно, я пока еще там плаваю. Может что-то вроде шаблона... Не знаю... На асме - понятное дело.

Так что остается: switch/case с хорошей hash-функций БЕЗ коллизий, вероятно, CRC32 со строки на С.


Дата: Авг 30, 2003 00:28:18

http://www.function-pointer.org/ - турториал по указателям на функции. Нельзя объявить указатель хрен знает на что. Поэтому switch/case - это единственное, что можно предложить, вероятно. Вот и усе :((((

<< . 1 . 2 . 3 . 4 . 5 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.081