2011-12-25 5 views
1

私の宿題のために、C#で非常に小さな仮想16ビットアセンブラインタープリタを書く必要があります。 バイト配列(64k)と変数(A、B、C、...)を持つレジスタでRAMをシミュレートします。 今私はローカル変数を保存する方法が必要です、Googleはスタックに割り当てられていると言います。ASMインタープリタ:ローカル変数はどのように格納されていますか?

私には分かりませんが、スタックに(プッシュで...)割り当てられている場合、後で使用するときにインタープリタはどのようにアクセスしますか?最初の行で

pi INT 3 
mov A, pi 

、PIは2行目に、PIが使用され、スタック上に割り当てられているが、PIがスタックにある場合インタプリタが知っておくべき方法:

は、次の2行を参照しますそのデータにアクセスするには? (私のスタックがあまりにも2ヘルパー関数(プッシュ、ポップ)とバイト配列は、また、スタックの最上位へのポインタがあります)

答えて

0

通常、スタックは通常のRAMにはなく、代わりにスタックポインタだけを追跡します。また、通常、ローカル変数は、変数のためのスペースを作るためにスタックポインタを移動し、その後、別のレジスタにスタック・ポインタをコピーすることによって、サブルーチンの先頭に割り当てられている

mov bp, sp ;copy stack pointer 
sub sp, 4 ;make room for two integer variables 

をローカル変数へのアクセスが行われますスタックポインタのコピーを使用して:

mov A, [bp-2] ;get first integer 
mov B, [bp] ;get second integer 

をあなたがサブルーチンを去るとき、あなたはローカル変数を解放するスタックポインタを復元

mov sp, bp ;restore stack 
ret ;exit from subroutine 
あなたが質問に使用する構文は、通常、グローバル変数ではなく、ローカル変数を宣言するために使用されて

.data 
pi int 3 ;declare a label and allocate room for an int in the program 
.code 
mov A, pi ;use the address of the label to access the int 
+0

これは私が探していたものです。 –

0

「Googleは、彼らがスタックに割り当てられていることを述べています」

これは実際のコンピュータに実装されている方法ですが、それだけではありません。

仮想インタープリタを使用するには、「ハッシュテーブル」というデータ構造を使用する必要があります。

これは宿題に関する質問です。だから直接的な答えはありません:P しかし、次のコードは、ハッシュテーブルの使い方を説明します。変数名と値をハッシュテーブルに格納します。

using System; 
using System.Collections; 

class Program 
{ 
    static Hashtable GetHashtable() 
    { 
    // Create and return new Hashtable. 
    Hashtable hashtable = new Hashtable(); 
    hashtable.Add("Area", 1000); 
    hashtable.Add("Perimeter", 55); 
    hashtable.Add("Mortgage", 540); 
    return hashtable; 
    } 

    static void Main() 
    { 
    Hashtable hashtable = GetHashtable(); 

    // See if the Hashtable contains this key. 
    Console.WriteLine(hashtable.ContainsKey("Perimeter")); 

    // Test the Contains method. It works the same way. 
    Console.WriteLine(hashtable.Contains("Area")); 

    // Get value of Area with indexer. 
    int value = (int)hashtable["Area"]; 

    // Write the value of Area. 
    Console.WriteLine(value); 
    } 
} 
+0

私はハッシュテーブルを知っているが、我々は、このためのハイレベルの構造を使用してはならない、私はアセンブラが持つ変数を識別することを想定しましたいくつかのids(数値)または私は間違っていますか? –

+0

あなたはそうではありません。しかし、あなたが 'ids'を割り当てると、最終的には2つの配列を使ってハッシュテーブルを実装することになります。 idsを使用するには2つの方法があります。1)変数をスタックにプッシュし、1つの配列にその位置(ID)を格納し、別の配列の対応する場所に変数名を格納します。その後、スタックの更新によってこれらの場所が更新されます。これは、最終的に低レベルの構造を使用して実装されたハッシュテーブルではありませんか?第2の方法は、スタックデータ構造にいくつかの機能を追加することです。スタック構造を使用すると、内容を繰り返し、必要なものを検索することができます。 – Shaunak

0

答えは次のとおりです。言語デザイナーは、可視性(変数名が定義されている場合はソースコードの名前のうち、利用可能なものは何ですか)とが何であるかを定義する必要があります。変数の他のオブジェクトの可視領域に定義された名前。異なる言語には異なるルールがあり、JavascriptとC++を比較するだけです。

だから、私はこのようにします。 (1)という名前空間の概念を導入する:ソースファイルの特定のポイントで表示される名前のリスト。 (これはC++の名前空間概念と同じではないことに注意してください)。名前空間は、名前を適切なオブジェクトに解決できる必要があります。 (2)インタプリタがあるファイルから別のファイルへ、あるブロックから別のファイルへと変更されたときに名前空間を変更するためのルールを実装する。

これらのステップは基本的にアセンブラだけでなく、ほとんどの言語で有効です。

(私は、「スタック上の割り当て」への言及は、別のサブルーチンで各サブルーチンを処理し、そこにローカルで名前空間を再定義するという考えを意味すると考えています。プロシージャが終了します)。

1

通常、スタックデータは、CPUレジスタがあるstack pointerを通じて比較的アクセスされていますスタックに格納されている最後の要素を指します。エミュレートされたCPUのメモリへのインデックスとして考えることができます。何かをスタックにプッシュするたびに、スタックポインタは何かのサイズだけ減分され、何かが減算後のアドレスのエミュレートされたメモリに格納されます。スタックから何かをポップすると、その値はスタックポインタに格納されているアドレスから取得され、スタックポインタは何かのサイズだけインクリメントされます。これは、CPUスタックが多くの異なるCPUでどのように動作するかを示しています。

CPUエミュレータまたはCPU命令エミュレータ/インタプリタを実装している場合は、変数はあまり気にしません。あなたのプログラムがCPU命令の観点から表現されているので、CPUレジスタとメモリを操作するCPU命令が気になります。これらの命令(命令)は、スタックに格納されているすべての変数、つまりスタックポインタの現在の値に対する相対的な位置を追跡する必要があります。

たとえば、スタックに渡された2つの16ビット整数値を加算する単純なサブルーチンを考えると、次のようになります。 16ビットのx86アセンブリ:

myadd: 
    push bp ; we'll be accessing stack through bp (can't do that through sp because there's no sp-relative memory addressing in 16-bit mode), so, let's save bp first 
    mov bp, sp ; bp is equal to the stack pointer 
    mov ax, dword ptr [bp + 4] ; load ax with 1st parameter stored at bp+4 (sp+4) 
    add ax, dword ptr [bp + 6] ; add to ax 2nd parameter stored at bp+6 (sp+6) 
    pop bp ; restore bp 
    ret ; near return to the caller at address stored at sp (address after call myadd), the result/sum is in ax 

そして、発信者は次のようになります。

push word 2 ; prepare/store 2nd parameter on the stack 
    push word 1 ; prepare/store 1st parameter on the stack 
    call myadd ; near call, pushes address of next instruction (add), jumps to myadd 
    add sp, 4 ; remove myadd's parameters (1 and 2) from the stack 
    ; ax should now contain 3 
関連する問題