Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: CALL, RET, NEXT и адресный интерпретатор |
|
|
Можно сделать всегда первым словом (которое и вызывается CALL-ом) "интерпретатор последовательности адресов", тогда все будет единообразно, все слова получатся "ассемблерные". Потери составят по одному адресу на каждое определение слова (на определение через DOES - 2 адреса). Но и это лучше, т.к. выходов из слова может быть больше одного (особенно если программировать в стиле Броуди).
Можно сделать всегда первым словом (которое и вызывается [b]CALL[/b]-ом) "интерпретатор последовательности адресов", тогда все будет единообразно, все слова получатся "ассемблерные". Потери составят по одному адресу на каждое определение слова (на определение через [b]DOES[/b] - 2 адреса). Но и это лучше, т.к. выходов из слова может быть больше одного (особенно если программировать в стиле Броуди).
|
|
|
|
Добавлено: Вс апр 08, 2012 16:46 |
|
|
|
|
|
Заголовок сообщения: |
Re: CALL, RET, NEXT и адресный интерпретатор |
|
|
in4 писал(а): А какие проблемы с возвратами? проблема не с возвратами, а с тем, что одно и то же слово надо вызывать двумя способами - из адресного интерпретатора и из "ассемблерного кода". Возврат в двух этих случаях различен, а делать два одинаковых кода, один для интерпретатора, другой для вызова из ассемблера - накладно в условиях нехватки памяти (а это именно так во встроенной системе!). in4 писал(а): которое извлекает из стека адрес возврата (который там разместил CALL) и продолжает интерпретацию с этого адреса (= действие NEXT). А когда слово вызвано из ассемблера, надо, чтобы действие было = RET, а не NEXT, т.е. после извлечения адреса возврата происходило не продолжение интерпретации с того места, а возврат к исполнению кода и продолжение. Решение в лоб означает, что ассемблерный вызов слова будет не просто Код: CALL addr, а Код: CALL addr, exit в котором Код: : exit RDROP RET ; вызов "распухает" почти в 2 раза, и это не нравится. По сути, надо делать два разных CALL один для вызова интерпретатора, другой для ассемблерного вызова. т.е. CALL^ret и CALL^next И где-то запоминать способ вызова. Наиболее приемлемо - на стеке возвратов и запоминать - в том бите адреса возврата, который не существенен для исполнения программы, когда в системе мало памяти. CALL становится префиксной командой. А в префиксном виде можно добавить и другие типы вызовов. Например, условный. Хм... этак недалеко и до полнго превращения четырехбитной система команд в восьмибитную.
[quote="in4"]А какие проблемы с возвратами?[/quote]
проблема не с возвратами, а с тем, что одно и то же слово надо вызывать двумя способами - из адресного интерпретатора и из "ассемблерного кода". Возврат в двух этих случаях различен, а делать два одинаковых кода, один для интерпретатора, другой для вызова из ассемблера - накладно в условиях нехватки памяти (а это именно так во встроенной системе!).
[quote="in4"]которое извлекает из стека адрес возврата (который там разместил CALL) и продолжает интерпретацию с этого адреса (= действие NEXT).[/quote]
А когда слово вызвано из ассемблера, надо, чтобы действие было = RET, а не NEXT, т.е. после извлечения адреса возврата происходило не продолжение интерпретации с того места, а возврат к исполнению кода и продолжение. Решение в лоб означает, что ассемблерный вызов слова будет не просто [code]CALL addr, [/code] а [code] CALL addr, exit[/code]
в котором [code]: exit RDROP RET ;[/code] вызов "распухает" почти в 2 раза, и это не нравится.
По сути, надо делать два разных CALL один для вызова интерпретатора, другой для ассемблерного вызова. т.е. CALL^ret и CALL^next И где-то запоминать способ вызова. Наиболее приемлемо - на стеке возвратов и запоминать - в том бите адреса возврата, который не существенен для исполнения программы, когда в системе мало памяти.
CALL становится префиксной командой. А в префиксном виде можно добавить и другие типы вызовов. Например, условный.
Хм... этак недалеко и до полнго превращения четырехбитной система команд в восьмибитную.
|
|
|
|
Добавлено: Сб апр 07, 2012 04:22 |
|
|
|
|
|
Заголовок сообщения: |
Re: CALL, RET, NEXT и адресный интерпретатор |
|
|
А какие проблемы с возвратами? Если слово ассемблерное, то оно вызывается через CALL и возвращает через RET. Если слово "фортовое", то оно может вызываться через CALL, а в качестве возврата (ведь там ожидается адрес, да?) используется адрес слова (у Баранове-Ноздрунова оно называется EXIT), которое извлекает из стека адрес возврата (который там разместил CALL) и продолжает интерпретацию с этого адреса (= действие NEXT). Так было в Форте для K580. Подробно в книге "Язык программированния ФОРТ" описано.
А какие проблемы с возвратами? Если слово ассемблерное, то оно вызывается через [b]CALL[/b] и возвращает через [b]RET[/b]. Если слово "фортовое", то оно может вызываться через [b]CALL[/b], а в качестве возврата (ведь там ожидается адрес, да?) используется адрес слова (у Баранове-Ноздрунова оно называется [b]EXIT[/b]), которое извлекает из стека адрес возврата (который там разместил [b]CALL[/b]) и продолжает интерпретацию с этого адреса (= действие [b]NEXT[/b]). Так было в Форте для K580. Подробно в книге "Язык программированния ФОРТ" описано.
|
|
|
|
Добавлено: Пт апр 06, 2012 23:49 |
|
|
|
|
|
Заголовок сообщения: |
Re: CALL, RET, NEXT и адресный интерпретатор |
|
|
вопрос писал(а): то нехорошо,если процессор "переходит к вычислению адреса перехода после выполнения слова", Собственно, вычислять его и не надо. Его надо всего лишь брать из двух разных мест в зависимости от типа исполнения слова. А тип задается непосредственно при вызове.
[quote="вопрос"]то нехорошо,если процессор "переходит к вычислению адреса перехода после выполнения слова",[/quote]
Собственно, вычислять его и не надо. Его надо всего лишь брать из двух разных мест в зависимости от типа исполнения слова. А тип задается непосредственно при вызове.
|
|
|
|
Добавлено: Пт апр 06, 2012 22:30 |
|
|
|
|
|
Заголовок сообщения: |
Re: CALL, RET, NEXT и адресный интерпретатор |
|
|
Так... ловлю мыслю!.. Так как памяти у моего процессора сейчас всего 16Кx16, значит, два бита регистра PC "пропадают". Их то и можно использовать для полезных функций... Одна - старая - флаг переноса в 15-м бите регистра PC. А вторая в 14-м бите может нести инфу о том, какой возврат ожидается, и определяется он при вызове подпрограммы.
:zombypc; :zombypc;
Так... ловлю мыслю!.. Так как памяти у моего процессора сейчас всего 16Кx16, значит, два бита регистра PC "пропадают". Их то и можно использовать для полезных функций... Одна - старая - флаг переноса в 15-м бите регистра PC. А вторая в 14-м бите может нести инфу о том, какой возврат ожидается, и определяется он при вызове подпрограммы.
|
|
|
|
Добавлено: Пт апр 06, 2012 22:28 |
|
|
|
|
|
Заголовок сообщения: |
Re: CALL, RET, NEXT и адресный интерпретатор |
|
|
Собственно, количество ... логических единиц при анализе этого механизма настолько невелик, что можно сметь надеяться сделать даже исчерпывающий перебор при поиске нужного решения. Понятно, что от слова к слову минимально ведёт команда перехода, поэтому самое простое - находить адрес перехода во время компиляции (подумаешь - задача ) и просто прыгать. Однако - вложенность, т.е. стек возвратов, таким образом неизбежным представляется RET. То есть, мы выбираем между прыжком (по разному оформленным) и прыжком ... а ведь тоже прыжком. Итак - перед нами на самом деле 2 прыжка - только разный механизм получения адреса. В общем случае можно исходить из следующего - прыжок будет происходить непременно, но способ вычисления (получения) адреса - неодинаков. Вот эти два различных способа нужно соспоставить и проанализировать. Дажее понятно, что если речь о скорости, то нехорошо,если процессор "переходит к вычислению адреса перехода после выполнения слова", желательно, чтобы адрес уже был вычислен. 3 варианта А) адрес вычисляется во время компиляции если возможно В) адрес вычисляется параллельно выполнению слова С) ничего не получается - смириться - адрес придётся вычислять отдельно
Собственно, количество ... логических единиц при анализе этого механизма настолько невелик, что можно сметь надеяться сделать даже исчерпывающий перебор при поиске нужного решения. Понятно, что от слова к слову минимально ведёт команда перехода, поэтому самое простое - находить адрес перехода во время компиляции (подумаешь - задача :?: ) и просто прыгать. Однако - вложенность, т.е. стек возвратов, таким образом неизбежным представляется RET. То есть, мы выбираем между прыжком (по разному оформленным) и прыжком ... а ведь тоже прыжком. Итак - перед нами на самом деле 2 прыжка - только разный механизм получения адреса. В общем случае можно исходить из следующего - прыжок будет происходить непременно, но способ вычисления (получения) адреса - неодинаков.
Вот эти два различных способа нужно соспоставить и проанализировать.
Дажее понятно, что [b]если речь о скорости[/b], то нехорошо,если процессор "переходит к вычислению адреса перехода после выполнения слова", желательно, чтобы адрес уже был вычислен. 3 варианта А) адрес вычисляется во время компиляции если возможно В) адрес вычисляется параллельно выполнению слова С) ничего не получается - смириться - адрес придётся вычислять отдельно
|
|
|
|
Добавлено: Пт апр 06, 2012 21:52 |
|
|
|
|
|
Заголовок сообщения: |
Re: CALL, RET, NEXT и адресный интерпретатор |
|
|
mOleg писал(а): не мешать одно с другим, если слово завершается RET, а не NEXT вызывать его с помощью CALL. А вообще, совмещение методик вызова страшный изврат, имхо. CALL-ом вызываются оба способа... да, изврат, но так есть...
[quote="mOleg"]не мешать одно с другим, если слово завершается RET, а не NEXT вызывать его с помощью CALL. А вообще, совмещение методик вызова страшный изврат, имхо.[/quote]
CALL-ом вызываются оба способа... да, изврат, но так есть...
|
|
|
|
Добавлено: Пт апр 06, 2012 21:23 |
|
|
|
|
|
Заголовок сообщения: |
Re: CALL, RET, NEXT и адресный интерпретатор |
|
|
WingLion писал(а): По сему и возникает вопрос - КАК? не мешать одно с другим, если слово завершается RET, а не NEXT вызывать его с помощью CALL. А вообще, совмещение методик вызова страшный изврат, имхо.
[quote="WingLion"]По сему и возникает вопрос - КАК?[/quote] не мешать одно с другим, если слово завершается RET, а не NEXT вызывать его с помощью CALL. А вообще, совмещение методик вызова страшный изврат, имхо.
|
|
|
|
Добавлено: Пт апр 06, 2012 17:42 |
|
|
|
|
|
Заголовок сообщения: |
CALL, RET, NEXT и адресный интерпретатор |
|
|
Стандартный вызов подпрограмм в процессоре превращается в вызов адресного интерпретатора, если каждую подпрогрaмму заканчивать не командой RET, а командой NEXT, которая при исполнении делает RET и сразу же новый CALL без выборки опкода. Форт-Программа с прямым шитым кодом превращается в код: Код: CALL word1 DW word2,word3,word4... DW word_next
word_next: RDROP NEXT Возникает некоторая проблема при необходимости вызвать форт-слово в коде на ассемблере. Для него приходится делать обертку в виде Код: CALL word label1 label1: RET ; - эквивалент ;CODE Чтобы расточительства такого не было, надо все слова заканчивать командой RET, а при возврате каким-то образом определять, какой это тип возврата - возврат в код или возврат в адресный интерпретатор... По сему и возникает вопрос - КАК?
Стандартный вызов подпрограмм в процессоре превращается в вызов адресного интерпретатора, если каждую подпрогрaмму заканчивать не командой RET, а командой NEXT, которая при исполнении делает RET и сразу же новый CALL без выборки опкода.
Форт-Программа с прямым шитым кодом превращается в код: [code] CALL word1 DW word2,word3,word4... DW word_next
word_next: RDROP NEXT[/code]
Возникает некоторая проблема при необходимости вызвать форт-слово в коде на ассемблере. Для него приходится делать обертку в виде [code] CALL word label1 label1: RET ; - эквивалент ;CODE[/code]
Чтобы расточительства такого не было, надо все слова заканчивать командой RET, а при возврате каким-то образом определять, какой это тип возврата - возврат в код или возврат в адресный интерпретатор...
По сему и возникает вопрос - КАК?
|
|
|
|
Добавлено: Пт апр 06, 2012 17:31 |
|
|
|
|