2011-11-10 34 views
1

作爲我們任務的一部分,我們應該用矩陣做各種功能。對於菜單,我們被分配使用「案例表」(它是作爲一個二維陣列實現的,每行只包含一個字母常量及其相應的功能)「案例表」如何在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可能是想起來更有幫助是'struct'而不是一個二維數組。 'struct {char lookup; function_ptr_t進程; } CaseTable [] = {{'A',Process_A},/ * ... * /};''#define NumberOfEntries(sizeof(CaseTable)/ sizeof(CaseTable [0]))' – user786653

+0

順便說一句,二維數組。它是一組元素,每個元素都有它自己的兩個元素。數組通常具有相同大小的元素。 「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中意味着將加載到ebx中的名稱爲CaseTable的對象的地址。在其他彙編程序中,這可能意味着從名爲CaseTable的對象的前四個字節讀入ebx。 同樣,DWORD Process_A定義了一個DWORD,其中包含名爲Process_A的對象的地址。
在其他組裝商中,等效物可能需要寫成mov ebx, OFFSET CaseTableDWORD OFFSET Process_A

其餘的,請參考您的書,the official NASM documentationIntel's/AMD's x86 CPU手冊。基本上做你的功課。如果有什麼不清楚的地方,請問具體的問題。

+0

非常感謝,在C中看到它確實讓所有人感覺到了。 我很抱歉沒有具體;我指的是caseTable的分配,但現在已經很清楚了。 – Rakosman

+0

沒有問題。請將回答您的問題的答案標記爲「答案」。爲此,每個答案的左側都有一個複選標記。 –