2011-11-10 79 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

没有问题。请将回答您的问题的答案标记为“答案”。为此,每个答案的左侧都有一个复选标记。 –