• 用汇编语言角度来理解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
    ", 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,对于常量可以看出,他们是按照无符号数来进行移位的。



  • 相关阅读:
    PHP 上传文件 function move_uploaded_file: failed to open stream
    python super() 方法使用
    python 负数转为无符号整数
    python Aes 加密 解密
    mongoDB 启动 Error: couldn't connect to server 127.0.0.1:27017 src/mongo/shell/mongo.js:91
    ansible使用
    字段类型binary
    7-14 求整数段和
    7-13 日K蜡烛图
    7-12 两个数的简单计算器
  • 原文地址:https://www.cnblogs.com/liwugang/p/7594103.html
Copyright © 2020-2023  润新知