Nicron
#31
24 апреля 1997 |
|
Программирование - калькулятор бейсика (продолжение).
WLODEK BLACK КАЛЬКУЛЯТОР БЕЙСИКА (Продолжение) Работать с вещественными числами в машинных кодах, конечно, сложнее, нежели в Бейсике, но не настолько, чтобы это становилось непонятным. При использовании калькулятора из кодов нужно прежде всего четко разделить данные на константы и изменяющиеся по ходу дела данные (не хочу употреблять термин "переменные"). Константы имеет смысл просчитать заранее и занести в тело программы в готовом виде - 5-байтовом внутреннем представлении. Выяснить значение констант в 5-байтовом представлении легко прямо в Бейсике. Наберите такую строку: 10 PRINT 2.7182818 (Это число "e"). Посмотрев содержимое памяти с адреса 23872 (если TR DOS инициализирована), обнаружим такую последовательность кодов: F5 32 2E 37 31 38 32 38 31 38 0E 82 2D F8 54 3A P 2 . 7 1 8 2 8 1 8 R I N T Маркер #0E разделяет ASCII-запись числа и внутренний 5-байтовый формат. Списав куда-нибудь значения 5-и байтов, стоящих после #0E, мы запомним значение константы. Данные после #0E предназначены для регистров в следующем порядке: 0E 82 2D F8 54 3A A E D C B Занеся их в регистры процессора именно в таком порядке и вызвав затем процедуру STK-STORE (#2AB2), мы получим на стеке калькулятора значение желаемого числа. Понятно, что, написав после "PRINT" любое число и просмотрев затем память, можно узнать 5-байтовое представление любого вещественного значения в диапазоне, допускаемом Бейсиком. Внимание - глюк! И извинения. В предыдущем номере закралась неточность. Вот правильный список процедур STK-STORE: #2AB1 - занесение в стек параметров строки (A обнуляется); #2AB2 - занесение в стек 5-байтового значения числа; #2ABB - занесение в стек регистров A,E,D,C,B без контроля. Существует еще так называемая "упакованная" форма числа, требующая только 4 байта для хранения значения. Прямо скажу, никогда не пытался ею пользоваться. В одной из умных книжек упомянут "глюк" упакованной формы: 0.5 <> 1/2. Ну да ладно... Если при вычислениях или на стадии ввода-вывода будет обнаружена какая-либо некорректность, Бейсик выполнит переход через RST #08 и стек возврата по ошибке. Иными словами, если система Бейсика не была модифицирована (извращена), любая традиционная для Бейсика ошибка приведет к "вылету" программы пользователя в обычный режим ввода команд Бейсика с сообщением об ошибке в низу экрана. Если подобное недопустимо, нужно обязательно переорганизовать стек возврата по ошибке (ERR_SP). Честно говоря, не знаю, надо ли сейчас рассказывать, как это делается. Давайте поступим так: вы напишете мне или на адрес редакции, если такой рассказ необходим, и он появится. Если по ходу выполнения машиннокодовой программы потребуется ввести числовые данные извне, то по крайней мере с клавиатуры это разумнее всего сделать в виде обычных символов цифр, как мы вводим данные на запрос по INPUT. Имитировать INPUT в кодах не стоит; лучше обеспечить ввод символьной строки каким-либо известным вам способом, а дальше преобразовать введенную последовательность символов во внутреннее 5-байтовое представление числа. Итак, у нас есть: символьное изображение числа; нужно получить: внутреннее представление числа. Очень легко это делается путем вычисления выражения VAL "строка". Параметры введенной строки (адрес начала и длина) заносятся на стек калькулятора, а затем выполняется функция VAL: LD DE,ASC_A ; адрес начала строки LD BC,ASC_B-ASC_A ; длина строки CALL #2AB1 ; STK-STORE для параметров строки LD B,#1D ; код функции VAL RST #28 ; вызов калькулятора DEFB #3B ; код функции fp-calc-2 ; на этом месте в стеке получено внутреннее представление числа DEFB ....... ; коды других операций калькулятора DEFB #38 ; выход из калькулятора ........... ASC_A DEFM "2.7182818" ; строка символов, изображающая число ASC_B Функция VAL при своей работе вызывает калькулятор рекурсивно для выполнения многочисленных пересчетов значений ASC-кодов и других промежуточных значений. Из-за этого ее нельзя включать в общий список DEFB кодов операций калькулятора, так как в таком случае теряются другие данные, и происходит какая-нибудь ошибка Бейсика. Для вызова рекурсивных функций предусмотрена специальная операция "fp-calc-2" - вторичный вызов калькулятора. При использовании fp-calc-2 код операции помещается в регистр B, а в теле DEFB ставится код #3B - обращение к fp-calc-2. После #3B могут располагаться коды последующих операций калькулятора. Так же нужно обращаться ко всем функциям, вычисляющим выражения, в том числе строковые - VAL$. Строка символов, определяющая число, может и не быть изображением собственно числа - в строке можно записать любое выражение, даже содержащее переменные Бейсика, и оно будет вычислено! Не трудно представить, что в такой работе задействован и интерпретатор Бейсика. Если функция VAL (или VAL$) вызывается только для преобразования введенного выражения, а затем сразу же производится выход из калькулятора (скажем, для подготовки и ввода других данных), обращение к VAL можно подсократить, вызывая ее не через fp-calc-2, а напрямую через CALL по известному адресу: ...облом!!! В справочнике очепятка... Адрес VAL$ - #35DE, а VAL - ? Ну да ладно, VAL$, так VAL$. Покажем использование VAL$. Вот фрагмент из некоторых мелких утилит, которыми я пользуюсь для оформления серверного диска, обработки "history" и тому подобных забот сисопа: Бейсик: INPUT "Source file:";a$:INPUT "Destination file:";b$:RANDOMIZE USR .... Коды: LD DE,VARLIN ; адрес строки "а$" LD BC,2 ; длина строки CALL #2AB1 ; STK-STORE CALL #35DE ; VAL$ CALL #2BF1 ; STK-FETCH ; на этом месте в DE - адрес значения символьной переменной a$, ; в BC - длина переменной а$ LD A,C ; проверяем, не больше 8 символов ли? CP 9 JR C,VL8 ; если не больше 8 символов LD C,8 ; иначе берем только первые 8 символов VL8 LD B,0 ; это на всякий случай - вдруг кто-нибудь ; 264 символа введет? :-) LD HL,FILNAM ; адрес буфера имени файла EX DE,HL LDIR ; имя файла из переменной a$ переслано в буфер ............. VARLIN DEFM "A$" ; "изображение" символьного выражения, состоящего только из одной переменной a$ ............. FILNAM DEFM " " ; буфер имени файла Вот так, без особого труда, а, главное, очень быстро производится ввод имени файла в некий буфер, из которого потом имя файла используется в соответствии с алгоритмом программы. CALL #35DE заменяет цепочку: LD B,#18 ; код операции VAL$ RST #28 DEFB #3B,#38 , то есть 3 байта вместо 5 плюс увеличение скорости исполнения. Конечно, если после DEFB #3B следуют другие коды операций калькулятора, разумнее вызывать VAL$ через fp-calc-2. Через VAL и VAL$ легко вычисляются всевозможные полезные функции типа RND, INKEY$ и т.д.: RND = VAL CHR$ 165; INKEY$ = VAL$ CHR$ 166. Причем VAL и VAL$ от одиночного простого значения (не от выражения) можно вычислять напрямую без fp-calc-2. Но все же лучше не рисковать!
Другие статьи номера:
Вступление - содержание номера. |
BBS - список станций BBS ZXNet. |
Программирование - калькулятор бейсика (продолжение). |
Рассказ - делаем бомбу ч. 3. |
Рассказ - Ну, юзер, погоди! |
Поиск - поиск игр, программ. |
Юмор - анекдоты. |
Реклама - реклама и объявления. |
Обратная связь - контакты редакции. |
Похожие статьи:
В этот день... 21 ноября