用匯編語言角度來理解C語言的一些問題



在彙編的世界裏,整數的存在和表示是沒有有符號數和無符號數之分的,都是用數的補碼錶示,有無符號的計算是靠指令來進行確定。如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,對於常量可以看出,他們是按照無符號數來進行移位的。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章