我知道int和其他32位數據類型適合寄存器。但是我不明白當我們的數據類型,比如1字節的char小於32位時會發生什麼。就像在字符的例子中,其餘的24位會發生什麼?它是否全部填充0?用一個詞來代表它不是太小?char數據類型如何在32位寄存器中表示?
更新:假設我有一個帶有char變量的C程序。它在註冊表中如何表示?
我知道int和其他32位數據類型適合寄存器。但是我不明白當我們的數據類型,比如1字節的char小於32位時會發生什麼。就像在字符的例子中,其餘的24位會發生什麼?它是否全部填充0?用一個詞來代表它不是太小?char數據類型如何在32位寄存器中表示?
更新:假設我有一個帶有char變量的C程序。它在註冊表中如何表示?
如果CPU允許分段寄存器訪問(例如對於字,字節),它可能只是使用字節子寄存器。如果CPU是嚴格的32位,你的字節進入0-7位。根據目的地的使用情況,如果目的地代碼與寄存器一起作爲整體使用,它可能會或可能不會將其餘部分屏蔽爲0.(AND reg,0x000000FF)。變數太多,開放性太大,給你一個白色的答案。
利用0xFF作爲字節寄存器,0x000000FF作爲d字寄存器與使用它們的操作碼相同,如果它們具有單獨的字節和雙字部分。除非它們是位特定的操作,如「如果高位設置」,或位旋轉/移位。如果有符號,則0xFF將擴展爲0xFFFFFFFF(或0x83至0xFFFFFF83)
編輯到更新:C代表寄存器中的字符確實將其餘部分清零,具體取決於編譯器,它可能會在設置位之前先將寄存器清零0-7或者它可以如上所述執行。簽名時,符號位需要擴展到0,寄存器NEG並設置0-7。有些CPU甚至有明確的操作符號擴展。
這取決於它如何放在那裏。對於一個容器來說,數據永遠不會「太小」。
字符必須服從integer promotion。只要將它們與其他非char整數值組合在一起,它們就會被符號擴展爲int
,如果它們與這些操作數組合在一起,則它們甚至會被浮點運算。
這是你要確保你不使用結果不當。當您將int
重新設置爲char
時,您肯定會接受丟失較高有效位的風險。至於編譯器的設計者,至於特定的編譯器如何處理它,這取決於編譯器設計者。在Pentium monstruous體系結構中,可以使用寄存器的char版本,但在更常規的處理器上,如果涉及進一步的計算,則可以更方便地對char進行簽名擴展以使其值正常化。
通常,無符號數量用零填充,並且有符號數量爲sign-extended。
C中的char
類型是一種特殊情況,因爲該標準允許它是有符號或無符號的(並且一些編譯器提供了讓開發人員選擇的選項)。這允許編譯器使用效率最高的那一個。
C語言沒有寄存器,所以沒有這種對程序員可見的表示。如果使用更寬寄存器的一部分,則未使用部分可能有其他數據,或者可能有零。重要的是正確翻譯正確的程序來操作char
值(或任何其他值),以便它產生正確的輸出和任何其他外部可見的行爲。
如果使用32位寄存器來保存8位字符,並且未使用的位不被清除,那麼生成的機器代碼必須小心,例如不要讓剩餘的24位參與像比較結果那樣的比較從(char_a == char_b)
,因爲然後兩個等於char
s會錯誤地比較不等。生成的機器代碼必須告訴處理器使用一些字節寬的操作,只查看最低有效8位。一些體系結構具有這種功能,因此可能更容易生成將存儲器中的char
表示形式轉換爲寄存器中的完整32位值的代碼(如果已簽名,則爲符號擴展)。
這實際上取決於給定目標處理器上的方便和高效。
在x86上,子寄存器有單獨的硬件名稱。 eax的下半部分是al。您甚至可以在同一個寄存器上分配2個字符:eax是[16位|啊|人]。所以有可能通過al/ah/bl/bh等高位垃圾處理字符。但是GCC喜歡錶現非常奇怪的事情:
char foo(char c) {
return c+(char)1;
}
GCC -02 -m32 -S:
foo:
pushl %ebp
movl %esp, %ebp
movzbl 8(%ebp), %eax
popl %ebp
addl $1, %eax
movsbl %al,%eax
ret
movzbl意味着零擴展,movsbl手段與符號位擴展。
首次將輸入擴展爲0,然後執行+1,然後用低字節(a1)符號位擴展結果(eax)。所以它使用零/符號位擴展。對於無符號字符,零值的值相同,對於有符號字符的符號位。
gcc -S可能會幫助你。 –