{"id":165,"date":"2009-06-26T16:24:23","date_gmt":"2009-06-26T15:24:23","guid":{"rendered":"http:\/\/netrix.org.pl\/?p=165"},"modified":"2010-01-24T14:51:25","modified_gmt":"2010-01-24T13:51:25","slug":"defekt-optymalizacji-kompilatora-x64","status":"publish","type":"post","link":"http:\/\/netrix.org.pl\/index.php\/2009\/06\/26\/defekt-optymalizacji-kompilatora-x64\/","title":{"rendered":"Defekt optymalizacji kompilatora x64"},"content":{"rendered":"<p>Podczas dalszego kodowania mojego silnika natrafi\u0142em na bardzo dziwny b\u0142\u0105d kompilatora Visual Studio. Zaczynaj\u0105c od pocz\u0105tku &#8211; mam oto taki kod:<\/p>\n<pre lang=\"cpp\" line=\"0\">\t\r\nenum\r\n{\r\n\t\/\/ Rozmiary p\u00f3l\r\n\tMAX_BITS_INDEX = sizeof(Size_t) * 4,\r\n\tMAX_BITS_MAGIC = sizeof(Size_t) * 4,\r\n\t\/\/ Maksymalne warto\u015bci p\u00f3l (Przesuni\u0119cie 1 w dw\u00f3ch operacjach, poniewa\u017c inaczej kompilator nie daje rady)\r\n\tMAX_INDEX = ((1 << MAX_BITS_INDEX \/ 2) << MAX_BITS_INDEX \/ 2) - 1,\r\n\tMAX_MAGIC = ((1 << MAX_BITS_MAGIC \/ 2) << MAX_BITS_MAGIC \/ 2) - 1\r\n};\r\n\/* ... *\/\r\n\r\n\/\/ handle = 0x0000000400000006;   - przykladowo\r\n\/\/ Size_t ma rozmiar wska\u017anika (jest zale\u017cny od platformy)\r\nSize_t value = handle &#038; MAX_MAGIC;\r\n<\/pre>\n<p>Ot\u00f3\u017c problem z tym kodem jest taki, \u017ce gdy zostanie skompilowany na platform\u0119 x64, zostaje wygenerowany nast\u0119puj\u0105cy kod w assemblerze:<\/p>\n<pre lang=\"asm\">\r\n    79:                 {\r\n    80:                         Size_t value = handle & MAX_MAGIC;\r\n\r\n000000013FC96F94  mov         rax,qword ptr [handle]\r\n000000013FC96F9C  mov         qword ptr [value],rax\r\n\r\n    81:                         if(value == *it) return true; \/\/ Dalszy kod \r\n<\/pre>\n<p>Jak wida\u0107 problem polega na braku kluczowej instrukcji and, kt\u00f3rej zadaniem jest odci\u0119cie najstarszych 32-bit\u00f3w. Dla por\u00f3wnania kod assemblera wygenerowanego dla platformy x86 jest nast\u0119puj\u0105cy:<\/p>\n<pre lang=\"asm\">\r\n    79:                 {\r\n    80:                         Size_t value = handle & MAX_MAGIC;\r\n00DC9DDC  mov         eax,dword ptr [handle]\r\n00DC9DDF  and          eax,0FFFFh\r\n00DC9DE4  mov         dword ptr [value],eax\r\n    81:                         if(value == *it) return true; \/\/ Dalszy kod \r\n<\/pre>\n<p>Tutaj instrukcja ta wyst\u0119puje.<\/p>\n<p>B\u0142\u0105d ten jednak nie wyst\u0119puje gdy samemu sprecyzuj\u0119 sta\u0142\u0105, tj.:<\/p>\n<pre lang=\"cpp\">\r\nSize_t value = handle & 0xffffffff;\r\n<\/pre>\n<p>W tym przypadku zostanie wygenerowany poprawny kod. <\/p>\n<p>Wniosek jest taki, \u017ce kompilator widz\u0105c operacj\u0119 and zmiennej ze sta\u0142\u0105 typu enum (kt\u00f3ry przechowuje warto\u015bci 32-bitowe), traktuje t\u0105 zmienn\u0105 jako typ 32-bitowy. W tym przypadku stwierdza, \u017ce instrukcja and nie ma sensu, bo warto\u015b\u0107 MAX_MAGIC zawiera maksymaln\u0105 warto\u015b\u0107 (0xffffffff). Wed\u0142ug mnie jest to ewidentny b\u0142\u0105d i nie powinno takie co\u015b wyst\u0105pi\u0107.<\/p>\n<p>\/\/ Edit :)<br \/>\nProblemem oczywi\u015bcie jest to, \u017ce enum jest tak naprawd\u0119 typem int, wi\u0119c si\u0119 dok\u0142adnie tak zachowuje.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Podczas dalszego kodowania mojego silnika natrafi\u0142em na bardzo dziwny b\u0142\u0105d kompilatora Visual Studio. Zaczynaj\u0105c od pocz\u0105tku &#8211; mam oto taki kod: enum { \/\/ Rozmiary p\u00f3l MAX_BITS_INDEX = sizeof(Size_t) * 4, MAX_BITS_MAGIC = sizeof(Size_t) * 4, \/\/ Maksymalne warto\u015bci p\u00f3l (Przesuni\u0119cie 1 w dw\u00f3ch operacjach, poniewa\u017c inaczej kompilator nie daje rady) MAX_INDEX = ((1<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[82,179,184,54],"_links":{"self":[{"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/165"}],"collection":[{"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/comments?post=165"}],"version-history":[{"count":6,"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/165\/revisions"}],"predecessor-version":[{"id":404,"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/165\/revisions\/404"}],"wp:attachment":[{"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/media?parent=165"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/categories?post=165"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/tags?post=165"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}