Загрузка из входного буфера терминала в стек параметров

Почему этот код не работает?

TIB 10 ACCEPT
TIB SP@ 1 cells - 10 cmove

В этом коде я попытался ввести строку и сохранить ее в буфере ввода терминала, а затем сохранить ее в стеке параметров.

А вот с .S вижу, что не работает.


person user1018183    schedule 09.01.2015    source источник
comment
Что следующее распечатывает в вашей системе? -1 U.   -  person Peter Mortensen    schedule 11.01.2015
comment
-1 U. вернул 4294967295 на Raspberry Pi (32-разрядная система). В той же системе 1 cells . вернул 4 (4 байта на слово — слово является отдельным элементом в стеке данных (или стеке параметров)).   -  person Peter Mortensen    schedule 11.01.2015
comment
Итак, каковы результаты для вашей установки/системы?   -  person Peter Mortensen    schedule 11.01.2015
comment
У меня 64-битная система, поэтому -1 U. возвращает FFFFFFFFFFFFFFFF в шестнадцатеричном формате (64 умножить на 1) и 1 ячейку. вернуть 8   -  person user1018183    schedule 13.01.2015


Ответы (3)


Стек параметров растет в сторону нехватки памяти

Основная проблема с примером кода заключается в том, что стек параметров растет в сторону нехватки памяти. Таким образом, отправной точкой для назначения копии должен быть более высокий адрес памяти (внутри существующего/определенного стека параметров). Итак, вместо

TIB SP@ 1 cells - 10 cmove

так должно быть:

TIB SP@ 1 cells + 10 cmove

Выделение памяти для строки

Следующая проблема заключается в том, что для строки в стеке параметров недостаточно места. ACCEPT оставил более одной ячейки (четыре байта в 32-битной системе), фактическое количество символов. С образцом ввода «user10181» (9 символов),

TIB 10 ACCEPT

приводит к:

.S <1> 9  ok

Забыв на время о том лишнем элементе1, для целей этой проработки мы выделяем четыре ячейки в стеке параметров (фактическое значение, например, 235, не имеет значения), 16 байт на 32-битная система:

235 DUP DUP DUP

Тогда результатом TIB SP@ 1 cells + 10 cmove будет:

.S <5> 9 235 8241 541085779 541215060  ok

Мы видим, что три из четырех ячеек (каждая по четыре байта) были перезаписаны cmove (как и ожидалось).

TIB перезаписывается последующим вводом с терминала

К сожалению, наши скопированные байты не такие, как ожидалось. Декодирование вывода для трех измененных ячеек (в десятичном формате), сначала из

8241 541085779 541215060

в шестнадцатеричный:

2031 20405053 20424954

А затем декодировать как ASCII:

20 31 20 40 50 53 20 42 49 54
   1      @  P  S     B  I  T

И реверсирование (сначала у нас была старшая память, а тестовая платформа - little endian) :

 "TIB SP@ 1 "

Это первые десять символов нашей второй строки, TIB SP@ 1 cells + 10 cmove. Таким образом, становится ясно, что терминальный входной буфер (TIB) слишком временный, чтобы его можно было использовать в данном случае.

Решение

Решение третьей проблемы состоит в том, чтобы весь код был скомпилирован до того, как мы запросим ввод данных пользователем. Например, поместите его в слово inputOnStack:

: inputOnStack TIB 10 ACCEPT 235 DUP DUP DUP TIB SP@ 1 cells + 10 cmove ;

Тогда результат:

inputOnStack user10181  ok
.S <5> 9 235 24881 942747697 1919251317  ok

Это соответствует «user10181», а десятый символ — «a» (скорее всего, из «a» в inputOnStack).

Тестовая платформа:

  • Raspberry Pi, модель B.
  • Операционная система: Raspbian, установленная NOOBS 1.3.10, выпущенный 9 сентября 2014 г.
  • Gforth: версия 0.7.0 (установлена ​​с sudo apt-get update; sudo apt-get install gforth)

1. Более продвинутая версия кода может использовать фактическое количество символов. В любом случае, он должен быть DROP так или иначе, чтобы сбалансировать стек, если этот код будет интегрирован в другой код.

person Peter Mortensen    schedule 11.01.2015
comment
TIB 10 ACCEPT 235 DUP DUP TIB SP@ 1 ячейка + 10 cmove — это мое решение, которое делает все, чтобы сократить время интерпретации. Я понял, спасибо. Еще одна важная вещь, которая поддерживает ваше решение, заключается в том, что cmove переходит к верхней памяти. - person user1018183; 13.01.2015

Внимательно рассмотрите, что происходит со стеком после каждого слова. Я воспроизвел ваш код ниже и аннотировал его с глубиной стека в каждой точке.

( 0 ) TIB ( 1 ) 10 ( 2 ) ACCEPT ( 1 )
( 1 ) TIB ( 2 ) SP@ ( 3 ) 1 ( 4 ) cells ( 4 ) - ( 3 ) 10 ( 4 ) cmove ( 1 )

Таким образом, когда выполняется SP@, он возвращает указатель на элемент стека 2. Затем указатель уменьшается на одну ячейку, в результате чего получается указатель на элемент стека 3 (поскольку стек растет вниз). cmove затем перезаписывает 10 байтов, то есть 2 элемента стека (при условии, что вы используете 64-битную версию). Таким образом, элементы стека 3 и 2 меняются. Наконец, cmove извлекает из стека три элемента, оставляя только один. Что без изменений.

person Lars Brinkhoff    schedule 10.01.2015

MU!

В основном то, что вы здесь делаете, это копирует CMOVE в область стека на Форте, где определен SP@ (это не стандартное слово). Так вы уничтожите стек. Ответ таков: такой код не должен работать.

Вопрос не должен быть "почему это не работает?" но "при каких обстоятельствах это имеет ожидаемый эффект?"
Предположим:

  • этот Форт имеет адресуемый и доступный для записи стек (если вы думаете, что это то же самое, прочитайте об дескрипторах сегментов Intel и особенностях инструкций POP и MOV)

  • SP@ указывает на вершину стека в момент вызова.

  • стек растет. (если он растет вниз, ситуация совершенно иная)

  • в начале вызова стек был пуст.

TIB и ACCEPT являются отвлекающими маневрами и будут игнорироваться.

 1 cells -   \ The pointer to the stack is changed opening up one cell

100 cmove  \ you overwrite one cell below the stack, 

        \ then the (32-bit) cell place where the result of SP@ resides *and*

        \ then TIB and then a couple of more bytes 

Предполагая защищенный Форт, последние байты находятся за пределами стека и приводят к ошибке сегментации.

Таким образом, вы должны перенастроить свое мышление на более низкий уровень, если хотите использовать Форт. Думайте о памяти как о стопке почтовых ящиков и начните оттуда.

person Albert van der Horst    schedule 09.02.2015