我正在使用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;
答案 0 :(得分: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
的相对位置会发生变化,并且您最终会从堆栈中读取错误的值。