在汇编的世界里,整数的存在和表示是没有有符号数和无符号数之分的,都是用数的补码表示,有无符号的计算是靠指令来进行确定。如JA/JB是用于无符号数的跳转指令,而JG/JL则是用于有符号数的指令。汇编中的指令目的非常明确,也更加容易理解,而在C语言层次,有了一定的抽象,有些含义可能不是很确定,下面会看一些例子,结合汇编代码的实现,来更好里面C语言代码的含义。

下面思考 一些问题:

1.将短整数值赋值给长整数,是采用符号扩展还是零扩展?还有这是由谁来决定的?

2.移位运算?

...

问题1:看下面一段代码

  1. char c = 0xFF;
  2. unsigned char uc = 0xFF;
  3. int i = c;
  4. unsigned int ui = c;
  5. int ii = uc;
  6. unsigned uii = uc;
  7. printf("i=0x%x, ui=0x%x, ii=0x%x, uii=0x%x\n", i,ui,ii,uii);
  8. 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看下面代码

  1. int i = 0xFFFFFFFF;
  2. unsigned int ui = 0xFFFFFFFF;
  3.  
  4. int lefit_i = i << 4;
  5. int left_ui = ui << 4;
  6. int right_i = i>>4;
  7. int right_ui = ui >> 4;
  8.  
  9. int left_imm = 0xFFFFFFFF << 4;
  10. int right_imm = 0xFFFFFFF >> 4;
  11. 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,对于常量可以看出,他们是按照无符号数来进行移位的。

用汇编语言角度来理解C语言的一些问题的更多相关文章

  1. 从四个属性的角度来理解C语言的指针也许会更好理解

    文章会在文末更新! 关于指针是什么,很多教材已经作出了定义,大多数都会定义为"存放变量内存地址的变量".从这句话中我觉得除了让我知道这个定义有11个字以外,其他就没什么用了.我个人 ...

  2. 这样子来理解C语言中指针的指针

    友情提示:阅读本文前,请先参考我的之前的文章<从四个属性的角度来理解C语言的指针也许会更好理解>,若已阅读,请继续往下看. 我从4个属性的角度来总结了C语言中的指针概念.对于C语言的一个指 ...

  3. 深入理解c语言_从编译器的角度考虑问题_纪念Dennis Ritchie先生

    开源中国: Dennis Ritchie教授过世了,他发明了C语言,一个影响深远并彻底改变世界的计算机语言.一门经历40多年的到今天还长盛不训的语言,今天很多语言都受到C的影 响,C++,Java,C ...

  4. 深入理解C语言的函数调用过程 【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-4240084.html 原文地址:深入理解C语言的函数调用过程 作者:wjlkoorey258     本文 ...

  5. 从需求的角度去理解Linux系列:总线、设备和驱动

    笔者成为博客专家后整理以前原创的嵌入式Linux系列博文,现推出以让更多的读者受益. <从需求的角度去理解linux系列:总线.设备和驱动>是一篇有关如何学习嵌入式Linux系统的方法论文 ...

  6. 从IL角度彻底理解回调_委托_指针

    从IL角度彻底理解回调_委托_指针 目录 从IL角度彻底理解回调_委托_指针 1.创作此文的背景 1.1.委托能帮助代码更好地封装 1.2.委托能随时随地更方便地运行其他类中的方法 1.3.委托非常适 ...

  7. Android AsyncTask完全解析,带你从源码的角度彻底理解

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11711405 我们都知道,Android UI是线程不安全的,如果想要在子线程里进 ...

  8. 从逆向的角度去理解C++虚函数表

    很久没有写过文章了,自己一直是做C/C++开发的,我一直认为,作为一个C/C++程序员,如果能够好好学一下汇编和逆向分析,那么对于我们去理解C/C++将会有很大的帮助,因为程序中所有的奥秘都藏在汇编中 ...

  9. 【转载】理解C语言中的关键字extern

    原文:理解C语言中的关键字extern 最近写了一段C程序,编译时出现变量重复定义的错误,自己查看没发现错误.使用Google发现,自己对extern理解不透彻,我搜到了这篇文章,写得不错.我拙劣的翻 ...

随机推荐

  1. DevExpress v18.2新版亮点——DevExtreme篇(一)

    行业领先的.NET界面控件2018年第二次重大更新——DevExpress v18.2日前正式发布,本站将以连载的形式为大家介绍新版本新功能.本文将介绍了DevExtreme Complete Sub ...

  2. Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks 阅读笔记

    Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks (使用循环一致的对抗网络的非配对图像-图 ...

  3. 《JavaScript Dom 编程艺术》读书笔记-第11章

    本章简单介绍了HTML5,并推荐了一个好工具Modernizr,用于检测浏览器可能支持的各种特性. HTML5的新特性包括: 可以用来在文档中绘制矢量及位图的<canvas>元素: 可以在 ...

  4. shell进程中的特殊状态变量

    $?:获取执行上一个指令的执行状态返回值(0为成功,非0为失败) $$:获取当前执行的shell脚本的进程号(PID) $!:获取上一个在后台工作的进程的进程号 $_:获取在此之前执行的命令或脚本的最 ...

  5. ORA-01555快照过旧报错

    一.现象 将数据迁移到新库时,执行较大的存过,会报这个错误. 二.原因 产生该报错的原因: (1)sql执行比较久,需要优化sql (2)回滚段过小 (3)undo保存时间过短 三.具体检查及恢复 1 ...

  6. JAVA接口里面的变量

    在interface里面的变量都是public static final 的.所以你可以这样写:public static final int i=10;或则int i=10:(可以省略掉一部分) 注 ...

  7. 自学python之路(day4)

    一 购物车小程序 goods=[{}, {}, {}] shop_car={} li=[] ,len(goods)): li.append(i) money=input('请输入您的总金额:') if ...

  8. Linux "ls -l"文件列表权限详解 【转】

    1.使用 ls -l 命令 执行结果如下(/var/log) : drwxr-x--- 2 root              adm    4096 2013-08-07 11:03 apache2 ...

  9. 日常踩坑 — 相邻元素之间的margin合并问题。

    踩坑:使用v-for渲染的组件,当然图中的id已经换成class,还是没有解决这个问题,于是各种查找资料,我就不信简单的CSS问题这么难解决! v-for渲染组件级传值: <div class= ...

  10. nodejs故障cnpm没反应

    莫名发生的故障cnpm没反应 重新整理nodejs使用流程 方案1 1.安装64位nodejs 2.设置代理 npm config set proxy http://127.0.0.1:9999    ...