|
发表于 2022-9-16 11:36:32
|
显示全部楼层
本帖最后由 ssffzz1 于 2022-9-16 11:40 编辑
1、第一步,我写个C代码试试
- #include <stdio.h>
- int
- main(void)
- {
- unsigned int v1,v2;
- unsigned int P3=0x5a5a5a5a;
- printf("P3=%#x\n",P3);
-
- v1=(P3>>4)&1;
- v2=P3&(1<<4)>0;
- printf("v1=%#x\n",v1);
- printf("v2=%#x\n",v2);
- return(0);
- }
复制代码
2、编译测试过程如下
- C20X~/tmp$ gcc -Wall -o 1 1.c
- 1.c: In function ‘main’:
- 1.c:12:10: warning: suggest parentheses around comparison in operand of ‘&’ [-Wparentheses]
- v2=P3&(1<<4)>0;
- ^
- C20X~/tmp$ ./1
- P3=0x5a5a5a5a
- v1=0x1
- v2=0
- C20X~/tmp$
复制代码
这个warning的意思就是12行这个表达是写的不够清晰,希望你弄个括号上去写明白点的意思。
3、汇编代码分析
- # 函数序言,不管它
- 1135: 55 push %rbp
- 1136: 48 89 e5 mov %rsp,%rbp
- 1139: 48 83 ec 10 sub $0x10,%rsp
- # unsigned int P3=0x5a5a5a5a; ,rbp-0x4这个位置是P3变量
- 113d: c7 45 fc 5a 5a 5a 5a movl $0x5a5a5a5a,-0x4(%rbp)
- # printf("P3=%#x\n",P3);
- 1144: 8b 45 fc mov -0x4(%rbp),%eax
- 1147: 89 c6 mov %eax,%esi
- 1149: 48 8d 3d b4 0e 00 00 lea 0xeb4(%rip),%rdi # 2004 <_IO_stdin_used+0x4>
- 1150: b8 00 00 00 00 mov $0x0,%eax
- 1155: e8 d6 fe ff ff callq 1030 <printf@plt>
- [color=Red]# P3进%eax寄存器
- 115a: 8b 45 fc mov -0x4(%rbp),%eax
- # %eax寄存器里的值右移 4位
- 115d: c1 e8 04 shr $0x4,%eax
- # 再和1做与运算
- 1160: 83 e0 01 and $0x1,%eax
- # 保存到v1,v1变量的位置是-0x8(%rbp)
- 1163: 89 45 f8 mov %eax,-0x8(%rbp)
- # P3进%eax寄存器
- 1166: 8b 45 fc mov -0x4(%rbp),%eax
- # %eax直接和 1 做了 and
- 1169: 83 e0 01 and $0x1,%eax
- # 保存到V2变量,v1变量的位置是-0xc(%rbp)
- 116c: 89 45 f4 mov %eax,-0xc(%rbp)
- [/color]
- 116f: 8b 45 f8 mov -0x8(%rbp),%eax
- 1172: 89 c6 mov %eax,%esi
- 1174: 48 8d 3d 91 0e 00 00 lea 0xe91(%rip),%rdi # 200c <_IO_stdin_used+0xc>
- 117b: b8 00 00 00 00 mov $0x0,%eax
- 1180: e8 ab fe ff ff callq 1030 <printf@plt>
- 1185: 8b 45 f4 mov -0xc(%rbp),%eax
- 1188: 89 c6 mov %eax,%esi
- 118a: 48 8d 3d 83 0e 00 00 lea 0xe83(%rip),%rdi # 2014 <_IO_stdin_used+0x14>
- 1191: b8 00 00 00 00 mov $0x0,%eax
- 1196: e8 95 fe ff ff callq 1030 <printf@plt>
- # return 0
- 119b: b8 00 00 00 00 mov $0x0,%eax
- 11a0: c9 leaveq
- 11a1: c3 retq
复制代码
# P3进%eax寄存器
115a: 8b 45 fc mov -0x4(%rbp),%eax
# %eax寄存器里的值右移 4位
115d: c1 e8 04 shr $0x4,%eax
# 再和1做与运算
1160: 83 e0 01 and $0x1,%eax
# 保存到v1,v1变量的位置是-0x8(%rbp)
1163: 89 45 f8 mov %eax,-0x8(%rbp)
# P3进%eax寄存器
1166: 8b 45 fc mov -0x4(%rbp),%eax
# %eax直接和 1 做了 and
1169: 83 e0 01 and $0x1,%eax
# 保存到V2变量,v1变量的位置是-0xc(%rbp)
116c: 89 45 f4 mov %eax,-0xc(%rbp)
着重看后半段红字,那个是v2那个表达式的真正汇编代码,这里没有看到 (1<<4)&0的具体执行,那是因为 编译器给你算好了。
(1) 1<<4 ,测出来是 16
(2) 16 > 0,因此结果为真,在这个版本的C语言里用1表示
就是这句 1169: 83 e0 01 and $0x1,%eax
最后就是P3和1与的结果了。
4、这里为什么v2是0呢,因为那个5a,的第0位是0,我换个数值试试
- C20X~/tmp$ cat 1.c
- #include <stdio.h>
- int
- main(void)
- {
- unsigned int v1,v2;
- unsigned int P3=0x5a5a5a55;
- printf("P3=%#x\n",P3);
-
- v1=(P3>>4)&1;
- v2=P3&(1<<4)>0;
- printf("v1=%#x\n",v1);
- printf("v2=%#x\n",v2);
- return(0);
- }
- C20X~/tmp$ gcc -Wall -o 1 1.c
- 1.c: In function ‘main’:
- 1.c:12:10: warning: suggest parentheses around comparison in operand of ‘&’ [-Wparentheses]
- v2=P3&(1<<4)>0;
- ^
- C20X~/tmp$ ./1
- P3=0x5a5a5a55
- v1=0x1
- v2=0x1
- C20X~/tmp$
复制代码 |
|