在汇编的世界里,整数的存在和表示是没有有符号数和无符号数之分的,都是用数的补码表示,有无符号的计算是靠指令来进行确定。如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 ", 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
", 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,对于常量可以看出,他们是按照无符号数来进行移位的。