首页
社区
课程
招聘
[讨论]有趣的C程序,欢迎踊跃讨论
发表于: 2009-12-6 13:28 11968

[讨论]有趣的C程序,欢迎踊跃讨论

2009-12-6 13:28
11968
收藏
免费 0
支持
分享
最新回复 (43)
雪    币: 458
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
26
我在24楼描述的反汇编的代码是一样的,那为什么执行结果却不一样呢?  一个是T 一个是F  很疑惑。。。
2009-12-8 13:25
0
雪    币: 247
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
27
和汇编代码没关系 和变量的值有关系 一个是正数一个是负数
2009-12-8 15:36
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
28
所以是编译器问题造成的
2009-12-8 20:34
0
雪    币: 458
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
29
[QUOTE=blueapplez;723857]不带unsigned
11:       if ( a == (char)0x80 )
0040102C   mov         eax,dword ptr [ebp-4]
0040102F   and         eax,0FFh
00401034   cmp         ea...[/QUOTE]

对24楼还有疑问的,可以看看我的博客的分析,本人的愚见,呵呵
http://hi.baidu.com/blueapple_c/blog/item/909473b27a29b0add9335aba.html
2009-12-8 22:37
0
雪    币: 25
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
30
这是因为X86规定 两个操作数不能全部在内存中,是你理解错了
2009-12-9 09:32
0
雪    币: 157
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
31
像24#这种问题,可以给微软写信说明一下。。。
2009-12-9 17:49
0
雪    币: 120
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
32
关于24#
0040102C   mov         eax,dword ptr [ebp-4]
这里传给eax的值是不同的。。。
2009-12-9 18:15
0
雪    币: 458
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
33
[QUOTE=AimPerf;724491]关于24#
0040102C   mov         eax,dword ptr [ebp-4]
这里传给eax的值是不同的。。。[/QUOTE]

但是我单步调试的时候发现 24#的2种情况 eax的值是相同的(VC6环境下)
我又试了一下 在VS2005环境下的结果
发现
不加 unsigned 的汇编码
        unsigned char a = 0x80 ;
004113AE  mov         byte ptr [a],80h
        if ( a == (char)0x80 )
004113B2  movzx       eax,byte ptr [a]
004113B6  cmp         eax,0FFFFFF80h
004113B9  jne         wmain+44h (4113D4h)
                printf ("T") ;

加 unsigned 的汇编码
        unsigned char a = 0x80 ;
004113AE  mov         byte ptr [a],80h
        if ( a == (unsigned char)0x80 )
004113B2  movzx       eax,byte ptr [a]
004113B6  cmp         eax,80h
004113BB  jne         wmain+46h (4113D6h)
                printf ("T") ;


如此看来 是VC6 做的不够好  在 VS2005里已经没有这个问题了
2009-12-10 12:34
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
34
刚开始学习汇编...
2009-12-11 10:55
0
雪    币: 27
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
35
如果把 short int a 改为 usigned short int a 即可输出T!
2009-12-11 11:36
0
雪    币: 162
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
36
你这个是有符号短整数,超过7fff的都表示负数。a=0x8000不信你把a打印出来看看,可能是-32767。
2009-12-11 13:25
0
雪    币: 232
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
37
楼主我在turbo c 中运行结果没问题的。
c在vc下运行。有时肯定是平台转换的问题。
2009-12-11 15:48
0
雪    币: 442
活跃值: (43)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
38
这一看就知道是符号位的问题

不过大家的讨论没怎么理解
2009-12-11 16:32
0
雪    币: 245
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
39
整数类型,短到长,无符号进行无符号扩展;有符号的进行有符号扩展;
void main( void )
{
   unsigned char a=0x80 ;
  
  if (a ==   0x80)//输出T
    printf ("T\n") ;
  else
    printf ("F\n") ;

  if (a ==  (char) 0x80)//输出F
    printf ("T\n") ;
  else
    printf ("F\n") ;

    if (a ==  (unsigned char) 0x80)//输出T
    printf ("T\n") ;
  else
    printf ("F\n") ;

}
10:     if (a ==   0x80)
0040104C 8B 45 FC             mov         eax,dword ptr [ebp-4]
0040104F 25 FF 00 00 00       and         eax,0FFh
00401054 3D 80 00 00 00       cmp         eax,80h
00401059 75 0F                jne         main+3Ah (0040106a)
11:       printf ("T\n") ;
0040105B 68 20 F0 42 00       push        offset string "T\n" (0042f020)
00401060 E8 7B 71 00 00       call        printf (004081e0)
00401065 83 C4 04             add         esp,4
12:     else
00401068 EB 0D                jmp         main+47h (00401077)
13:       printf ("F\n") ;
0040106A 68 1C F0 42 00       push        offset string "F\n" (0042f01c)
0040106F E8 6C 71 00 00       call        printf (004081e0)
00401074 83 C4 04             add         esp,4
14:
15:
16:     if (a ==  (char) 0x80)
00401077 8B 4D FC             mov         ecx,dword ptr [ebp-4]
0040107A 81 E1 FF 00 00 00    and         ecx,0FFh
00401080 83 F9 80             cmp         ecx,80h
00401083 75 0F                jne         main+64h (00401094)
17:       printf ("T\n") ;
00401085 68 20 F0 42 00       push        offset string "T\n" (0042f020)
0040108A E8 51 71 00 00       call        printf (004081e0)
0040108F 83 C4 04             add         esp,4
18:     else
00401092 EB 0D                jmp         main+71h (004010a1)
19:       printf ("F\n") ;
00401094 68 1C F0 42 00       push        offset string "F\n" (0042f01c)
00401099 E8 42 71 00 00       call        printf (004081e0)
0040109E 83 C4 04             add         esp,4
22:       if (a ==  (unsigned char) 0x80)
004010A1 8B 55 FC             mov         edx,dword ptr [ebp-4]
004010A4 81 E2 FF 00 00 00    and         edx,0FFh
004010AA 81 FA 80 00 00 00    cmp         edx,80h
004010B0 75 0F                jne         main+91h (004010c1)
23:       printf ("T\n") ;
004010B2 68 20 F0 42 00       push        offset string "T\n" (0042f020)
004010B7 E8 24 71 00 00       call        printf (004081e0)
004010BC 83 C4 04             add         esp,4
24:     else
004010BF EB 0D                jmp         main+9Eh (004010ce)
25:       printf ("F\n") ;
004010C1 68 1C F0 42 00       push        offset string "F\n" (0042f01c)
004010C6 E8 15 71 00 00       call        printf (004081e0)
004010CB 83 C4 04             add         esp,4

注意以上三句加红的:
(1)if (a ==   0x80):机器码3D 80000000 //用eax可省去寄存器
    00401054 3D 80 00 00 00       cmp         eax,80h
(2)if (a ==  (char) 0x80):机器码83 F9 80 //F9=ecx
    00401080 83 F9 80             cmp         ecx,80h
(3)if (a ==  (unsigned char) 0x80):机器码81  FA  80000000 //FA=edx
    004010AA 81 FA 80 00 00 00    cmp         edx,80h
再参考:
IA-32 Intel Architecture Software Developer’s Manual, Volume 2;p3-76表:CMP—Compare Two Operands

Opcode Instruction Description
3C ib CMP AL, imm8 Compare imm8 with AL
3D iw CMP AX, imm16 Compare imm16 with AX
3D id CMP EAX, imm32 Compare imm32 with EAX
80 /7 ib CMP r/m8, imm8 Compare imm8 with r/m8
81 /7 iw CMP r/m16, imm16 Compare imm16 with r/m16
81 /7 id CMP r/m32,imm32 Compare imm32 with r/m32
83 /7 ib CMP r/m16,imm8 Compare imm8 with r/m16
83 /7 ib CMP r/m32,imm8 Compare imm8 with r/m32
38 /r CMP r/m8,r8 Compare r8 with r/m8
39 /r CMP r/m16,r16 Compare r16 with r/m16
39 /r CMP r/m32,r32 Compare r32 with r/m32
3A /r CMP r8,r/m8 Compare r/m8 with r8
3B /r CMP r16,r/m16 Compare r/m16 with r16
3B /r CMP r32,r/m32 Compare r/m32 with r32
段落:Description
..........When an immediate value is used as an operand, it is signextended
to the length of the first operand......
第一个if用的机器码为3D 同时操作数为四字节的80000000 (4字节)=(00000080H)
第二个if用的机器码为83,寄存器 F9,操作数是 80(1字节),此处,由于上面的那句话,可见,此1字节的80会被有符号扩展为32位长度(因为寄存器(操作数1)是32位的) =80FFFFFF(即FFFFFF80H);
第三个if用的机器码为81,寄存器  FA,操作数  80000000(4字节)=(00000080H)
所以,第一、三个if比较是相等的因为:易见寄存器中的值都是00000080;同时立即数是4字节长的00000080H;
而第二个if由于要进行有符号扩展,所以比较结果不等;
注意,第一、三个机器码(3D、81)只接受16/32bit的立即数;而第二个机器码83只接受8bit立即数;
鄙人拙见,不妥之处,望讨论;谢谢关注;
2009-12-11 19:07
0
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
40
这似乎是汇编的问题吧
2009-12-12 16:46
0
雪    币: 245
活跃值: (93)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
41
.......
事情是这样的 在32位寄存器里 你如果定义a=0x8000 不做其他的情况的话,前面根据高位自动符号扩展为0xFFFF8000  如果你定义a=0x7000的话 会自动扩展为0x00007000
事实上,我们可以用这个来检测一个数字的最高有效位是不是1
2011-1-5 00:30
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
42
很有趣的一个问题!!!不过我功力不够呢 我要加油呀!!!
2011-1-5 09:35
0
雪    币: 1149
活跃值: (888)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
43
0040102C   mov         eax,dword ptr [ebp-4]
参数里面的值 是一样的么。。。
2011-1-5 09:44
0
雪    币: 167
活跃值: (1574)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
44
从逻辑层上来看 32767 的范围 永远不会大于等于 32768 的

冬祭 说的是对的

从实现层来看 short 的时候 movsx 一个带符号F扩展后比较 另一个是0扩展 ~

而0X80000000 这个时候做比较 跳转依据是通过标志寄存器的ZF来实现的 无所谓是否有符号数 所以就T了
2011-1-5 10:12
0
游客
登录 | 注册 方可回帖
返回
//