2

当使用大型数组时,能够将数组调整为每个数字的特定字节数会很好。大多数情况下,我希望快速例程将这些调整后的多字节数读取为堆栈上的单曲,反之,将单曲存储在针对特定字节数调整的数组中。在 64 位系统中,除了 1 个字节 (c@c!) 和 8 个字节 (@!) 之外,还需要其他单个数字数组。

那么如何实现

cs@ ( ad b -- n )
cs! ( n ad b -- )

其中 b 是字节数。cs这个词!似乎工作

: cs! ( n ad b -- )  >r sp@ cell+ swap r> cmove drop ;

但是 cs@ 以及如何在没有 sp@ 或类似词的纯 ANS Forth 中做到这一点呢?

4

3 回答 3

2

Forth200*x* 委员会花费了相当长的时间来开发一个适合的内存访问字集。由于它的大小,到目前为止我们还没有将它包含在标准中。

于 2016-03-01T16:54:39.943 回答
1
\ little-endian (eg. pc, android)
: mb! ( n ad i -- )  2>r here ! here 2r> cmove ;
: mb@ ( ad i -- n )  here 0 over ! swap cmove here @ ;

\ big-endian (eg. mac)
: mb! ( n ad i -- )  2>r here ! here cell + r@ - 2r> cmove ;
: mb@ ( ad i -- n )  here 0 over ! cell + over - swap cmove here @ ;

\ little-endian test
1 here ! here c@ negate .

当然,这里可以是任何一个单元格缓冲区。

感谢 ruvim 向前解析过程!

于 2015-11-28T18:36:26.657 回答
1

兼容的方式是使用C@和按位运算。为了在内存中使用与 Forth 系统相同的字节顺序,需要检测字节顺序并编译某些定义的合适版本。

\ These definitions use little-endian format in memory.
\ Assumption: char size and address unit size equal to 1 octet.

: MB! ( x addr u -- )
  ROT >R  OVER +  SWAP
  BEGIN  2DUP U>  WHILE  R> DUP 8 RSHIFT >R OVER C! 1+ REPEAT
  2DROP RDROP
;
: MB@ ( addr u -- x )
  0 >R  OVER +
  BEGIN  2DUP U<  WHILE  1- DUP C@ R> 8 LSHIFT OR >R  REPEAT
  2DROP R>
;

为了获得更高的性能,最好使用实现特定的功能(包括W@T@Q@SP@等)甚至内联 Forth 汇编程序。

请注意,通过DO循环直接定义通常性能较差(取决于优化器;在 SP-Forth/4.21 中为 10%)。供参考的代码:

: MB! ( x addr u -- )
  OVER + SWAP ?DO DUP I C! 8 RSHIFT LOOP DROP
;
: MB@ ( addr u -- x )
  DUP 0= IF NIP EXIT THEN
  0 -ROT
  1- OVER + DO 8 LSHIFT I C@ OR -1 +LOOP
;

?DO由于减少了循环索引和+LOOP语义,我们不能在第二种情况下使用:当索引越过“循环限制减一和循环限制之间的边界”时,它会离开圆圈。

于 2015-11-28T15:55:15.010 回答