• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-16  評(píng)論-116  文章-0  trackbacks-0
            轉(zhuǎn)載請(qǐng)注明出處:http://www.shnenglu.com/greatws/archive/2008/09/05/61057.html

            32位系統(tǒng),eax,ecx,edx,ebx這些寄存器都是32位的,而要使用一個(gè)64位的變量,需要用到2個(gè)寄存器,或者一個(gè)寄存器用到2次,往往在某些地方就會(huì)出現(xiàn)意想不到的問(wèn)題。

            今天參加了CSDN的英雄會(huì),有幸見(jiàn)了些名人,回到家上CSDN,看到個(gè)帖子
            http://topic.csdn.net/u/20080905/16/3823c75d-c33b-4ea0-83b1-8386d03e6c6c.html
            具體內(nèi)容:

            題目:
            1、不能用庫(kù)函數(shù),要求達(dá)到效率o(1);
            2、將符號(hào)'@'插入字符串ptr的首位,字符串ptr原內(nèi)容按照原來(lái)的順序排在'@'之后.

            void insert(char *str, char tmp)
            {
                 
            //填寫(xiě)代碼:
            }

            void main(void)
            {
                
            char ptr[16]="abcdefg";
                
            char temp='@';
                insert(ptr, temp);
                printf(
            "%s\n;",ptr);
            }


            我很容易想到
            void insert(char *str, char tmp)
            {
                
            *((__int64*)(str + 1)) = *(__int64*)str;
                
            *str = tmp;
            }

            可是結(jié)果卻很令人驚訝,輸出@abcddfg,有一個(gè)字節(jié)不對(duì)。仔細(xì)一想,應(yīng)該是把64位變量放到2個(gè)寄存器中了。
            用OD反一下,看下主函數(shù)里的關(guān)鍵地方,OH,前面分配棧的一句是sub esp,18

             100401030  /$  A1 DCB64000   mov     eax, dword ptr [40B6DC]  
             200401035  |?  8945 EC       mov     dword ptr [ebp-14], eax
             300401038  |?  8B0D E0B64000 mov     ecx, dword ptr [40B6E0]
             40040103E  |?  894D F0       mov     dword ptr [ebp-10], ecx
             500401041  |?  33D2          xor     edx, edx                         ;  namespac.0040E2B8
             600401043  |?  8955 F4       mov     dword ptr [ebp-C], edx
             700401046  |?  8955 F8       mov     dword ptr [ebp-8], edx
             800401049  |?  C645 EB 40    mov     byte ptr [ebp-15], 40
             90040104D  |?  0FB645 EB     movzx   eax, byte ptr [ebp-15]
            1000401051  |.  50            push    eax
            1100401052  |?  8D4D EC       lea     ecx, dword ptr [ebp-14]
            1200401055  |?  51            push    ecx
            1300401056  |.  E8 A5FFFFFF   call    00401000
            140040105B  |?  83C4 08       add     esp, 8
            第一行,0x04B6DC就是常量字符串"abcdefg"的地址,把分2次每次4個(gè)送入棧,完成char ptr[16]的初始化,第8 9行是把'@'放入eax,第10行把最后一個(gè)參數(shù)入棧,也就是@,11行把ebp-14也就是ptr傳給ecx,12行把ptr入棧,也就是倒數(shù)第二個(gè)參數(shù),然后調(diào)用下面的函數(shù)。

             100401000  /$  55            push    ebp
             200401001  |.  8BEC          mov     ebp, esp
             300401003  |.  8B45 08       mov     eax, dword ptr [ebp+8]
             400401006  |.  8B4D 08       mov     ecx, dword ptr [ebp+8]
             500401009  |?  8B11          mov     edx, dword ptr [ecx]
             60040100B  |.  8950 01       mov     dword ptr [eax+1], edx
             70040100E  |?  8B49 04       mov     ecx, dword ptr [ecx+4]
             800401011  |?  8948 05       mov     dword ptr [eax+5], ecx
             900401014  |?  8B55 08       mov     edx, dword ptr [ebp+8]
            1000401017  |.  8A45 0C       mov     al, byte ptr [ebp+C]
            110040101A  |.  8802          mov     byte ptr [edx], al
            120040101C  |?  5D            pop     ebp
            130040101D  |.  C3            retn
            3 4行把剛才入棧的ptr指針存入eax,ecx
            第5行把char ptr[16]的前4個(gè)字節(jié)abcd存入edx,也就是0x64636261,注意高低位
            然后把edx里的4個(gè)字節(jié)的數(shù),寫(xiě)入ptr+1的位置,可見(jiàn)問(wèn)題就出現(xiàn)在這里,一下寫(xiě)入4個(gè)字節(jié),在ptr+1到ptr+4的位置,由于*(ptr+4)里的內(nèi)容并未保存,所以被覆蓋了,導(dǎo)致后面第2次讀取的數(shù)據(jù)不正確,最后的結(jié)果也不會(huì)輸出正確

            看了下邊網(wǎng)友的回帖,比較好的方法就是用移位,本來(lái)是數(shù),移位肯定不會(huì)出問(wèn)題,使用的是shld雙精度左移指令(為什么是左移不是右移?同樣注意高低位),保證數(shù)據(jù)不會(huì)丟失
            void insert(char *str, char tmp)
            {
                
            *(__int64*)str <<= 8;
                
            *str = tmp;
            }
            運(yùn)行,結(jié)果正確

            可以看出,在32位系統(tǒng)使用64位變量需要很注意,尤其是在賦值的時(shí)候,比如我上邊的例子。往往在一個(gè)大工程里,出現(xiàn)這樣的問(wèn)題,很難查出原因來(lái),因此,需要格外注意。還有在多線程的時(shí)候,一個(gè)讀一個(gè)寫(xiě),由于使用2個(gè)寄存器,就有可能在一個(gè)寫(xiě)線程操作到一個(gè)64位數(shù)的32位的時(shí)候,線程正好切換到讀線程,導(dǎo)致產(chǎn)生一些奇怪的數(shù)據(jù),而且這種奇怪的情況并不是每次運(yùn)行都能體現(xiàn)出來(lái),造成的損失可想而知。所以對(duì)跨線程使用64位變量必須嚴(yán)格進(jìn)行同步。


            by greatws
            posted on 2008-09-05 22:22 greatws 閱讀(3386) 評(píng)論(4)  編輯 收藏 引用

            評(píng)論:
            # re: 32位系統(tǒng)上使用64位變量需要特別注意 2008-09-06 00:24 | clear
            *((__int64*)(str + 1)) = *(__int64*)str;

            這個(gè)可是即使在64位系統(tǒng)上,應(yīng)該也不能保證正確的代碼吧...
            _int64數(shù)據(jù)在特定系統(tǒng)上都是有特定對(duì)齊要求的,不能簡(jiǎn)單的把一個(gè)地址轉(zhuǎn)換到_int64*的說(shuō)  回復(fù)  更多評(píng)論
              
            # re: 32位系統(tǒng)上使用64位變量需要特別注意 2008-09-06 00:26 | clear
            就是_int32*也是有對(duì)齊要求的,只不過(guò)x86系統(tǒng)把這個(gè)對(duì)齊要求降低到1罷了
            在很多嵌入式系統(tǒng)里面,也是要求4字節(jié)對(duì)齊32位數(shù)據(jù)的說(shuō)  回復(fù)  更多評(píng)論
              
            # re: 32位系統(tǒng)上使用64位變量需要特別注意[未登錄](méi) 2008-09-06 14:05 | megax
            這么做的意義是什么呢?這么做肯定是非法操作啊,沒(méi)看懂。。。  回復(fù)  更多評(píng)論
              
            # re: 32位系統(tǒng)上使用64位變量需要特別注意 2008-09-07 14:47 | 陳梓瀚(vczh)
            編譯器的bug……  回復(fù)  更多評(píng)論
              

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            久久九色综合九色99伊人| 少妇久久久久久久久久| 99久久无码一区人妻| 成人国内精品久久久久影院| 香蕉久久一区二区不卡无毒影院| 国产精品永久久久久久久久久| 欧美午夜精品久久久久久浪潮| 久久九九兔免费精品6| 久久精品国产亚洲麻豆| 久久精品国产久精国产果冻传媒 | 久久99精品九九九久久婷婷| 中文精品99久久国产| 久久免费视频观看| 亚洲精品白浆高清久久久久久| 成人精品一区二区久久久| 奇米影视7777久久精品| 久久涩综合| 色噜噜狠狠先锋影音久久| 亚洲午夜久久久影院伊人| 久久久久久国产a免费观看黄色大片 | 亚洲精品无码久久久久去q| 99久久国产亚洲高清观看2024| 新狼窝色AV性久久久久久| 日日狠狠久久偷偷色综合96蜜桃| 久久综合综合久久97色| 久久精品中文字幕无码绿巨人| 97香蕉久久夜色精品国产| 日韩亚洲国产综合久久久| 久久亚洲国产欧洲精品一| 精品久久久久久国产潘金莲| 久久精品国产2020| 久久久国产亚洲精品| 久久久久99这里有精品10| 久久久午夜精品| 久久精品一区二区三区AV| 久久伊人五月丁香狠狠色| 亚洲人AV永久一区二区三区久久 | 韩国无遮挡三级久久| 国产精品久久免费| 久久精品国产只有精品2020| 国内精品久久久人妻中文字幕|