在彙編的世界裏,整數的存在和表示是沒有有符號數和無符號數之分的,都是用數的補碼錶示,有無符號的計算是靠指令來進行確定。如JA/JB是用於無符號數的跳轉指令,而JG/JL則是用於有符號數的指令。彙編中的指令目的非常明確,也更加容易理解,而在C語言層次,有了一定的抽象,有些含義可能不是很確定,下面會看一些例子,結合彙編代碼的實現,來更好裏面C語言代碼的含義。
下面思考 一些問題:
1.將短整數值賦值給長整數,是採用符號擴展還是零擴展?還有這是由誰來決定的?
2.移位運算?
...
問題1:看下面一段代碼
char c = 0xFF;
unsigned char uc = 0xFF;
int i = c;
unsigned int ui = c;
int ii = uc;
unsigned uii = uc;
printf("i=0x%x, ui=0x%x, ii=0x%x, uii=0x%x\n", i,ui,ii,uii);
i,ui, ii, uii分別是什麼呢?
運行結果:
i=0xffffffff, ui=0xffffffff, ii=0xff, uii=0xff
看下他們的彙編代碼:
MOV BYTE PTR SS:[EBP-8],0FF
; char c=0xFF;
MOV BYTE PTR SS:[EBP-18],0FF
; unsigned char uc = 0xFF;
MOVSX EAX,BYTE PTR SS:[EBP-8]
; 符號擴展c放入EAX (EAX)=0xFFFFFFFF
MOV DWORD PTR SS:[EBP-10],EAX ; i = (eax) = 0xFFFFFFFF;
MOVSX ECX,BYTE PTR SS:[EBP-8]
; 符號擴展c放入ECX (ECX)=0xFFFFFFFF
MOV DWORD PTR SS:[EBP-C],ECX ; ui = (ecx) = 0xFFFFFFFF;
MOV EDX,DWORD PTR SS:[EBP-18]
AND EDX,0FF
; (edx) = 0xFF;
MOV DWORD PTR SS:[EBP-4],EDX
; ii = (edx) = 0xFF;
MOV EAX,DWORD PTR SS:[EBP-18]
AND EAX,0FF
; (eax) = 0xFF
MOV DWORD PTR SS:[EBP-14],EAX
; uii = (eax) = 0xFF
從彙編代碼可以看出,對於c採用符號擴展,而對於uc採用的是零擴展,可以看出對於有符號的短整數將採用符號擴展,無符號的短整數將採用零擴展,這些都只是由源操作數來決定。
問題2看下面代碼
int i = 0xFFFFFFFF;
unsigned int ui = 0xFFFFFFFF;
int lefit_i = i << 4;
int left_ui = ui << 4;
int right_i = i>>4;
int right_ui = ui >> 4;
int left_imm = 0xFFFFFFFF << 4;
int right_imm = 0xFFFFFFF >> 4;
printf("left_i=0x%x, left_ui=0x%x, right_i=0x%x, right_ui=0x%x, left_imm=0x%x,right_imm=0x%x \n", left_i,left_ui,right_i,right_ui,left_imm,right_imm);
運行結果:
left_i=0xfffffff0, left_ui=0xfffffff0, right_i=0xffffffff, right_ui=0xfffffff, left_imm=0xfffffff0,right_imm=0x0ffffff
看下他們的彙編代碼:
MOV DWORD PTR SS:[EBP-14],-1 ; i=0xFFFFFFFF;
MOV DWORD PTR SS:[EBP-C],-1 ; ui=0xFFFFFFFF;
MOV EAX,DWORD PTR SS:[EBP-14]
SHL EAX,4 ; (eax)= i<<4;
MOV DWORD PTR SS:[EBP-4],EAX ; left_i=(eax)
MOV ECX,DWORD PTR SS:[EBP-C]
SHL ECX,4
; (ecx)=ui<<4;
MOV DWORD PTR SS:[EBP-8],ECX ; left_ui=(ecx)
MOV EDX,DWORD PTR SS:[EBP-14]
SAR EDX,4 ; (edx)=i>>4
MOV DWORD PTR SS:[EBP-18],EDX ; right_i=(edx)
MOV EAX,DWORD PTR SS:[EBP-C]
SHR EAX,4 ; (eax)=ui>>4
MOV DWORD PTR SS:[EBP-20],EAX ; right_ui=(eax)
MOV DWORD PTR SS:[EBP-1C],-10 ; 0xFFFFFFFF << 4 = 0xFFFFFFF0
MOV DWORD PTR SS:[EBP-10],0FFFFFFF ; 0xFFFFFFFF >> 4 = 0x0FFFFFF
可以看出,有符號和無符號整數的左移都使用的是SHL,而右移操作有符號數用的是SAR,而無符號數用的是SHR,對於常量可以看出,他們是按照無符號數來進行移位的。