免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3638 | 回复: 5
打印 上一主题 下一主题

编译器对不同进制常量的不同处理 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-06-08 14:12 |只看该作者 |倒序浏览
在看补码的时候遇到一个古怪的问题,似乎编译器对十进制常量汇编的时候,会做一个转换,但是其它进制不会:

  1. test.c
  2. #include <stdio.h>

  3. int main()
  4. {
  5.         char a = 0b00000000;
  6.         char b = 0b10000001;

  7.         printf("a: %d, b:%d\n", a, b);

  8.         return 0;
  9. }
复制代码
#make  test
#./test
a: 0, b:-127

为什么b不是-1而是-127呢,看来是用二进制表示的时候,汇编器将0b10000001直接读入了,而printf读出的时候,
CPU内部做了转换,也即10000001 取反11111110再加1求得11111111,也即-127

查看生成的反汇编代码为:
80483cd:       c6 44 24 1f 00          movb   $0x0,0x1f(%esp)
80483d2:       c6 44 24 1e 81         movb   $0x81,0x1e(%esp)

第一句将0x0放入堆栈esp+0x1f处,第二句将0x81放入堆栈esp+0x1e处,0x81就是0b10000001。
看来当使用二进制给出初始值的时候,汇编器忠实于原数值。

再看下面程序:
#include <stdio.h>

int main()
{
        char a = 0b00000000;
        char b = -1;

        printf("a: %d, b:%d\n", a, b);

        return 0;
}

#./test
a: 0, b:-1

查看生成的汇编代码为:
80483cd:       c6 44 24 1f 00          movb   $0x0,0x1f(%esp)
80483d2:       c6 44 24 1e ff          movb   $0xff,0x1e(%esp)
第一句将0x0放入堆栈esp+0x1f处,第二句将0xff放入堆栈esp+0x1e处,0xff就是-1的补码。
看来当使用十进制给出初始值的时候,汇编器将翻译原数值为补码到机器指令。

假如我们使用十六进制呢,char b = 0x81; 打印结果与二进制给出的结果是一致的,另外测试8进制是结果也为-127。
难道只有十进制的时候,编译器会忠实于赋予的值? 为什么要这样处理? 请不吝指点!

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
2 [报告]
发表于 2011-06-08 14:24 |只看该作者
哪个编译器支持 0b表示二进制?
-1的二进制应该是11111111,而不是10000001

论坛徽章:
2
CU十二周年纪念徽章
日期:2013-10-24 15:41:34处女座
日期:2013-12-27 22:22:41
3 [报告]
发表于 2011-06-08 14:31 |只看该作者
补码10000001本来就是-127。

论坛徽章:
0
4 [报告]
发表于 2011-06-08 14:33 |只看该作者
本帖最后由 lli_njupt 于 2011-06-08 14:38 编辑

#gcc -v
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)

看来二进制大家用的都很少啊,
-1的二进制应该是11111111,而不是10000001,这点楼上应该是指计算机内部表示了?
因为它用补码表示负数,看来是-1的十进制编译机器指令的时候直接由汇编器转化为二进制的
内部表示11111111了,恩,其它进制也是如此罢了,没甚奇怪的了!

论坛徽章:
0
5 [报告]
发表于 2011-06-08 14:40 |只看该作者
补码表示的二进制有符号序列 10000001 就是代表-127。 11111111代表-1

论坛徽章:
0
6 [报告]
发表于 2011-06-08 14:44 |只看该作者
用以下方式更好理解,不妨假设汇编器做了以下转换:

8/16进制  =>  2进制            
10进制    =>  16进制 => 2进制,10转16的时候已经转为补码了,然而8/16进制  =>  2进制直接放入机器指令了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP