用于不同存储器寻址方案的C代码的可移植性

时间:2012-04-11 14:39:15

标签: c dcpu-16

如果我理解正确,DCPU-16 specification 0x10c描述了一个16位地址空间,其中每个偏移地址都是一个16位字,而不是大多数其他存储器架构中的字节。这有一些奇怪的后果,例如:我想sizeof(char)sizeof(short)都会返回1

在这些不同的内存寻址方案之间保持C代码可移植是否可行?要记住的问题是什么?

编辑:也许我应该给出一个更具体的例子。假设您有一些处理字节流的网络代码。你是通过在每个地址只放一个字节来丢弃一半的内存,这样代码就可以保持不变,或者你是否通过位移来概括所有内容来处理每个偏移的N个字节?

edit2 :答案似乎集中在数据类型大小的问题上,这不是重点 - 我甚至不应该提到它。问题是如何应对失去用指针解决内存中任何字节的能力。期望代码对此不可知是否合理?

4 个答案:

答案 0 :(得分:9)

这完全可行。粗略地说,C的基本整数数据类型具有坚持的大小:

sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long)

上述内容并不完全符合规范,但它很接近。

正如awoodland在评论中指出的那样,你也期望DCPU-16的C编译器有CHAR_BIT == 16

不假设DCPU-16会sizeof (char) == 2,这是一个常见的谬误。

答案 1 :(得分:6)

当你说'失去解决字节的能力'时,我认为你的意思是'bit-octet',而不是'char'。可移植代码应该只假设CHAR_BIT >= 8。实际上,没有字节寻址的体系结构通常会定义CHAR_BIT == 8,并让编译器生成访问该字节的指令。

我实际上不同意建议的答案:CHAR_BIT == 16是一个不错的选择。我更喜欢:CHAR_BIT == 8sizeof(short) == 2。在这种情况下,编译器可以处理移位/屏蔽,就像许多RISC架构一样,用于字节访问。

我想Notch会进一步修改和澄清DCPU-16规范;已经有对中断机制和进一步指令的请求。这是游戏的美学背景,所以我怀疑很快会有官方的ABI规范。那就是说,某人将继续努力!

修改

考虑C中的char数组。编译器在DCPU内存的每个本机16位word中打包2个字节。因此,如果我们访问第10个元素(索引9),则获取单词#[9/2] = 4,并提取字节#[9%2] = 1.

让'X'成为数组的起始地址,'I'是索引:

SET J, I
SHR J, 1    ; J = I / 2
ADD J, X    ; J holds word address
SET A, [J]  ; A holds word
AND I, 0x1  ; I = I % 2 {0 or 1}
MUL I, 8    ; I = {0 or 8} ; could use: SHL I, 3
SHR A, I    ; right shift by I bits for hi or lo byte.

寄存器A保存'byte' - 它是一个16位寄存器,因此可以忽略上半部分。 或者,上半部分可以归零:

AND A, 0xff ; mask lo byte.

这不是优化的,但它传达了这个想法。

答案 2 :(得分:0)

平等就像这样:

1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)

short类型可以是1,事实上您甚至可能希望int类型实际上1(我没有' t读取规范,但我假设正常数据类型是16位)。这个东西是由编译器定义的。

实际上,编译器可能希望将long设置为大于int的值,即使它需要编译器做一些额外的工作(比如在软件中实现加法/乘法等)。

这不是内存寻址问题,而是粒度问题。

答案 3 :(得分:0)

是的,完全可以移植C代码

在数据传输方面,建议打包(或使用压缩)或发送16位字节

因为CPU几乎完全只与(游戏)内部设备通信,这些内部设备很可能全部都是16位,这应该不是真正的问题

BTW我同意CHAR_BIT应为16(IIRC),每个字符必须是可寻址的,因此CHAR_BIT ==8将要求sizeof(char*) ==2这将使其他所有内容过于复杂