Код магнитолы

JS - телефон

Оппозиция в России ?

Россия и Украина

Мысли в слух...

JS - часы

Российская...власть ?

Skype

Создаём сайт

Любимые сериалы

Гостевая


На главную

Ассемблер и арифметика

Ассемблер позволяет обработать все операционные кнопки, которые имеются на нашем арифмометре. Единственный нюанс, который придётся учесть - арифмометр будет работать с целыми, положительными числами.
Сделаем небольшое отступление и поговорим о том, с какими числами должен был работать наш арифмометр и почему мы от этого (пока) отказались. Это дробные (кнопка с символом "точка" - которой у нас нет) десятичные числа.

Мы набираем на дисплее число, предположим, что дробное. Затем, после знака операции, набираем ещё одно. Что-бы процессор произвёл арифметическую операцию эти числа необходимо представить в двоичном виде. Как это будет происходить:

1. берём число с дисплея-строку символов
2. определяем целую часть
2.1 преобразуем целую часть в bin
3. определяем дробную часть
3.1 преобразуем дробную часть в bin
4. собираем число: целая часть + дробная часть...вроде-бы - всё верно, но между целой и дробной частью имеется разделительный символ "."
5. у разделительного символа есть свой код 2Еh или 00101110 в двоичном , но если его вставить между целой и дробной частью - процессор этого не поймёт
6. что-бы процессор понял, что число дробное, его надо представить в вещественном виде

Обратим внимание на то, что процессор такие числа не обрабатывает, этим занимается - сопроцессор (арифметический процессор), у которого свои арифметические команды.
Мы то-же воспользуемся услугами сопроцессора - математика у него намного проще. Oдин из операндов располагается в вершине стека сопроцессора - регистре st(0), куда, после выполнения, записывается и результат. Другой опреанд может располагатся либо в памяти, либо в другом регистре st(1)...st(7) стека сопроцессора:

 передача данных:  
   fld источник --> загрузка числа из области памяти в вершину стека st(0)
   fst приёмник --> сохранение числа из вершины стека st(0) в память
   fstр приёмник --> сохранение числа из вершины стека st(0) в память с
                            выталкиванием его из регистра	   
   fxch st(i) --> st --> st(i)
 сложение:  
   fadd -----------> st + st(1) -----> st 
   fadd источник --> st + источник --> st, источник - адрес ячейки памяти 
   fadd st(i),st --> st(i) + st -----> st(i)
 вычитание: 
   fsub -----------> st - st(1) -----> st
   fsub источник --> st - источник --> st, источник - адрес ячейки памяти
   fsub st(i),st --> st(i) - st -----> st(i)
 умножение: 
   fmul -----------> st * st(1) ----> st
   fmul источник --> st(i) * источник -> st 
   fmul st(i) -----> st(i) * st ----> st
   fmul st(i),st --> st(i) * st ----> st(i)
 деление:  
   fdiv -----------> st : st(1) -----> st
   fdiv источник --> st : источник --> st
   fdiv st(i) -----> st : st(i) -----> st 
   fdiv st(i),st --> st : st(i) -----> st(i)
 извлечение квадратного корня:  
   fsqrt --> из значения st --> st
 выделение порядка и мантисы значения st:  
   fxtract  --> мантиса (вещественное число) -->st,
	                      порядок (без смещения) --> st(1) 

						  
Поскольку мы будем использовать компилятор masm32, то вершину стека мы будем обозначать st а не st(0).
Это - не все команды, только те, что могут понадобится.
Хочется ещё раз подчеркнуть - это команды сопроцессора для работы с вещественными числами.
Во всех арифметических операциях, на мой взгляд, наиболее удобен первый вариант - безоперандный, легче следить за регистрами. Есть ещё два момента, которые имеют разную трактовку в разных источниках.
Момент первый:
Сопроцессор необходимо инициировать - перед его кодом помещают команду finit. Среди продчего - она должна "очищать" регистры стека сопроцессора, работающего по принципу колеса обозрения. Это удобно, если арифметика не очень длинная, т.к. регистров всего 8. Поэтому - не стоит забывать о варианте fstр. Рассмотрим это колесо поближе на примере операции сложения:
 
 ; a + b = c
 .data
    a  db  2,2
    b  db  3,3
 .data?
    c  db  ?
 ...                ; st     st(1)    st(2)   ...   st(7)
  finit             ;  -       -        -             -
  fld  a            ; 2,2      -        -             -
  fld  b            ; 3,3     2,2       -             -
  fadd              ; 5,5     2,2       -             -
  fstp c            ; 2,2      -        -             -
  fwait
  push  offset c
  ...
Момент второй:
После кода сопроцессора необходимо помещать команду fwait - для синхронизации работы процессора и сопроцессора.
Единого мнения по этому поводу нет. Поэтому мы будем исползовать обе команды. А поскольку мы не знаем - с какой именно операции начнётся работа арифмометра, то лучше задействовать их в каждой обработке.

Теперь, когда у нас есть арифмометр и он умеет (мы так предполагаем) выполнять все задействованые арифметические операции - начинается самое интересное...

дальше...
...назад