2

私はDelphipascalで簡単なPIC18MCPUニーモニックシミュレーションに取り組んでいます。はい、DelphiIDEを使用するつもりです。asm命令をシミュレートすることはできますが、ラベルで停止します。場合によっては、Delphiラベルのアドレスを知る必要があります。ラベルをポインター変数にキャストする可能性はありますか?

私の例のように?

procedure addlw(const n:byte); //emulation of mcpu addlw instruction
begin
  Carry := (wreg + n) >= 256;
  wreg := wreg + n;
  Zero := wreg = 0;
  inc(CpuCycles);
end;

procedure bnc(p: pointer ); //emulation of mcpu bnc instruction
asm
  inc   CpuCycles
  cmp   byte ptr Carry, 0
  jnz   @exit
  pop   eax     //restore return addres from stack
  jmp   p
@exit:
end;

//MCPUASMコードのエミュレーション

procedure Test;
label
  Top;
var
  p: pointer;
begin
//
Top:
  addlw(5);  //emulated  mcpu addlw instruction
  bnc(Top);  //emulated  mcpu bnc branch if not carry instruction
//
end;
4

1 に答える 1

5

いいえ、そのようにラベルを操作することはできません。他のすべてをエミュレートしているので、Delphiラベルに設計されていないことを強制する代わりに、アセンブララベルもエミュレートすることもできます。

作成した「アセンブラ」コードの代わりに、次のようなコードを使用できるとします(今のところ、正確に実装する方法を心配する必要はありません)。

procedure Test;
var
  Top: TAsmLabel;
begin
//
DefineLabel(Top);
  addlw(5);  //emulated  mcpu addlw instruction
  bnc(Top);  //emulated  mcpu bnc branch if not carry instruction
//
end;

構文は十分に似ていると思います。そのコードを実行するときはTop、次の命令を参照する必要があります。これは、を呼び出す命令addlwです。

仮想関数内では、そのアドレスはリターンアドレスDefineLabelに対応しているため、指定されたパラメーターにリターンアドレスを格納するように書き込みます。DefineLabel

type
  TAsmLabel = Pointer;

procedure DefineLabel(out Result: TAsmLabel);
asm
  mov ecx, [esp]  // copy return address
  mov [eax], ecx  // store result
end;

このコードはスタックを破壊することに注意してください。関数bcnはそのリターンアドレスをスタックに残すため、キャリーフラグが最終的に設定されると、以前のリターンアドレスの証跡がスタックに残されます。最初にスタックオーバーフローが発生しない場合、包含関数の最後に到達したときに奇妙な結果が発生します。戻りを試みますが、呼び出し元に行く代わりに、代わりにbncの戻りアドレスを見つけて、コードの途中に戻ります。そして、それはすべて、コード内に他のスタック相対参照がないことを前提としています。ある場合は、の相対位置が変更されるため、呼び出し でも問題が発生する可能性があり、スタックから間違った値を読み取ることになります。bnc(Top)Top

于 2012-05-24T19:06:27.770 に答える