MasterGH Опубликовано 28 марта, 2010 Поделиться Опубликовано 28 марта, 2010 Привет, это вновь MasterGH с занудной, но полезной статьёй )Рассмотрим работу с некоторыми FPU инструкциями компилятора Borland C++Подопытная программка, которую я написал выглядит так:рис.1(весит 12 кб в сжатом состоянии.. хе-хе, буду знать)Как видите, она умеет уменьшать, увеличивать и уменьшать с условием значение здоровья типа float. Основной код, который я добавил в приложение.float fhealth = 100.0;//---------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender){fhealth-=20.0;updateValue();}//---------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender){fhealth+=20.0;updateValue();}//---------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender){if (fhealth>10) {fhealth-=5;};updateValue();}void TForm1::updateValue(){Edit1->Text=fhealth;}//---------------------------------------------------------------------------Остальной код писать не буду, т.к. он генерируется автоматически. Ах да updateValue() нужно добавить в приватную область класса формы и больше я никакого кода не писал. А теперь взглянем на ассемблерные инструкции этих действий.Буду приводить кусок исходника и описание.//---------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender){fhealth-=20.0;updateValue();}Это тоже самое что:рис.2Так как всё тут просто комментировать не буду.Идём к следующей инструкции.//---------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender){fhealth+=20.0;updateValue();}Почти аналогично, только с инструкцией добавления:рис.3Ну, а теперь самое интересное://---------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender){if (fhealth>10) {fhealth-=5;};updateValue();}А теперь разберём инструкции подробнее:Unit1.cpp.32: if (fhealth>10) {fhealth-=5;};00401CF8 D90598414000 fld dword ptr [$00404198] //грузим в стек FPU 100.000401CFE D9052C1D4000 fld dword ptr [$00401d2c] // грузим в стек FPU 5.0//Сейчас ST(0)=10, а ST(1)=100 00401D04 D9C9 fxch st(1) // меняет местами содержимое регистров//Сейчас ST(0)=100, а ST(1)=10 00401D06 DAE9 fucompp // сравнивание с двойным выталкиванием из стека//Сейчас ST(0)=Empty, а ST(1)= Empty (что означает пустые) Флаги FPU поменялисьБыло/сталорис.400401D08 DFE0 fstsw axЛезу в справку:fstsw и fnstsw сохраняют текущее значение слова статуса FPU в указанном месте. Операндом-адресатом может быть либо 16 бит в памяти, либо регистр AX. fstsw перед сохранением слова проверяет на подвешенные немаскируемые прерывания, fnstsw этого не делаетКороче какие-то флаги FPU загнали в AXрис.500401D0A 9E sahf // загружаем ah в младший байт регистра eflagsрис.600401D0B 7612 jbe $00401d1f // jbe не работает когда 10<100 при флагах CPU: CF=1 и ZF=1// а теперь вы полнение записи здоровья00401D0D D905301D4000 fld dword ptr [$00401d30] // грузим 5 в ST(0)00401D13 D82D98414000 fsubr dword ptr [$00404198] // от здоровья отнимаем ST(0) и сохраняем здоровье в ST(0)00401D19 D91D98414000 fstp dword ptr [$00404198] // выталкиваем и записываем вновь здоровьеUnit1.cpp.33: updateValue();00401D1F FF75FC push dword ptr [ebp-$04]00401D22 E80D000000 call TForm1::updateValue() // ну, а это уже пошла моя функция обновления…00401D27 59 pop ecxЗаключение.Короче говоря, берём на зуб:Unit1.cpp.32: if (fhealth>10) {fhealth-=5;};00401CF8 D90598414000 fld dword ptr [$00404198]// fhealth00401CFE D9052C1D4000 fld dword ptr [$00401d2c]// 10.000401D04 D9C9 fxch st(1)00401D06 DAE9 fucompp 00401D08 DFE0 fstsw ax00401D0A 9E sahf 00401D0B 7612 jbe $00401d1f // if (fhealth>10) {fhealth-=5;};00401D0D D905301D4000 fld dword ptr [$00401d30]00401D13 D82D98414000 fsubr dword ptr [$00404198]00401D19 D91D98414000 fstp dword ptr [$00404198]Unit1.cpp.33: updateValue();00401D1F FF75FC push dword ptr [ebp-$04]Этот шаблон вы можете применить в своих скриптах, когда некоторый параметр не должен быть меньше другого некоторого параметра.Не знаю как вы, я подумал сложные скрипты лучше писать на С++ реализованные в dll, которые можно подгрузить скриптами CE, но об этом позже... Ссылка на комментарий Поделиться на другие сайты Поделиться
holy Опубликовано 21 июня, 2016 Поделиться Опубликовано 21 июня, 2016 On 28.03.2010 at 6:06 PM, MasterGH said: А теперь разберём инструкции подробнее: Unit1.cpp.32: if (fhealth>10) {fhealth-=5;}; 00401CF8 D90598414000 fld dword ptr [$00404198] //грузим в стек FPU 100.0 00401CFE D9052C1D4000 fld dword ptr [$00401d2c] // грузим в стек FPU 5.0 Кажется тут в комментариях должно было быть "грузим в стек FPU 10.0" вместо "грузим в стек FPU 5.0" Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 21 июня, 2016 Автор Поделиться Опубликовано 21 июня, 2016 Я уже исправлять не буду, Пусть как есть. Шесть прошло с момента поста. Даже не верится. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения