2011-11-10 37 views
1

割り当ての一環として、行列を使ってさまざまな関数を実行することになっています。メニューの場合、 "case table"(各行に文字定数とその対応する関数のみを含む2次元配列として実装されています)NASMで「ケーステーブル」はどのように機能しますか?

私は実際にノートを理解できませんが、本はゼロヘルプです(それはまったく言及していません)

.data 
CaseTable BYTE 'A' ; lookup value 
    DWORD Process_A ; address of procedure 
    EntrySize = ($ - CaseTable) 
    BYTE 'B' 
    DWORD Process_B 
    BYTE 'C' 
    DWORD Process_C 
    BYTE 'D' 
    DWORD Process_D 

NumberOfEntries = ($ - CaseTable)/EntrySize 
…. 
segment .text 
... 
    mov ebx, CaseTable ; point EBX to the table 
    mov ecx,NumberOfEntries ; loop counter 

L1: cmp al,[ebx] ; match found? 
    jne L2 ; no: continue 
    call PTR [ebx + 1] ; yes: call the procedure 
    jmp L3 ; and exit the loop 
L2: add ebx,EntrySize ; point to next entry 
    loop L1 ; repeat until ECX = 0 

L3: 

誰かが私を助けることができますか?

+0

Cに精通しているなら、それは2D配列ではなく 'struct'であると考えるほうが役に立つかもしれません。 'struct {char lookup; function_ptr_tプロセス。 } CaseTable [] = {{A '、Process_A}、/ * ... * /}; '#define NumberOfEntries(sizeof(CaseTable)/ sizeof(CaseTable [0]))' – user786653

+0

Btw、実際には2次元アレイ。これは要素の配列であり、各要素には2つの要素があります。配列は通常、同じサイズの要素を持ちます。 "BYTE 'A'"と "DWORD Process_A"はありません。 –

答えて

5

アイデアは簡単です。あなたは十分にアセンブリ言語がわからない場合は、以下の同等のCコードを理解してみてください(私が定義するプロセスの自由を取った_ *()明確な文字を印刷し、()メインで投げるなど):

#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; 
} 

出力:

A 
B 
C 
D 

ここで唯一の問題は、$mov ebx, CaseTableのようなものです。

$ evaluates to the assembly position at the beginning of the line containing the expression; so you can code an infinite loop using JMP $.したがって

EntrySize = ($ - CaseTable)テーブルの最初のエントリの大きさを算出し、同様にNumberOfEntries = ($ - CaseTable)/EntrySize最初テーブル全体のサイズを計算した後、あなたのテーブルのエントリの数を与える一つのエントリのサイズで除算。

他のアセンブラ(MASMやTASMなど)とは異なり、NASM mov ebx, CaseTableは、CaseTableという名前のオブジェクトのアドレスをebxにロードすることを意味します。他のアセンブラでは、CaseTableという名前のオブジェクトから最初の4バイトをebxに読み込むことができます。 同様に、DWORD Process_Aは、Process_Aという名前のオブジェクトのアドレスを含むDWORDを定義します。
他のアセンブラでは、等価物はmov ebx, OFFSET CaseTableDWORD OFFSET Process_Aと書く必要があります。

残りについては、the official NASM documentationおよびIntel's/AMD's x86 CPUマニュアルを参照してください。あなたの宿題は基本的に行います。何かが明確でない場合は、の質問にお答えください。

+0

ありがとう、Cでそれを見て本当にすべての意味を作った。 私は具体的ではないことをお詫び申し上げます。私はcaseTableの割り当てを指していましたが、今はすべて明らかです。 – Rakosman

+0

問題ありません。あなたの質問に答えた答えに 'the'の答えを記入してください。そのためには、すべての答えの左側にチェックマークがあります。 –

関連する問題