理解寄存器位寬決定的數值範圍、有符號/無符號解讀差異、溢出截斷行為,是編寫正確組合語言代碼的基礎。本文以 EAX/AX/AH/AL 為例詳細演示。
EAX (32位) = 11111111 11111111 11111111 11111111 AX (16位) = 11111111 11111111 AH (8位) = 11111111 AL (8位) = 11111111
EAX、AX、AH、AL 實際指向同一物理寄存器的不同位範圍。
| 寄存器 | 位寬 | 最大值 | 十六進位 |
|---|---|---|---|
| AL / AH | 8 位 | 255 | $FF |
| AX | 16 位 | 65,535 | $FFFF |
| EAX | 32 位 | 4,294,967,295 | $FFFFFFFF |
{ 超出 AX 容量會編譯錯誤 }
mov ax, 65536 { Error }
{ 運行時溢出:EAX 最大值 + 1 = 0 (高位截斷) }
mov eax, 4294967295
add eax, 1 { EAX = 0 }
{ AX 溢出不進位到 EAX 高位 }
mov ax, 65535
add ax, 1 { AX = 0, EAX 高 16 位不變 }
{ AL 溢出 }
mov al, 255
add al, 1 { AL = 0 }
| 寄存器 | 最小值 | 最大值 |
|---|---|---|
| AL / AH | -128 | 127 |
| AX | -32,768 | 32,767 |
| EAX | -2,147,483,648 | 2,147,483,647 |
{ mov ax, -1 實際存入 11111111 11111111b }
{ EAX 變為 00000000 00000000 11111111 11111111b = 65535 }
{ 函數返回 Integer 時會被解讀為正數 65535 ! }
{ 正確做法:使用 32 位寄存器 }
mov eax, -1 { EAX = $FFFFFFFF = -1 (正確) }