Ada中Z80仿真器中的类型转换太多

时间:2017-05-27 10:26:14

标签: types ada z80

我在Ada做一个Z80模拟器。 我正在实施JR(Jump relative)系列,但我对我的代码不满意:

with Ada.Text_IO;

procedure main is
    type UInt16 is mod 2 ** 16;
    type UInt8  is mod 2 **  8;
    type Int8   is range -128 .. 127;

    package UInt16_IO is new Ada.Text_IO.Modular_IO (UInt16);

    function Two_Complement(N : UInt8) return Int8 is
    begin
        if N <= 127 then
            return Int8 (N);
        end if;
        return Int8 (Integer (N) - 256);
    end Two_Complement;

    -- Relative jump
    function Jr (Address : UInt16; D: UInt8) return UInt16 is
    begin
        return UInt16 (Integer (Address) + Integer (Two_Complement (D) + 2));
    end Jr;

    Address : UInt16;
begin
    Address := 16#683#;
    UInt16_IO.Put (Item => Jr (Address, 16#F1#), Base => 16); -- Get    16#676# which is good !
end main;

它似乎有效,但我发现转换的类型太多了。 你有什么建议吗?

谢谢,

奥利弗。

4 个答案:

答案 0 :(得分:6)

你可以看看

function Jr (Address : UInt16; D: UInt8) return UInt16 is
   Offset : constant Uint16
     := Uint16 (D) + (if D >= 16#80# then 16#ff00# else 0);
begin
   return Address + Offset + 2;
end Jr;

但它取决于你需要发生什么 - 例如 - 地址为0而D就是16#80(上面的代码返回16#ff82#)。

答案 1 :(得分:1)

如果两个整数类型非常密切相关,至少形成一定的观点,如果它们只在值的子集中有所不同而不是函数,则考虑子类型。

我怀疑从概念的角度来看,选择子类型可能会使问题变得模糊。所以,如果我可以推测,使用你关于那些整数的目的的知识来发展名称,如Offset(猜测)将通过传达他们的目的来增加名称的价值:他们的意思,而不仅仅是他们有多少比特,或者他们是否签名。也许这会软化类型转换的体验,因为那时参数“成为”所谓类型=概念的对象。运行时(或编译时)效果将是相同的。

在C语言中,类型别名也是XintNN_t的可能性;别名甚至可能包括int - 如果这是可取的。

答案 2 :(得分:1)

由于Ada专注于类型安全,因此以下两种类型定义不能直接兼容,如Ada编译器所示:

type UInt8 is mod 2 ** 8;
type UInt_8 is mod 2 ** 8;

这就是在同一表达式中使用类型转换时的原因。解决此问题的一种方法是定义通用类型。例如,

type Int32 is range -2 ** 31 .. 2 ** 31 - 1;

subtype UInt8 is Int32 range       0 .. 2 ** 8 - 1;
subtype  Int8 is Int32 range -2 ** 7 .. 2 ** 7 - 1;

然后您不需要这么多转换,因为编译器将使用Int32类型作为计算的基本类型。例如,return Int8 (Integer (N) - 256);过程中的语句Two_Сomplement可以简化为return Int8 (N - 256);

作为旁注,您还可以使用Interfaces库来确保类型的正确大小。此外,该库还具有便捷的操作,例如Shift_LeftShift_Right等。

答案 3 :(得分:1)

我怀疑命名的一些改动可能有助于解决问题。

你可以用这个:

Subtype Address is UInt16;

Function "+"( Location : Address; Offset: Int8 ) return Address is
  (if Offset < 0 then Location - UInt16(ABS Offset)
   else Location + UInt16(Offset) );

这将允许您将Jr重新表述为:

-- Relative jump
function Jr (Location : Address; D: UInt8) return UInt16 is
    Offset : Constant Int8 := Two_Complement(D) + 2;
begin
    return Location + Offset;
end Jr;