Помощь - Поиск - Пользователи - Календарь
Полная версия: Немного о вещественном асме.
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ассемблер
TarasBer
У меня вопрос - почему не компилируется этот кусок кода?


procedure SinCos(var d, c, s: extended); assembler;
asm
fld d
fsincos
fstp c
fstp s
end;



И как его правильно переписать. Компилятор говорит что инвалид комбинатион оф опкоде энд операндс. Вот глобальные переменные можно передавать, локальные можно, а передаваемые в процедуру - нельзя! Что за странное ограничение?
TarasBer
Да, ещё вопрос - как заставить Дельфи показать регистры сопроцессора и показать то, что он скомпилировал, в виде ассемблерного кода?
volvo
У меня не говорит, что неправильные операнды, жалуется, что не знает такой инструкции FSINCOS... Компилятор какой? Я вот это откомпилировал и выполнил на TP7 без проблем:

{ Код от Merlyn-а }
procedure FSinCos(var S, C : extended ; A : extended) ; assembler ;
asm
fld [A] ; db $CD,$35,$FB
les di,[C] ; fstp es:tbyte ptr[di] ;
les di,[S] ; fstp es:tbyte ptr[di] ;
end {FSinCos} ;


var Rad, _Sin, _Cos: extended;
begin
Rad := Pi / 4;
FSinCos(_Sin, _Cos, Rad);
writeln(_Sin, ' ', _Cos);
end.

Вот результат:
 7.07106781186548E-0001  7.07106781186548E-0001
... По-моему, все правильно.
TarasBer
Цитата(volvo @ 6.03.2009 16:54) *

У меня не говорит, что неправильные операнды, жалуется, что не знает такой инструкции FSINCOS...


А это команда из более позднего видимо сопроцессора. А у Паскаля 287 это вершина технического прогресса.
Видимо db $CD,$35,$FB и есть код этой команды, насильно так сказать, заставим Паскаль это компилировать.

Цитата

Компилятор какой?


А, Дельфа... Седьмая.

Цитата

Я вот это откомпилировал и выполнил на TP7 без проблем:

{ Код от Merlyn-а }
procedure FSinCos(var S, C : extended ; A : extended) ; assembler ;
asm
fld [A] ; db $CD,$35,$FB
les di,[C] ; fstp es:tbyte ptr[di] ;
les di,[S] ; fstp es:tbyte ptr[di] ;
end {FSinCos} ;
var Rad, _Sin, _Cos: extended;
begin
Rad := Pi / 4;
FSinCos(_Sin, _Cos, Rad);
writeln(_Sin, ' ', _Cos);
end.

Вот результат:
 7.07106781186548E-0001  7.07106781186548E-0001
... По-моему, все правильно.


Как хитро он переменные из регистров грузит. Через промежуточный регистр оказывается...
А Merlyn, кстати, раз знает код команды, не может переписать это в кодах полностью? А то, говорят, это единственная возможность делать макросы на Паскале. Издевательство такое утончённое.


Добавлено через 4 мин.
У меня этот код почему-то ошибку при выполнении выдаёт. Только окно сразу же закрывается, а аль-эф-5 в дельфе нету, не посмотреть что за ошибка.
volvo
Для Дельфей (для D7 именно) на QualityCentral в свое время выкладывался вот такой код (из JediVCL):
procedure FSinCos(var Sin, Cos: Extended; X: Extended); assembler;
asm
FLD X
FSINCOS
FSTP Extended PTR [EDX]
FSTP Extended PTR [EAX]
FWAIT
end;

var Rad, _Sin, _Cos: extended;
begin
Rad := Pi / 4;
FSinCos(_Sin, _Cos, Rad);
writeln(_Sin, ' ', _Cos);
readln;
end.

, только что проверил под D2009 - работает.
TarasBer
Цитата(volvo @ 6.03.2009 17:33) *

Для Дельфей (для D7 именно) на QualityCentral в свое время выкладывался вот такой код (из JediVCL):
procedure FSinCos(var Sin, Cos: Extended; X: Extended); assembler;
asm
FLD X
FSINCOS
FSTP Extended PTR [EDX]
FSTP Extended PTR [EAX]
FWAIT
end;

var Rad, _Sin, _Cos: extended;
begin
Rad := Pi / 4;
FSinCos(_Sin, _Cos, Rad);
writeln(_Sin, ' ', _Cos);
readln;
end.

, только что проверил под D2009 - работает.


Да, это работает, спасибо. При замене EDX и EAX на С и S тоже работает. Только при замене порядка переменных уже работать перестаёт. А текущий порядок какой-то по-моему неестественный.
И ещё вопрос - команда FWAIT что делает, насколько тут нужна, и если я вместо вызова процедуры буду просто писать этот ассемблерный код, безо всяких вызовов - она тоже нужна?
volvo
Такой порядок - более приемлемый:
procedure FSinCos(X: Extended; var Sin, Cos: Extended); assembler;
? Так тоже работает...

Цитата
команда FWAIT что делает, насколько тут нужна
Этак команда заставляет процессор ждать, пока со-процессор не закончит свои действия (в данном случае - сохранение результата). Все-таки желательно этого дождаться, если не хочешь потом иметь глюков с частично записанным, а частично - нет результатом вычисления (по той простой причине, что ты не подождал сигнала от FPU об окончании сохранения, а начал использовать их раньше...)
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.