如果我理解正确,DCPU-16 specification 0x10c描述了一个16位地址空间,其中每个偏移地址都是一个16位字,而不是大多数其他存储器架构中的字节。这有一些奇怪的后果,例如:我想sizeof(char)
和sizeof(short)
都会返回1
。
在这些不同的内存寻址方案之间保持C代码可移植是否可行?要记住的问题是什么?
编辑:也许我应该给出一个更具体的例子。假设您有一些处理字节流的网络代码。你是通过在每个地址只放一个字节来丢弃一半的内存,这样代码就可以保持不变,或者你是否通过位移来概括所有内容来处理每个偏移的N个字节?
edit2 :答案似乎集中在数据类型大小的问题上,这不是重点 - 我甚至不应该提到它。问题是如何应对失去用指针解决内存中任何字节的能力。期望代码对此不可知是否合理?
答案 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 == 8
,sizeof(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
这将使其他所有内容过于复杂