2015-11-28 9 views
2

При использовании больших массивов было бы неплохо настроить массив на определенное количество байтов на число. В основном я хочу, чтобы быстрые подпрограммы читали такие отрегулированные многобайтовые числа для синглов в стеке и, наоборот, сохраняли синглы в массиве, настроенные на определенное количество байтов. В 64-битной системе есть потребность в других одиночных массивах чисел, чем один байт (c @ c!) И восемь байтов (@!).Многобайтовый магазин и выборка в Forth - как реализовать?

Так как реализовать

[email protected] (ad b -- n) 
cs! (n ad b --) 

где Ь число байтов. Слово cs! кажется, работает, как

: cs! (n ad b --) >r [email protected] cell+ swap r> cmove drop ; 

, но как о CS @ и как сделать это в чистом ANS Forth без SP @ или подобных слов?

+0

Обратите внимание, что 'CS' означает операции с потоком Control-Flow Stack, такие как 'cs-roll' и т. Д., См. [Дополнительный набор инструментов для программирующих инструментов] (http://www.forth200x.org/documents/html/tools .html). Поэтому использование суффикса 'cs' для другой семантики может запутать. – ruvim

+0

Да, это было знакомо, но я об этом не думал. Лучше имена, возможно, mb @ и mb! – Lehs

+0

Должно ли выражение 'addr @' давать тот же результат, что и 'addr 8 mb @', если размер ячейки равен 64 бит? Я имею в виду, что 'cmove' может привести к разному результату в таком случае. Также обратите внимание, что в общем случае порядок байтов может отличаться в памяти и в стеке. – ruvim

ответ

1

Совместимый способ заключается в использовании [email protected] и побитовых операций. Чтобы использовать тот же порядок байтов в памяти, что и система 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 
; 
: [email protected] (addr u -- x) 
    0 >R OVER + 
    BEGIN 2DUP U< WHILE 1- DUP [email protected] R> 8 LSHIFT OR >R REPEAT 
    2DROP R> 
; 

Для повышения производительности это может быть лучше использовать специфические особенности реализации (в том числе [email protected], [email protected], [email protected], [email protected] и т.д.), или даже встроенный Форт-ассемблера.

Обратите внимание, что простое определение с помощью цикла DO обычно имеет худшую производительность (зависит от оптимизатора, 10% в SP-Forth/4.21). Код для ссылки:

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

Мы не можем использовать ?DO во втором случае из-за снижения индекса цикла и +LOOP semantics: он оставляет круг, когда индекс пересекает «границу между пределом цикла минус один и предел цикла ".

+0

Какова идея не использовать do-loop? – Lehs

+0

Спасибо, ruvim, но я думаю, что нашел хорошее решение (?) Сам! – Lehs

+0

@Lehs идея не использовать do-loop - это производительность - я обновил ответ. – ruvim

1
\ little-endian (eg. pc, android) 
: mb! (n ad i --) 2>r here ! here 2r> cmove ; 
: [email protected] (ad i -- n) here 0 over ! swap cmove here @ ; 

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

\ little-endian test 
1 here ! here [email protected] negate . 

Конечно, ЗДЕСЬ может быть любой буфер для одной ячейки.

Спасибо, ruvim за разбор процесса!

+0

Хорошая идея - короткое решение!Хотя, по моим тестам, производительность этого решения хуже, чем решение с do-loop. Также обратите внимание, что эти определения будут работать неправильно в случае ** big-endian **. Кроме того, 'mb @' должен стереть буфер перед перемещением данных. – ruvim

+0

@ruvim: вы правы. Здесь нужно очистить. Что такое big-endian? – Lehs

+0

Лучше вообще не использовать 'ЗДЕСЬ', чтобы избежать столкновений и использовать буфер потока или буфер в стеке возврата. Что касается big-endian, см. [Endianness] (https://en.wikipedia.org/wiki/Endianness) – ruvim

1

Комитет Forth200 * x * положил довольно много времени на разработку словарного набора Memory Access. Пока мы не включили его в стандарт по своим размерам.

+1

Это не дает ответа на вопрос. Чтобы критиковать или просить разъяснения у автора, оставьте комментарий ниже их сообщения. - [Из обзора] (/ review/low-quality-posts/11465846) – Milap

+0

Если вы действительно перейдете по ссылке и прочитайте статью, вы найдете ее не только обсуждает трудности с предоставлением таких слов , но также предоставляет определение набора из 22 слов, которое делает это упрощение, а также модульные тесты для проверки правильности слова . –

 Смежные вопросы

  • Нет связанных вопросов^_^