Форум: "Начинающим";
Текущий архив: 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.052 c