2

我正在使用 Delphi pascal 进行简单的 PIC18 MCPU 助记符模拟。是的,我打算使用 Delphi IDE。我可以模拟任何 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;

//模拟MCPU ASM代码

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 回答