Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.146.255.127] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Помогите разобратся:
... ;набрали 1-е число: GetWindowTextA@12 --> eax ... plus: ;нажали "+" (id_But equ 1Ch) mov edx,0 ;очищаем регистр mov edx,1Ch ;отмечаем нажатую кнопку mov str1,eax ;сохраняем что набрали finit ;инициируем сопроцессор fldz ;очищаем вершину стека 0-->st(0) fld str1 ;добавляем первое число str1-->st(0) call clear ;очищаем дисплей ... ;набрали 2-е число: GetWindowTextA@12 --> eax ... itog: ;нажали "=" cmp edx,1Ch je plus_ex ... plus_ex: call clear ;очищаем дисплей mov buf,0 ;очищаем буфер ? mov str2,eax ;сохраняем что набрали finit ;инициируем сопроцессор fadd str2 ;st(0)+str2-->st(0) fst buf ;st(0)-->buf - здесь сумма push offset buf push [hWndEdt] call SetWindowTextA@8 ;выводим сумму на дисплей jmp exit ;mov eax,0 jmp finish ... finish: pop edi pop esi pop ebx pop ebp ret 16 winproc endp clear proc push Edt push [hWndEdt] call SetWindowTextA@8 ret clear endp end go В результате сложения (после нажатия "=") - на дисплее последнее набранное число. Такое впечатление, что первое число в st(0) не попало (fld str1) или, почему-то, от туда исчезло. Даже без конвертации что-то должно быть. |
Сообщ.
#2
,
|
|
|
Как бы негоже проводить инициализацию на каждый раз. Так, в Винде на 32-битах у меня вообще пишет недопустимую операцию при добавлении числа к пустой ячейке. В 16-битном режиме что-то складывает с давно там записанным.
|
Сообщ.
#3
,
|
|
|
finit уничтожает все данные во всех (в т.ч. специальных) регистрах сопроцессора. К незанятому регистру FPU ничего нельзя прибавить. В FPU есть специальные регистры-теги, которые хранят доп.информацию об основных стековых регистрах. Если регистр помечен как незанятый, то и результат будет "никаким".
Цитата cupoma58 @ Если вы пытаетесь записать в st(0) строку, то там явно будет не то, что нужно. И это "что-то" может быть, например, NaN (нечисло) или Inf (бесконечность).Даже без конвертации что-то должно быть. p.s. jmp exit или finish? |
Сообщ.
#4
,
|
|
|
Цитата Jin X @ У меня книга "Assembler для Dos, Windows и Unix" (Москва, 1999) пишет:finit уничтожает все данные во всех (в т.ч. специальных) регистрах сопроцессора. Цитата Собственно, 16-битный запуск подтвердил, что если после finit'а идёт сразу fadd, то происходит прибавление чего-то с чем-то. А вот Винда 32-битная пишет "1#IND" в регистре. Так что не всё столь однозначно. FINIT: ... Регистры данных никак не изменяются, но все они помечаются пустыми в регистре TW. |
Сообщ.
#5
,
|
|
|
Так и есть. Содержимое регистров помечается пустым. Это можно изменить в регистре тэгов, чем и "воскресить" хранящиеся там значения, однако смысла в этом нет никакого. FINIT предназначена для начальной инициализации, чтобы сбросить весь предыдущий неизвестный контекст, так что если контекст нужен, проще просто не выполнять инициализацию. У ТС второй FINIT абсолютно лишний.
При попытке выполнить какою-либо операцию, которая зависит от содержимого регистра, над пустым регистром ведёт к исключению Invalid Operation. После FINIT – да и вообще так в WinAPI принято в качестве дефолтного поведения – все исключения замаскированы, а маскированная реакция на пустой регистр – помещение в него вещественной неопределённости (разновидность NaN). Соответственно любая операция с NaN тоже порождает NaN. |
Сообщ.
#6
,
|
|
|
Цитата Славян @ Как бы негоже проводить инициализацию на каждый раз. Так, в Винде на 32-битах у меня вообще пишет недопустимую операцию при добавлении числа к пустой ячейке. В 16-битном режиме что-то складывает с давно там записанным. Команда "finit" добавляется в обработку каждой кнопки операции, поскольку неизвестно - с какой операции начнётся работа арифмометра. Я так понимаю - из "plus_ex" его лучше убрать ? Добавлено Цитата Qraizer @ Так и есть. Содержимое регистров помечается пустым. Это можно изменить в регистре тэгов, чем и "воскресить" хранящиеся там значения, однако смысла в этом нет никакого. FINIT предназначена для начальной инициализации, чтобы сбросить весь предыдущий неизвестный контекст, так что если контекст нужен, проще просто не выполнять инициализацию. У ТС второй FINIT абсолютно лишний. При попытке выполнить какою-либо операцию, которая зависит от содержимого регистра, над пустым регистром ведёт к исключению Invalid Operation. После FINIT – да и вообще так в WinAPI принято в качестве дефолтного поведения – все исключения замаскированы, а маскированная реакция на пустой регистр – помещение в него вещественной неопределённости (разновидность NaN). Соответственно любая операция с NaN тоже порождает NaN. Т.е. - вообще избавится от "finit" ? |
Сообщ.
#7
,
|
|
|
Так. Смотри. FPU – это устройство, работающее по запросу. Т.е. вот есть команда, оно её выполняет, закончил и есть следующая, выполняет следующую, нет следующей если, останавливается и ждёт новых команд. Он работает параллельно с CPU, асинхронно, поэтому ситуация, когда у него кончились команды, а новых от CPU ещё не поступило – это нормально. При этом в состоянии останова он естественно сохраняет свой контекст неизменным, чтобы как только новая команда, тут же исполнить её на этом контексте. Это не CPU, который не умеет стоять и постоянно должен что-то делать. (На самом деле умеет, но для этого есть специальные команды. Т.е. фактически он даже когда стоит, то не стоит, а выполняет команду "стоять".) Поэтому, когда ты ему даёшь первую команду, FPU может хранить неизвестный тебе контекст от предыдущего потока исполнения. Для этого и нужна FINIT: полностью нейтрализовать влияние предыдущего контекста.
Но требуется это только в начале работы. Как только ты сделал FINIT, далее ты уже можешь управлять FPU единолично, т.к. он находится под контролем твоей программы. Т.к. ты можешь прогнозировать его состояние, сбрасывать контекст требуется очень редко. Можно сказать, что в подавляющем большинстве случаев и не требуется вовсе. (Если это не так, имеет смысл пересмотреть архитектуру приложения, чем заморачиваться многократными сбросами контекста по ходу её выполнения. Ну и есть ещё особые случаи, типа обработки исключительных ситуаций, чтобы сбросить состояние ошибки и вернуть FPU в нормальный режим.) Увы, что-то конкретное посоветовать по твоему коду сложно. Непонятно даже, как ты получаешь числа из полей редактирования, ибо GetWindowText() возвращает в EAX длину текста в поле, переданного в приложение, а не введённое в него значение. И это не говоря уже о SetWindowText() которая работает с текстами, а не числами. По меньшей мере FLDZ не нужна, т.к. FLD и так загружает (теоретически) в вершину стека первый операнд, и не нужен второй FINIT, т.к. он полностью сбрасывает весь предыдущий контекст, и толку было ранее что-либо загружать. |
Сообщ.
#8
,
|
|
|
Добавлю, что периодическое использование finit маскирует ошибки в программе, что не есть хорошо.
Любая нормальная функция должна "убирать за собой". Т.е. внесла 3 числа, 3 же числа с вершины стека и удалила (за исключением случая, когда нужно вернуть значение в регистре st0). Если где-то есть ошибка, finit её прикроет, но от этого она никуда не денется. К тому же, функции могут вызываться друг за другом (хотя это не очень рекомендуется из-за небольшого размера стека FPU), когда результат предыдущей функции будет нужен далее. И finit удалит результат предыдущей функции. Например, ln(x)+sqrt(y): 1. Загружаем x [st0=x] 2. Вызываем ln, получаем результат [st0=ln(x)] 3. Загружаем y [st0=y, st1=ln(x)] 4. Вызываем sqrt, получаем результат [st0=sqrt(y), st1=ln(x)] – если в sqrt будет finit, то st1 очистится (пометится как очищенный) 5. faddp – складываем x и y (если в sqrt был finit, то ничего не получится... и даже исключение будет замаскировано) |
Сообщ.
#9
,
|
|
|
Цитата Qraizer @ Так. Смотри. FPU – это устройство, работающее по запросу. Т.е. вот есть команда, оно её выполняет, закончил и есть следующая, выполняет следующую, нет следующей если, останавливается и ждёт новых команд. Он работает параллельно с CPU, асинхронно, поэтому ситуация, когда у него кончились команды, а новых от CPU ещё не поступило – это нормально. При этом в состоянии останова он естественно сохраняет свой контекст неизменным, чтобы как только новая команда, тут же исполнить её на этом контексте. Это не CPU, который не умеет стоять и постоянно должен что-то делать. (На самом деле умеет, но для этого есть специальные команды. Т.е. фактически он даже когда стоит, то не стоит, а выполняет команду "стоять".) Поэтому, когда ты ему даёшь первую команду, FPU может хранить неизвестный тебе контекст от предыдущего потока исполнения. Для этого и нужна FINIT: полностью нейтрализовать влияние предыдущего контекста. Но требуется это только в начале работы. Как только ты сделал FINIT, далее ты уже можешь управлять FPU единолично, т.к. он находится под контролем твоей программы. Т.к. ты можешь прогнозировать его состояние, сбрасывать контекст требуется очень редко. Можно сказать, что в подавляющем большинстве случаев и не требуется вовсе. (Если это не так, имеет смысл пересмотреть архитектуру приложения, чем заморачиваться многократными сбросами контекста по ходу её выполнения. Ну и есть ещё особые случаи, типа обработки исключительных ситуаций, чтобы сбросить состояние ошибки и вернуть FPU в нормальный режим.) Увы, что-то конкретное посоветовать по твоему коду сложно. Непонятно даже, как ты получаешь числа из полей редактирования, ибо GetWindowText() возвращает в EAX длину текста в поле, переданного в приложение, а не введённое в него значение. И это не говоря уже о SetWindowText() которая работает с текстами, а не числами. По меньшей мере FLDZ не нужна, т.к. FLD и так загружает (теоретически) в вершину стека первый операнд, и не нужен второй FINIT, т.к. он полностью сбрасывает весь предыдущий контекст, и толку было ранее что-либо загружать. Я скорректировал код в соответствии с рекомендациями: ... wmcommand: movzx eax,word ptr [ebp+10h] cmp eax,..h ;id_but --> "цифра или символ точка" je nabor cmp eax,1Ch ;id_but --> "+" je plus ... cmp eax,24h ;id_but --> "=" je itog ... jmp defwndproc ;обработка нажатия кнопок: nabor: ... call SetWindowTextA@8 ;набрали 1-e число ;в предыдущем варианте я ошибся с функцией ... plus: ;нажали "+" mov edx,0 ;очищаем регистр и... mov edx,hbutS ;...сохраняем id кнопки --> "+" mov str1,eax ;сохраняем 1-е число finit ;инициируем сопроцессор fld str1 ;str1-->st(0) call clear ;очищаем дисплей ... ;набрали 2-е число...число набирается и остаётся на дисплее ... itog: ;нажали "=" cmp edx,hbutS ;если нажали "+"... je plus_ex ;...переходим сюда...не переходим ... plus_ex: call clear ;очищаем дисплей...очистка не срабатывает mov str2,eax ;сохраняем 2-e число в str2 mov eax,buf ;освобождаем буфер fadd str2 ;st(0)+str2-->st(0) fst buf ;st(0)-->buf fwait push buf ;здесь сумма push [hWndEdt] call SetWindowTextA@8 ;выводим её на дисплей jmp exit ... exit: mov eax,0 jmp finish ... finish: pop edi pop esi pop ebx pop ebp ret 16 winproc endp clear proc push Edt push [hWndEdt] call SetWindowTextA@8 ret clear endp end go После нажатия "=" на дисплее остаётся 2-е набранное число. Убрал из "plus_ex:" всё, кроме "call clear" и "jmp exit" - картина не меняется. Похоже, что код в метке "itog:" не работает и переход к "plus_ex:" не происходит. В чём дело - понять не могу. Помогите разобратся. -------------------- И ещё один момент: Цифры на дисплее набираются путём нажатия на кнопки арифмометра. В общем случае число - это "string". Число добавляется на дисплей при помощи SetWindowTextA, в результате в ЕАХ остаётся hex-вариант числа (?). И тогда конвертация идёт по цепочке hex-->bin-->hex, или, всё-таки, str-->hex-->bin-->hex-->str ? |
Сообщ.
#10
,
|
|
|
Цитата cupoma58 @ Ну, по приведённым фрагментам ничего сказать нельзя. Что такое hbutS, где лежит в EDX, каковы значения EAX и откуда ни берутся? Ты б полный текст привёл, что ли... В чём дело - понять не могу. Помогите разобратся. Добавлено Второй вопрос тоже непонятен. Цитата cupoma58 @ Если ты, у которого есть полный код, не знаешь, откуда мы-то можем знать? в результате в ЕАХ остаётся hex-вариант числа (?) |
Сообщ.
#11
,
|
|
|
Цитата Qraizer @ Ну, по приведённым фрагментам ничего сказать нельзя. Что такое hbutS, где лежит в EDX, каковы значения EAX и откуда ни берутся? Ты б полный текст привёл, что ли... Целиком код очень большой, уже сейчас более 700 строк. Я выбрал код обработки операции "+", он типичный, из "неработающих": .386 ... WinProc proc push ebp mov ebp,esp push ebx push esi push edi ... cmp dword ptr [ebp+0Ch],WM_COMMAND je wmcommand ... jmp defwndproc ... wmcommand: mov eax,hbut ;хэндл одной из цифровых кнопок или "." cmp [ebp+14h],eax ;нажали цифру или "." je nabor ;переходим сюда ... mov eax,hbutS ;хэндл "+" cmp [ebp+14h],eax ;нажали "+" ? je plus ;переходим сюда ... mov eax,hbutI ;хэндл "=" cmp [ebp+14h],eax ;нажали "=" ? je itog ;переходим сюда ... mov eax,hbutC ;хэндл "С" cmp [ebp+14h],eax ;нажали "C" ? (butC db " ",0) je clear ;переходим сюда ... jmp exit nabor: push 16 push offset buf ;получаем содержимое буфера (символы) push [hedt] call GetWindowTextA@12 add eax,offset buf ;добавляем его к тому, что в еах push 16 push eax ;туда-же добавляем push [EBP+14h] ;символ кнопки call GetWindowTextA@12 push offset buf ;набранное число (string или hex - что преобразовывать в bin ?) push [hedt] call SetWindowTextA@8 ;где-то здесь будет конвертация mov esi,eax ;сбрасываем набранные символы в esi: в обработке используем 2 сохранённых регистра - esi и edi jmp exit plus: ;нажимаем "+" mov str1,esi ;сохраняем 1-e число в str1 и... mov esi,0 ;...очищаем esi mov edi,hbutS ;сохраняем хэндл использованной операционной кнопки в edi call clearproc ;очищаем дисплей jmp exit ... clear: call clearproc jmp exit ... itog: ;набрали 2-е число, НАЖИМАЕМ "=" и смотрим: cmp hbutS,edi ;если разница содержимого = 0 то... je plus_ex ;...переходим сюда <--- ПЕРЕХОДА НЕ ПОЛУЧАЕТСЯ ... jmp exit plus_ex: call clearproc ;очищаем дисплей <---ЕСЛИ ОТАВИТЬ ЭТО mov str2,esi ;сохраняем 2-е число в str2 и... mov esi,0 ;...очищаем esi mov edi,0 ;убираем хэндл кнопки из edi mov eax,buf ;освобождаем буфер finit ;инициируем сопроцессор fld str1 ;str1-->st(0) fld str2 ;str2-->st(0),str1-->st(1) fadd ;str1+str2-->st(0) fstp buf ;st(0)-->buf ;где-то здесь будет конвертация push buf ;здесь сумма push [hedt] ;выводим её на дисплей call SetWindowTextA@8 jmp exit <--- И ЭТО - ДИСПЛЕЙ ДОЛЖЕН ОЧИСТИТСЯ - ЭТОГО НЕ ПРОИСХОДИТ ... exit: mov eax,0 jmp finish ... finish: pop edi pop esi pop ebx pop ebp ret 16 winproc endp clearproc proc push offset Edt push [hedt] call SetWindowTextA@8 ret clearproc endp end go Возможно, что команды сопроцессора, которыми я пользуюсь, не соответствуют процессору, который у меня стоит (IntelAtom не старше 2006 г.), но из 3-х "прямых" арифметических операций срабатывает только одна - извлечение квадратного корня: ... sqr: call clearproc mov str1,esi mov edi,0 mov eax,buf finit fld str1 fsqrt fst buf fwait push offset buf push [hedt] call SetWindowTextA@8 jmp exit ... возведение в квадрат: не работает - только очистка дисплея ... n2: call clearproc mov str1,esi mov edi,0 mov eax,buf finit fld str1 ;str1-->st(0) fld str1 ;str1-->st(0),str1-->st(1) fmul ;str1*str1-->st(0) fst buf push offset buf push [hedt] call SetWindowTextA@8 jmp exit ... возведение в куб: не работает - только очистка дисплея ... n3: call clearproc mov str1,esi mov edi,0 mov eax,buf finit fld str1 ;str1-->st(0) fld str1 ;str2-->st(0),str1-->st(1) fmul ;str1*str1-->st(0) fld st(0) ;копируем st(0) fld str1 fmul ;(str1*str1)*str1-->st(0) fst buf fwait push offset buf push [hedt] call SetWindowTextA@8 jmp exit ... Даже без конвертации что-то должно появлятся. |
Сообщ.
#12
,
|
|
|
Цитата cupoma58 @ FPU в обед сто лет исполняется. Его архитектура не менялась со времён 80386.Возможно, что команды сопроцессора, которыми я пользуюсь, не соответствуют процессору, который у меня стоит Цитата cupoma58 @ Похоже, у тебя в коде для FPU две проблемы.из 3-х "прямых" арифметических операций срабатывает только одна - извлечение квадратного корня: Во-первых, я выше говорил, что CPU с FPU работают асинхронно. Это значит, что когда FPU выполняет некую команду, CPU идёт себе спокойно дальше по своим командам, и если FPU требуется некое время для завершения, CPU может уйти уже достаточно далеко. Если тебе в CPU нужны результаты FPU, следует синхронизироваться с ним. Для синхронизации предназначена FWAIT, которая останавливает CPU до того момента, пока FPU не закончит выполнять свою команду. FSQRT у тебя содержит такую синхронизацию, поэтому неудивительно, что она работает, но второй фрагмент наверняка использует результат, который FPU ещё не вычислил и потому не сохранил в памяти. Третий фрагмент сам по себе неправильный, см. ниже. Во-вторых, становится понятно, почему тебе кругом понадобились FINIT. Ты неправильно работаешь со стеком. Ты, похоже, ожидаешь, что после любой команды операнды из стека изымаются, но на самом деле этого не происходит. Например, команда FMUL помещает результат в ST(0), замещая один из сомножителей, но она при этом оставляет в ST(1) второй. Команда FST передаёт вершину стека в приёмник, но при этом она сохраняет неизменным и сам ST(0). Тебе либо следует пользоваться этим, либо нейтрализовывать этот эффект вариантами команд с побочным эффектом на стек, иначе со временем стек весь будет забит ненужными данными, все 8 регистров будут непусты, и поэтому новые FLD будут вызывать исключительные ситуации переполнения стека. FINIT, конечно, всё очищает, поэтому это как бы решение, но я выше говорил, что это плохое решение. Лучше правильно работать со стеком. Например: sqr: ; ... fld str1 fsqrt fstp buf fwait ... n2: ; ... fld str1 ;str1-->st(0) fld str1 ;str1-->st(0),str1-->st(1) fmulp ;str1*str1-->st(1) and pop fstp buf ;store and pop fwait ... n3: ; ... fld str1 ;str1-->st(0) fmul st(0) ;str1*str1-->st(0) fld str1 fmulp ;(str1*str1)*str1-->st(1) and pop fstp buf ;store and pop fwait n2: ; ... fld str1 ;str1-->st(0) fmul st(0) ;str1*str1-->st(0) fstp buf ;store and pop fwait ... n3: ; ... fld str1 ;str1-->st(0) fmul st(0) ;str1*str1-->st(0) fmul str1 ;(str1*str1)*str1-->st(0) fstp buf ;store and pop fwait Добавлено P.S. И всё ещё непонятно, как ты получаешь данные из текстовых полей и как туда передаёшь результаты. По факту, GetWindowText() и SetWindowText() работают с текстом, но FPU требует чисел. Я не вижу кода, который осуществлял бы преобразования. |
Сообщ.
#13
,
|
|
|
Цитата Qraizer @ Инструкции CPU и FPU отправляются в один поток исполнения.Во-первых, я выше говорил, что CPU с FPU работают асинхронно. Это значит, что когда FPU выполняет некую команду, CPU идёт себе спокойно дальше по своим командам, и если FPU требуется некое время для завершения, CPU может уйти уже достаточно далеко. Если тебе в CPU нужны результаты FPU, следует синхронизироваться с ним. Для синхронизации предназначена FWAIT, которая останавливает CPU до того момента, пока FPU не закончит выполнять свою команду. Такого, чтобы CPU ушёл далеко вперёд, не дождавшись результата работы FPU, нет уже со времён царя Гороха Intel: Цитата Инструкции могут исполняться одновременно, но они всё же находятся в едином потоке инструкций, поэтому их логическая последовательность сохраняется, и процессор будет ждать завершения FPU безо всяких fwait'ов (например, в последовательности fstp [X] + mov eax,[X] инструкция mov eax,[X] будет выполнена только после завершения fstp [X]). Единственное, что может быть – это перестановка инструкций, результаты которых не влияют друг на друга, но это уже другая тема, не связанная непосредственно с FPU.Because the integer unit and x87 FPU are separate execution units, it is possible for the processor to execute floating-point, integer, and system instructions concurrently. No special programming techniques are required to gain the advantages of concurrent execution. (Floating-point instructions are placed in the instruction stream along with the integer and system instructions.) However, concurrent execution can cause problems for floating-point exception handlers. Инструкция fwait (wait) уже давно используется только для синхронизации исключений. Так что в этом проблемы быть точно не может. Добавлено Можно даже провести маленький эксперимент (без чтения мануалов): fld1 rdtsc mov ecx,eax fsin rdtsc sub eax,ecx fstp st Заменяем fsin на fadd st,st (менее ресурсоёмкое вычисление), получаем 21-36. Убираем обе, получаем почти то же, что и с fadd (но чаще 21, чем 36). Если бы CPU просто посылал FPU "задание" для исполнения, результат был бы одинаковым (или почти одинаковым). |
Сообщ.
#14
,
|
|
|
Цитата Qraizer @ ]Похоже, у тебя в коде для FPU две проблемы. Во-первых... P.S. И всё ещё непонятно, как ты получаешь данные из текстовых полей и как туда передаёшь результаты. По факту, GetWindowText() и SetWindowText() работают с текстом, но FPU требует чисел. Я не вижу кода, который осуществлял бы преобразования. Благодарю за советы. Заменю fst на fstp. Что касается "текст-число-текст" - эти процедуры ещё в процессе. Finit я использую в каждой операции потому, что неизвестно - с какой начнётся работа. И мне, всё-таки, непонятно: почему не происходит перехода в цепочке plus-itog-plus_ex ? В Java, при ветвлении, используется сравнение с типом арифметического действия (+,-...). Я сохраняю хэндл кнопки в edi (plus) и в itog проверяю - какая кнопка была нажата "cmp hbut,edi". Почему не работает ? |
Сообщ.
#15
,
|
|
|
Цитата cupoma58 @ Цитата Qraizer @ ]Похоже, у тебя в коде для FPU две проблемы. Во-первых... P.S. И всё ещё непонятно, как ты получаешь данные из текстовых полей и как туда передаёшь результаты. По факту, GetWindowText() и SetWindowText() работают с текстом, но FPU требует чисел. Я не вижу кода, который осуществлял бы преобразования. Благодарю за советы. Заменю fst на fstp. Что касается "текст-число-текст" - эти процедуры ещё в процессе. Finit я использую в каждой операции потому, что неизвестно - с какой начнётся работа. И мне, всё-таки, непонятно: почему не происходит перехода в цепочке plus-itog-plus_ex ? В Java, при ветвлении, используется сравнение с типом арифметического действия (+,-...). Я сохраняю хэндл кнопки в edi (plus) и в itog проверяю - какая кнопка была нажата "cmp hbut,edi". Почему не работает ? Всё - разобрался. В цепочке "oper-->itog-->oper_ex" были лишние команды. Теперь по сопроцессору: мой компилятор (masm32v11) обозвал команду fmulp - инвалидной и сказал, что st(0) не может быть первым операндом (fmul st(0)). Не работает самый простой код: ... ; st st(1) st(2) ... st(7) finit ; - - - - fld str1 ; str1 - - - fld str1 ; str1 str1 - - fmul ; itog - - - fstp ; - - - - fwait ... Предложенные варианты кода - так-же не работают. Всё заработало, а возведение в квадрат и в куб - не хочет ! Причём, не работает арифметический код, предварительная очистка дисплея - происходит. Если, только, это очистка. Что посоветуете ? |