Идея тривиальна.Если вы не знаете достаточно ассемблера, попробуйте понять следующий эквивалентный код C (я взял на себя смелость определить Process _ * () как печать отдельных букв и добавив main ()):
#include <stdio.h>
void Process_A(void)
{
printf("A\n");
}
void Process_B(void)
{
printf("B\n");
}
void Process_C(void)
{
printf("C\n");
}
void Process_D(void)
{
printf("D\n");
}
typedef struct
{
char Char;
void (*Subroutine)(void);
} CaseTableEntry;
CaseTableEntry CaseTable[] =
{
{ 'A', &Process_A }, // equivalent to "BYTE 'A'" + "DWORD Process_A"
{ 'B', &Process_B },
{ 'C', &Process_C },
{ 'D', &Process_D }
};
void Process(char Char)
{
const size_t NumberOfEntries = sizeof(CaseTable) / sizeof(CaseTableEntry);
CaseTableEntry* entry = &CaseTable[0]; // equiv to "mov ebx, CaseTable"
size_t count = NumberOfEntries; // equiv to "mov ecx, NumberOfEntries"
do
{
// "L1:" would be here
if (entry->Char == Char) // equiv to "cmp al,[ebx]" + "jne L2"
{
entry->Subroutine(); // equiv to "call PTR [ebx + 1]"
break; // equiv to "jmp L3"
}
// "L2:" would be here
entry++; // equiv to "add ebx, EntrySize"
} while (--count > 0); // equiv to "loop L1"
// "L3:" would be here
}
int main(void)
{
Process('A');
Process('B');
Process('X');
Process('C');
Process('D');
return 0;
}
Output:
A
B
C
D
Единственными проблемами здесь могут быть такие вещи, как $
и mov ebx, CaseTable
.
$ оценивает положение сборки в начале строки, содержащей выражение;так что вы можете закодировать бесконечный цикл, используя JMP $.
Следовательно, EntrySize = ($ - CaseTable)
вычисляет размер первой записи таблицы, а также NumberOfEntries = ($ - CaseTable) / EntrySize
сначала вычисляет весь размер таблицы, а затем делит его наразмер одной записи дает вам количество записей таблицы.
В отличие от других ассемблеров (например, MASM и TASM), в NASM mov ebx, CaseTable
означает загрузку в ebx адреса объекта с именем CaseTable
.В других ассемблерах это может означать чтение в ebx первых 4 байтов от объекта с именем CaseTable
.Точно так же DWORD Process_A
определяет DWORD, содержащий адрес объекта с именем Process_A
.
. В других ассемблерах эквиваленты, возможно, должны быть записаны как mov ebx, OFFSET CaseTable
и DWORD OFFSET Process_A
.
Для остальныхпожалуйста, обратитесь к своей книге, официальной документации NASM и Intel / AMD x86 CPU.Делай свою домашнюю работу, в основном.Если что-то не понятно, приходите и задавайте конкретных вопросов.