如何模拟"添加eax,1"在Prolog?

时间:2014-03-23 23:34:39

标签: prolog

我正在尝试使用Prolog来模拟一些简单的asm代码。 (32位)

我是Prolog的新手,我在没有任何解决方案的情况下遇到了一些问题。

基本上如果这是代码:

...
add eax, 1
...

我希望以这种方式模拟:

...
EAX is EAX - 1,
...

和swipl会产生如下错误:

  Call: (7) 1 is 1-1 ? creep
 Fail: (7) 1 is 1-1 ? creep
 ....
 false

我基本上知道我可以这样做:

EAX_temp is EAX + 1 

但是如何在下一条指令中继续操纵EAX ..?

任何人都能给我一些帮助..?谢谢!

2 个答案:

答案 0 :(得分:2)

可能有几种好方法可以做到这一点。答案可能会进一步通过您目前尚不清楚的背景进一步完善。

一种方法是,您可以为寄存器值创建动态事实:

:- dynamic(register/2).  % Fill in as needed

register(eax, 0).
register(ebx, 0).
...

add(Reg, Value) :-
    (   retract(register(Reg, OldValue))
    ->  NewValue is OldValue + Value
    ;   NewValue = Value                % If the register wasn't defined
    ),
    assertz(register(Reg, NewValue)).

然后做:

add(eax, 4).           % add eax,4

要读取寄存器,您只需使用,例如:

register(eax, EAXValue).

assertretract的主要缺点是它们比列表操作占用了更多的CPU时间。但我认为它们对于这种应用程序是有意义的,在这种应用程序中,你有一个CPU“状态”,由几个寄存器值表示。

答案 1 :(得分:2)

“Prolog”方式是在一个术语中实际维护所有寄存器的状态,该术语通过运行模拟的主谓词传递。所以,例如:

% general-purpose registers
% regs(EAX, EBX, ECX, EDX, ESI, EDI)
regs(0, 0, 0, 0, 0, 0)

但请注意:这不是谓词(因此最后会丢失一点)!这是一个术语,它将被初始化为全零(我假设在这里):

init_regs(regs(0,0,0,0,0,0)).

因此,在程序开始时,您可以使用以下命令初始化寄存器:

main :-
    init_regs(Regs),
    step(Regs).

step(Regs) :-
    read_instruction(Instruction),
    apply_instruction(Instruction, Regs, New_regs),
    step(New_regs).

apply_instruction(add(eax, Addend),
        regs(EAX, EBX, ECX, EDX, ESI, EDI),
        regs(New_EAX, EBX, ECX, EDX, ESI, EDI)) :-
    New_EAX is EAX + Addend.

您可以将其保留在此处,或者您可以使用帮助程序谓词来访问所需的一个寄存器,例如:

reg_eax(reg(EAX, _, _, _, _, _), EAX).
reg_ebx(reg(_, EBX, _, _, _, _), EBX).
% and so on

设置寄存器:

set_reg_eax(reg(EAX, EBX, ECX, EDX, ESI, EDI),
            New_EAX,
            reg(New_EAX, EBX, ECX, EDX, ESI, EDI)).
% and so on

然后您可以使用这样来定义apply_instruction/3

apply_instruction(add(eax, Addend), Regs, New_regs) :-
    reg_eax(Regs, EAX),
    New_EAX is EAX + Addend,
    set_reg_eax(Regs, New_EAX, New_regs).

一种谓词,reg_eaxset_reg_eax可以由图书馆library(record)(参见here)自动生成,其中最初的想法由Richard o提出Keefe在他的书“The Prop of Prolog”中做了exaclty这种东西。如果使用libary,则无需自己编写所有访问权限并设置谓词。

但是,如果您使用的是SWI-Prolog,您也可以使用Dicts;见here。这是SWI-Prolog(版本7)当前开发版本的一部分,使得处理具有命名参数的结构变得更加容易。