Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.06.03;
Скачать: [xml.tar.bz2];

Вниз

Округление и умножение вещественных чисел Assembler   Найти похожие ветки 

 
balepa ©   (2007-05-15 10:15) [0]

Помогите сделать на Assemblere вот что, вещественное число (Single) умножить на 10, из того что получилось вернуть целую часть в переменную
Или подскажите где можно статьи на эту тему почитать.
С ув.


 
DVM ©   (2007-05-15 10:23) [1]

Напиши на Delphi и погляди в окно CPU


 
balepa ©   (2007-05-15 10:58) [2]

DVM ©   (15.05.07 10:23) [1]
Хотелось бы не просто сделать чтоб работало, но и понять что, как и почему


 
DVM ©   (2007-05-15 11:05) [3]


> но и понять что, как и почему

Возьми книгу по ассемблеру и читай - все будет понятно. А зачем сие нужно сделать именно на асме?


 
balepa ©   (2007-05-15 11:09) [4]


> DVM ©   (15.05.07 11:05) [3]

Найти хорошую книгу тоже проблема, посоветуй.


> А зачем сие нужно сделать именно на асме?


для того что бы знать.


 
Elen ©   (2007-05-15 12:09) [5]


> Найти хорошую книгу тоже проблема, посоветуй.

неправда. есть куча хорошего материала. Вот например "АССЕМБЛЕР И ПРОГРАММИРОВАНИЕ ДЛЯ IBM PC.  ПИТЕР АБЕЛЬ"
А еще статьи на Wasm.ru. Просто не ленись яндекс спрашивать.


 
umbra ©   (2007-05-15 12:16) [6]


> Или подскажите где можно статьи на эту тему почитать.

Лучше всего почитать "IA-32 Intel Architecture Software Developers Manual", часть первую. Скачать можно с сайта Интел. Плюс - там освещены все основные моменты. Минус - на английском :)


 
balepa ©   (2007-05-15 12:19) [7]


> Elen ©   (15.05.07 12:09) [5]

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


 
DVM ©   (2007-05-15 12:50) [8]


> Elen ©  

Действительно полно плохих книг по асм. В них часто материал преподностится в виде делай как я и получишь то же что и я. Непонятные короче.


 
Elen ©   (2007-05-15 13:33) [9]

А-а-а. ну мне такие вроде не попадались. Ну вот Абель вроде неплохо пишет.


 
begin...end ©   (2007-05-15 23:02) [10]

> balepa ©   (15.05.07 10:15)

Вначале напишем ассемблерный код, решающий поставленную задачу, а затем разберём, что делает каждая его строчка.

var
 S: Single;
 I: Integer;
begin
 S := 8.7654321;
 I := 10;
 asm
   FLD     [S]   // 1
   FIMUL   [I]   // 2
   SUB     ESP, 4  // 3
   FNSTCW  [ESP]  // 4
   FNSTCW  [ESP + 2]  // 5
   FWAIT   // 6
   OR      [ESP], $0F00 // 7
   FLDCW   [ESP]  // 8
   FRNDINT   // 9
   FLDCW   [ESP + 2]  // 10
   ADD     ESP, 4  // 11
   FSTP    [S]   // 12
 end;
 ...
end


1. Команда FLD записывает вещественное число (в нашем случае -- 32-разрядное, хотя можно записывать и значения в других форматах) на вершину стека сопроцессора (его стек -- это особая структура из восьми регистров).

2. Команда FIMUL (Integer Multiplication) выполняет умножение вещественного числа, находящегося на вершине стека (мы только что записали туда переменную S),

на целое число, находящееся по адресу, указанному в качестве операнда (у нас указан адрес переменной I). При этом умножаемое выталкивается из стека, а результат умножения записывается на его (стека) вершину.

Теперь самое интересное: нужно отбросить дробную часть у полученного результата. Эта операция является разновидностью округления, а для округления предназначена команда FRNDINT. Сопроцессор поддерживает 4 режима округления -- округление до ближайшего целого, до ближайшего меньшего/большего целого и, наконец, округление путём отбрасывания дробной части. Перевести сопроцессор в нужный режим округления можно, записав нужное значение в поле RC (Rounding Control) 16-разрядного регистра управления сопроцессором (CWR). Поле представлено 10-м и 11-м битом этого регистра. Для того, чтобы округлять путём отбрасывания, оно должно содержать двоичное значение 11, т.е. оба его бита должны быть "включены".

Алгоритм наших дальнейших действий таков: мы должны сохранить текущее содержимое регистра CWR, затем записать в его поле RC значение 11, вызвать команду округления и, наконец, восстановить прежнее содержимое регистра.

3. Выделяем в стеке (только уже в обычном стеке, а не в стеке сопроцессора) 4 байта -- этого хватит для двух копий содержимого регистра CWR.

4. Команда FNSTCW сохраняет управляющее слово (содержимое регистра CWR) по указанному адресу -- на вершине стека.

5. То же самое значение записываем в стек ниже. Эту копию мы изменять не будем -- она понадобится, чтобы восстановить значение регистра CWR после того, как мы закончим округление.

7. С помощью маски $0F00 изменяем значение первой копии управляющего слова. В слове $0F00 "установлены" биты с номерами 8, 9, 10, 11. Зачем нужны 10-й и 11-й  -- уже понятно, а 8-й и 9-й биты -- это поле управления точностью, и 11 -- это его значение по умолчанию. Команда OR использует значение по адресу ESP -- туда мы записывали слово командой FNSTCW ещё в строке под номером 4. Но не нужно забывать, что команда OR исполняется основным процессором, в то время как FNSTCW -- сопроцессором. Процессор и сопроцессор работают параллельно, и нет гарантии, что к моменту исполнения 7-й строки сопроцессор уже справится со строкой № 4. Чтобы такая гарантия появилась, надо перед командой OR вставить команду FWAIT -- она останавливает основной процессор до тех пор, пока сопроцессор не выполнит последнюю поступившую в него команду.

8. С помощью команды FLDCW загружаем только что подготовленное нами управляющее слово в регистр CWR. Теперь сопроцессор будет округлять так, как нам нужно.

9. FRNDINT -- непосредственно округление. Команда округляет число, находящееся на вершине стека сопроцессора, в соответствии с установленным режимом округления, и записывает результат на место исходного числа.

10. Команда FLDCW восстанавливает предусмотрительно сохранённое нами значение управляющего слова сопроцессора.

11. Выделенные в стеке 4 байта нам больше не нужны -- восстанавливаем прежний адрес вершины стека.

12. Командой FSTP сохраняем наш результат, находящийся на вершине стека сопроцессора, то бишь в регистре ST(0), в переменную S.


 
balepa ©   (2007-05-16 06:04) [11]


> begin...end ©   (15.05.07 23:02) [10]

Огромнейшее спасибо


 
balepa ©   (2007-05-16 07:24) [12]

Я в начале не дописал вернуть в переменную целого типа SmallInt.
Если кому будет интересно это делает команда FISTP.
(Нашел книжку "Ассемблер для DOS, Windows и Unix" Зубков там много чего интересного нашел.)
Еще раз спасибо begin_end



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.06.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.068 c
11-1160962882
Grademax
2006-10-16 05:41
2007.06.03
Как в KOL создать кнопку в стиле XP с картинкой


15-1178262859
Rouse_
2007-05-04 11:14
2007.06.03
Курение убивает :)


15-1178704240
KilkennyCat
2007-05-09 13:50
2007.06.03
не курите траву!


2-1179124034
Люха
2007-05-14 10:27
2007.06.03
Выключение компа


15-1178371957
parus
2007-05-05 17:32
2007.06.03
Защита от автоматич. регистраций





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский