tag:blogger.com,1999:blog-1702873441071265539.post8332433494513969709..comments2023-05-29T19:02:20.570+03:00Comments on Блог GunSmoker-а: Задачка №18ВGunSmokerhttp://www.blogger.com/profile/15611696588191431330noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-1702873441071265539.post-18371439171895203052015-07-18T03:41:42.408+03:002015-07-18T03:41:42.408+03:00Вообще-то процессору вообще проще обнулять регистр...Вообще-то процессору вообще проще обнулять регистр целиком и сравнивать на равенство полного регистра с нулём, а не выделять из регистра байты и оперировать с ними.<br /><br />Собственно, при включенной оптимизации Delphi компилирует именно такой код, поэтому Boolean выше будет, фактически, скомпилирован в BOOL. При выключенной оптимизации компилятор Delphi компилирует буквальный код.<br /><br />Проблема в том, что мы не контролируем вызывающий нас код (код Windows), а там может быть что угодно - как и сравнение младшего байта (навряд ли), так и сравнение полного регистра (скорее всего). Компилятору C вообще не нужно волноваться о "результат то в eax, то в ax, то в al". <br /><br />Более того, не всегда даже выполняется "не-ноль - это истина" - иногда функции Windows требуют <a href="http://www.transl-gunsmoker.ru/2009/04/bool-boolean-integer.html" rel="nofollow">конкретного значения для True</a>.GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-87731144480690672382015-07-14T13:34:29.690+03:002015-07-14T13:34:29.690+03:00Думаю, что скажу банальность - но разве не логично...Думаю, что скажу банальность - но разве не логично компилятору делать код, проверяющий на True и False простой проверкой младшего бита в младшем разряде регистра?<br />Ведь тогда не будет проблемы, когда результат то в eax, то в ax, то в al...AlnZhttps://www.blogger.com/profile/04024511757099280427noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-80385050430338123112015-05-01T19:31:54.848+03:002015-05-01T19:31:54.848+03:00Абсолютно верно :)
Вы практически подошли к концу ...Абсолютно верно :)<br />Вы практически подошли к концу решения задачи, но... :)Александр (Rouse_) Багельhttps://www.blogger.com/profile/03072586754182036553noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-65218714069553138552015-05-01T16:53:24.541+03:002015-05-01T16:53:24.541+03:00Я понял, что Вы имели в виду. Вы правы. Постами вы...Я понял, что Вы имели в виду. Вы правы. Постами выше я руководствовался, исходя из справки, что результат может принимать два значения "нуль" и "не нуль". Отсюда происходит проверка на нулевое значение: <i>cmp eax, 0</i> и <i>test eax, eax</i> , обе установят флаг нуля. Написав <i>cmp eax, 0</i> я хотел подчеркнуть именно сравнение с нулем.<br /><br />И эта заковыка даже на win32 демонстрирует это поведение - не обнуляется весь регистр, как это происходит в случае с явным идентификатором <i>FALSE</i> :<br />function EnumWindowsProc(const AWnd: HWND; const AParam: LPARAM): Boolean; stdcall;<br />begin<br /> Result := not (AWnd = HWND(AParam));<br />end;Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-20066468491959170772015-05-01T15:00:22.790+03:002015-05-01T15:00:22.790+03:00ЗЫ: это с учетом разницы между BOOL и Boolean (осо...ЗЫ: это с учетом разницы между BOOL и Boolean (особенно второй вариант подвержен ошибке)Александр (Rouse_) Багельhttps://www.blogger.com/profile/03072586754182036553noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-87868157428260899092015-05-01T14:58:15.635+03:002015-05-01T14:58:15.635+03:00Ой, пардон - что-то странное сказал.
Конечно же:...Ой, пардон - что-то странное сказал. <br /><br />Конечно же:<br /><br />test eax, eax<br />sbb eax, eax<br />inc eax<br /><br />и<br /><br />cmp eax, 1<br />sbb eax, eax<br />inc eax<br /><br />в EAX результатАлександр (Rouse_) Багельhttps://www.blogger.com/profile/03072586754182036553noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-13562990108773384222015-05-01T14:54:23.177+03:002015-05-01T14:54:23.177+03:00>> Не суть, какой инструкцией результат буде...>> Не суть, какой инструкцией результат будет проверен - логическим умножением или инструкцией сравнения.<br />Смотря как стравнивать :)<br />test eax, eax<br />jz<br />и <br />cmp eax, 1<br />jnz<br />по сути идентичны, но дадут разное поведение на 32 битном регистре :)<br />Александр (Rouse_) Багельhttps://www.blogger.com/profile/03072586754182036553noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-86198062335934861912015-05-01T14:17:29.798+03:002015-05-01T14:17:29.798+03:00Не суть, какой инструкцией результат будет провере...Не суть, какой инструкцией результат будет проверен - логическим умножением или инструкцией сравнения. Внимание на самом значении.<br />Я успел увидеть подсказку)). Но аномалий с ней, с подсказкой, не заметил. Это касается win32. У меня еще не возникало задач, которые вынудили бы установить 64-битную систему. Выходит в ней и закавыка. Дождусь ответ от знатоков win64.<br />А в win32 этот код работает по той причине, что кодогенератор создает такой код: <i>xor eax, eax</i> для выражения <i>Result := false</i>.<br />Внутри же <i>EnumWindows</i> результат не задействуется, но возвращается в <i>Button1Click</i> через переменную <i>fSuccess</i>:<br /><br />BOOL PseudoEnumWindows(..., WNDENUMPROC lpfn, ...)<br /> {<br /> UINT i;<br /> UINT cHwnd;<br /> HWND *phwndT;<br /> HWND *phwndFirst;<br /> BOOL fSuccess = TRUE;<br /> <br /> if ((cHwnd = BuildHwndList(..., &phwndFirst) == -1) {<br /> return FALSE;<br /> }<br /> <br /> phwndT = phwndFirst;<br /> for (i = 0; i < cHwnd; i++) {<br /> if (!(fSuccess = (*lpfn)(*phwndT, lParam)))<br /> break;<br /> phwndT++;<br /> }<br /> <br /> FinalizeHwndList;<br /><br /> return fSuccess;<br /> }<br /><br /><br />P.S.: Теги "bold, italic и href" - хорошо. Но очень не хватает "pre и code".Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-22389173852305173482015-05-01T13:07:54.149+03:002015-05-01T13:07:54.149+03:00Хотя, нет, это уже явная подсказка.
Тогда просто у...Хотя, нет, это уже явная подсказка.<br />Тогда просто упомяну, что сравнение идет через <br />test eax, eax<br />jzАлександр (Rouse_) Багельhttps://www.blogger.com/profile/03072586754182036553noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-74434869362121791952015-05-01T12:37:40.797+03:002015-05-01T12:37:40.797+03:00Этот комментарий был удален автором.Александр (Rouse_) Багельhttps://www.blogger.com/profile/03072586754182036553noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-13775573609371633532015-05-01T11:50:44.087+03:002015-05-01T11:50:44.087+03:00ну да. Если для BOOL будет eax , то для Boolean - ...ну да. Если для BOOL будет eax , то для Boolean - это al. Илья, это часть одного регистра.<br />Проблема в том, что старшие биты не будут инициализированы. А вызывающая подпрограмма проверяет результат на равенство нулю, то есть: равно нулю или не равно.<br />Наглядный листинг:<br />mov eax, 0FFFFFFFFh<br />mov al, 0 ; Result := false, инициализируется 1 байт при типе Boolean<br />; значение в регистре будет таким eax = 0FFFFFF00h<br />; а теперь проверочка<br />cmp eax, 0 ; if Result = 0 then<br /><br />В подпрограмме EnumWindowsProc что будет в регистре eax, в момент присваивания результата, неизвестно. И в 99,99% случаях вызывающая подпрограмма получит ненулевое значение.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-83295357251992752902015-04-30T21:53:05.656+03:002015-04-30T21:53:05.656+03:00И еще есть разница в регистрах, куда ложится резул...И еще есть разница в регистрах, куда ложится результат EnumWindowsProc. Для BOOL это будет eax, а для Boolean - другой. Как вариант - EnumWindowsProc вычитает значение не из того регистраAnonymoushttps://www.blogger.com/profile/15179843416881938538noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-70671153707985177592015-04-30T21:45:46.764+03:002015-04-30T21:45:46.764+03:00Возможно дело в типа, возвращаемом EnumWindowsProc...Возможно дело в типа, возвращаемом EnumWindowsProc? Boolean 1-байтный, в то время как BOOL 4-байтный. Не испортит ли это стек?Anonymoushttps://www.blogger.com/profile/15179843416881938538noreply@blogger.com