分支语句 汇编
案例来自于 《二进制安全基础》(ISBN:9787302651277)
对可执行文件进行反汇编,得到汇编代码
4-1.c:2 (25)
080484bb 8d 4c 24 04 LEA ECX=>argc,[ESP + 0x4]
080484bf 83 e4 f0 AND ESP,0xfffffff0
080484c2 ff 71 fc PUSH dword ptr [ECX + local_res0]
080484c5 55 PUSH EBP
080484c6 89 e5 MOV EBP,ESP
080484c8 51 PUSH ECX
080484c9 83 ec 34 SUB ESP,0x34
080484cc 89 c8 MOV EAX,ECX
080484ce 8b 40 04 MOV EAX,dword ptr [EAX + argv]
080484d1 89 45 d4 MOV dword ptr [EBP + local_34],EAX
... ....
LAB_08048668 XREF[1]: 08048661(j)
08048668 8b 4d fc MOV ECX,dword ptr [EBP + local_c]
0804866b c9 LEAVE
0804866c 8d 61 fc LEA ESP=>local_res0,[ECX + -0x4]
0804866f c3 RET
先写出 C 语言代码大致框架
void main(int argc, char* argv[])
{
....
}
4-1.c:3 (7)
080484df c7 45 e0 00 00 00 00 MOV dword ptr [EBP + local_28],0x0
4-1.c:4 (7)
080484e6 c7 45 e4 00 00 00 00 MOV dword ptr [EBP + local_24],0x0
4-1.c:5 (7)
080484ed c7 45 e8 00 00 00 00 MOV dword ptr [EBP + local_20],0x0
C 语言中的局部变量一般存在栈上
void main(int argc, char* argv[])
{
int a1 = 0; // [EBP + local_28]
int a2 = 0; // [EBP + local_24]
int a3 = 0; // [EBP + local_20]
}
4-1.c:6 (16)
080484f4 83 ec 0c SUB ESP,0xc
080484f7 68 f0 86 04 08 PUSH DAT_080486f0 = E8h
080484fc e8 7f fe ff ff CALL libc.so.6::puts int puts(char * __s)
08048501 83 c4 10 ADD ESP,0x10
4-1.c:7 (16)
08048504 83 ec 0c SUB ESP,0xc
08048507 68 39 87 04 08 PUSH DAT_08048739 = E8h
0804850c e8 6f fe ff ff CALL libc.so.6::puts int puts(char * __s)
08048511 83 c4 10 ADD ESP,0x10
这里可以看出调用了 puts() 函数,PUSH DAT_XXX 是将 DAT_XXX 地址值保存到栈上,说白点就是传参,puts() 函数会输出 DAT_XXX 地址所在的数据,以 DAT_08048739 为例,其它太多了,就不一一贴出来了
DAT_08048739 XREF[1]: main:08048507(*)
08048739 e8 ?? E8h
0804873a af ?? AFh
0804873b b7 ?? B7h
0804873c e8 ?? E8h
0804873d be ?? BEh
0804873e 93 ?? 93h
0804873f e5 ?? E5h
08048740 85 ?? 85h
08048741 a5 ?? A5h
08048742 61 ?? 61h a
08048743 e7 ?? E7h
08048744 9a ?? 9Ah
08048745 84 ?? 84h
08048746 e5 ?? E5h
08048747 80 ?? 80h
08048748 bc ?? BCh
08048749 3a ?? 3Ah :
0804874a 00 ?? 00h
这个是编码后的内容,我找 AI 写了一个 Python 脚本写了一个将它转为字符,可以参考我的这篇博客,转出来的字符是 “请输入a的值:”
#include <stdio.h>
void main(int argc, char* argv[])
{
int a1 = 0; // [EBP + local_28]
int a2 = 0; // [EBP + local_24]
int a3 = 0; // [EBP + local_20]
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
}
4-1.c:8 (20)
08048514 83 ec 08 SUB ESP,0x8
08048517 8d 45 e0 LEA EAX=>local_28,[EBP + -0x20]
0804851a 50 PUSH EAX
0804851b 68 4b 87 04 08 PUSH DAT_0804874b = 25h %
08048520 e8 7b fe ff ff CALL libc.so.6::__isoc99_scanf undefined __isoc99_scanf()
08048525 83 c4 10 ADD ESP,0x10
4-1.c:9 (16)
08048528 83 ec 0c SUB ESP,0xc
0804852b 68 4e 87 04 08 PUSH DAT_0804874e = E8h
08048530 e8 4b fe ff ff CALL libc.so.6::puts int puts(char * __s)
08048535 83 c4 10 ADD ESP,0x10
4-1.c:10 (20)
08048538 83 ec 08 SUB ESP,0x8
0804853b 8d 45 e4 LEA EAX=>local_24,[EBP + -0x1c]
0804853e 50 PUSH EAX
0804853f 68 4b 87 04 08 PUSH DAT_0804874b = 25h %
08048544 e8 57 fe ff ff CALL libc.so.6::__isoc99_scanf undefined __isoc99_scanf()
08048549 83 c4 10 ADD ESP,0x10
4-1.c:11 (16)
0804854c 83 ec 0c SUB ESP,0xc
0804854f 68 60 87 04 08 PUSH DAT_08048760 = E8h
08048554 e8 27 fe ff ff CALL libc.so.6::puts int puts(char * __s)
08048559 83 c4 10 ADD ESP,0x10
4-1.c:12 (20)
0804855c 83 ec 08 SUB ESP,0x8
0804855f 8d 45 e8 LEA EAX=>local_20,[EBP + -0x18]
08048562 50 PUSH EAX
08048563 68 4b 87 04 08 PUSH DAT_0804874b = 25h %
08048568 e8 33 fe ff ff CALL libc.so.6::__isoc99_scanf undefined __isoc99_scanf()
0804856d 83 c4 10 ADD ESP,0x10
这里写了分别输入 a、b、c 的值,估计原来的变量命名也是如此
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
}
4-1.c:13 (9)
08048570 8b 45 e0 MOV EAX,dword ptr [EBP + local_28]
08048573 c1 e0 03 SHL EAX,0x3
08048576 89 45 e0 MOV dword ptr [EBP + local_28],EAX
这里 shl 是逻辑左移
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
a = a << 3;
}
4-1.c:14 (12)
08048579 8b 45 e0 MOV EAX,dword ptr [EBP + local_28]
0804857c 83 f8 0f CMP EAX,0xf
0804857f 0f 8e be 00 00 00 JLE LAB_08048643
4-1.c:14 (12)
08048585 8b 45 e0 MOV EAX,dword ptr [EBP + local_28]
08048588 83 f8 10 CMP EAX,0x10
0804858b 0f 8f b2 00 00 00 JG LAB_08048643
这里可以看出是分支语句。CMP EAX,0xf 就是比较变量 a 与 15 比大小,JLE LAB_08048643 表示变量 a 小于或等于 15 的话,就跳转到 LAB_08048643,JG 表示如果大于则跳转。写成表达式就是 a <= 15 || a > 16。
LAB_08048643 XREF[2]: 0804857f(j), 0804858b(j)
4-1.c:42 (16)
08048643 83 ec 0c SUB ESP,0xc
08048646 68 72 87 04 08 PUSH s_failed!_08048772 = "failed! "
0804864b e8 30 fd ff ff CALL libc.so.6::puts int puts(char * __s)
08048650 83 c4 10 ADD ESP,0x10
4-1.c:44 (2)
08048653 eb 01 JMP LAB_08048656
LAB_08048655 XREF[2]: 080485a8(j), 08048641(j)
4-1.c:14 (1)
08048655 90 NOP
LAB_08048656 XREF[1]: 08048653(j)
4-1.c:44 (13)
08048656 90 NOP
switchD_080485b5::default
08048657 8b 45 f4 MOV EAX,dword ptr [EBP + local_14]
0804865a 65 33 05 14 00 00 00 XOR EAX,dword ptr GS:[0x14]
08048661 74 05 JZ LAB_08048668
4-1.c:44 (13)
08048663 e8 08 fd ff ff CALL libc.so.6::__stack_chk_fail undefined __stack_chk_fail()
-- Flow Override: CALL_RETURN (C
LAB_08048668 XREF[1]: 08048661(j)
08048668 8b 4d fc MOV ECX,dword ptr [EBP + local_c]
0804866b c9 LEAVE
0804866c 8d 61 fc LEA ESP=>local_res0,[ECX + -0x4]
0804866f c3 RET
分支语句执行完后 main() 函数就结束了
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
a = a << 3;
if (a <= 15 || a > 16)
{
puts("failed! ");
}
}
回到 0x0804858b 处的指令,接着往下看
4-1.c:15 (7)
08048591 c7 45 ec 00 00 00 00 MOV dword ptr [EBP + local_1c],0x0
4-1.c:16 (7)
08048598 c7 45 f0 00 00 00 00 MOV dword ptr [EBP + local_18],0x0
4-1.c:17 (24)
0804859f 8b 45 e4 MOV EAX,dword ptr [EBP + local_24]
080485a2 83 e8 05 SUB EAX,0x5
080485a5 83 f8 04 CMP EAX,0x4
080485a8 0f 87 a7 00 00 00 JA LAB_08048655
080485ae 8b 04 85 88 87 04 08 MOV EAX,dword ptr [EAX*0x4 + switchD_080485b5::switchdataD_08048788] = 080485b7
switchD_080485b5::switchD
080485b5 ff e0 JMP EAX
发现还有一部分,可以估计刚才的分支语句是 if ... else ... 结构,而且 else 的部分嵌套了 switch 分支
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
a = a << 3;
if (a <= 15 || a > 16)
{
puts("failed! ");
}
else
{
// [EBP + local_1c] [EBP + local_18]
int a1 = 0, a2 = 0;
switch (b)
{
....
}
}
}
接下来看分支语句内部
switchD_080485b5::switchdataD_ XREF[1]: main:080485ae(*)
08048788 b7 85 04 08 addr switchD_080485b5::caseD_5
0804878c c9 85 04 08 addr switchD_080485b5::caseD_6
08048790 db 85 04 08 addr switchD_080485b5::caseD_7
08048794 ed 85 04 08 addr switchD_080485b5::caseD_8
08048798 30 86 04 08 addr switchD_080485b5::caseD_9
后面的数字提示了我们 case 后的值,如果没有,也是可以推出来
0804859f 8b 45 e4 MOV EAX,dword ptr [EBP + local_24]
080485a2 83 e8 05 SUB EAX,0x5
080485a5 83 f8 04 CMP EAX,0x4
080485a8 0f 87 a7 00 00 00 JA LAB_08048655
080485ae 8b 04 85 88 87 04 08 MOV EAX,dword ptr [EAX*0x4 + switchD_080485b5::switchdataD_08048788] = 080485b7
可以看到这里 b - 5,如果值大于 4 就结束了,不会进入后面的跳转语句,这是 switch 语句的一个优化,当 b 的值大于 9 的时候就不进入 switch 分支。EAX 的值乘以 4 加上 switchD_080485b5::switchdataD_08048788 的地址 0x08048788 就是 b - 5 小于或等于 4 时会跳转的地址。如果 b - 5 的值为 0,那就跳转到 0 × 0 x 4 + 0 x 08048788 0\times0\mathrm{x}4+0\mathrm{x}08048788 0×0x4+0x08048788 也就是 0x08048788;如果为 1,跳转到 0x0804878c
switch (b)
{
case 5: ...;
case 6: ...;
case 7: ...;
case 8: ...;
case 9: ...;
}
刚才似乎看到了一个 default
switchD_080485b5::default
08048657 8b 45 f4 MOV EAX,dword ptr [EBP + local_14]
0804865a 65 33 05 14 00 00 00 XOR EAX,dword ptr GS:[0x14]
08048661 74 05 JZ LAB_08048668
为什么 switch 分支代码里没写 default 呢?这里的 default 在 main() 函数结束前做了检查栈的工作,有可能是反汇编的时候,反汇编软件标记出错了。
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
a = a << 3;
if (a <= 15 || a > 16)
{
puts("failed! ");
}
else
{
// [EBP + local_1c] [EBP + local_18]
int a1 = 0, a2 = 0;
switch (b)
{
case 5: ...;
case 6: ...;
case 7: ...;
case 8: ...;
case 9: ...;
}
}
}
看看 switch 语句的前 3 个分支
switchD_080485b5::caseD_5 XREF[2]: 080485b5(j), 08048788(*)
4-1.c:19 (16)
080485b7 83 ec 0c SUB ESP,0xc
080485ba 68 72 87 04 08 PUSH s_failed!_08048772 = "failed! "
080485bf e8 bc fd ff ff CALL libc.so.6::puts int puts(char * __s)
080485c4 83 c4 10 ADD ESP,0x10
4-1.c:20 (2)
080485c7 eb 78 JMP LAB_08048641
switchD_080485b5::caseD_6 XREF[2]: 080485b5(j), 0804878c(*)
4-1.c:22 (16)
080485c9 83 ec 0c SUB ESP,0xc
080485cc 68 72 87 04 08 PUSH s_failed!_08048772 = "failed! "
080485d1 e8 aa fd ff ff CALL libc.so.6::puts int puts(char * __s)
080485d6 83 c4 10 ADD ESP,0x10
4-1.c:23 (2)
080485d9 eb 66 JMP LAB_08048641
switchD_080485b5::caseD_7 XREF[2]: 080485b5(j), 08048790(*)
4-1.c:25 (16)
080485db 83 ec 0c SUB ESP,0xc
080485de 68 72 87 04 08 PUSH s_failed!_08048772 = "failed! "
080485e3 e8 98 fd ff ff CALL libc.so.6::puts int puts(char * __s)
080485e8 83 c4 10 ADD ESP,0x10
4-1.c:26 (2)
080485eb eb 54 JMP LAB_08048641
LAB_08048641 XREF[5]: 080485c7(j), 080485d9(j),
080485eb(j), 0804861c(j),
0804862e(j)
4-1.c:14 (2)
08048641 eb 12 JMP LAB_08048655
可以看出都是打印,打印完就 switch 分支就结束了
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
a = a << 3;
if (a <= 15 || a > 16)
{
puts("failed! ");
}
else
{
// [EBP + local_1c] [EBP + local_18]
int a1 = 0, a2 = 0;
switch (b)
{
case 5:
puts("failed! ");
break;
case 6:
puts("failed! ");
break;
case 7:
puts("failed! ");
break;
case 8: ...;
case 9: ...;
}
}
}
switch 分支第四个语句
switchD_080485b5::caseD_8 XREF[2]: 080485b5(j), 08048794(*)
4-1.c:28 (9)
080485ed c7 45 f0 00 00 00 00 MOV dword ptr [EBP + local_18],0x0
080485f4 eb 08 JMP LAB_080485fe
LAB_080485f6 XREF[1]: 08048604(j)
4-1.c:29 (4)
080485f6 83 45 ec 01 ADD dword ptr [EBP + local_1c],0x1
4-1.c:28 (4)
080485fa 83 45 f0 01 ADD dword ptr [EBP + local_18],0x1
LAB_080485fe XREF[1]: 080485f4(j)
4-1.c:28 (8)
080485fe 8b 45 e8 MOV EAX,dword ptr [EBP + local_20]
08048601 39 45 f0 CMP dword ptr [EBP + local_18],EAX
08048604 7e f0 JLE LAB_080485f6
4-1.c:31 (6)
08048606 83 7d ec 09 CMP dword ptr [EBP + local_1c],0x9
0804860a 75 12 JNZ LAB_0804861e
4-1.c:32 (16)
0804860c 83 ec 0c SUB ESP,0xc
0804860f 68 7b 87 04 08 PUSH s_success!_0804877b = "success! "
08048614 e8 67 fd ff ff CALL libc.so.6::puts int puts(char * __s)
08048619 83 c4 10 ADD ESP,0x10
4-1.c:36 (2)
0804861c eb 23 JMP LAB_08048641
LAB_0804861e XREF[1]: 0804860a(j)
4-1.c:34 (16)
0804861e 83 ec 0c SUB ESP,0xc
08048621 68 72 87 04 08 PUSH s_failed!_08048772 = "failed! "
08048626 e8 55 fd ff ff CALL libc.so.6::puts int puts(char * __s)
0804862b 83 c4 10 ADD ESP,0x10
4-1.c:36 (2)
0804862e eb 11 JMP LAB_08048641
可以看到有一个 for 循环
080485ed c7 45 f0 00 00 00 00 MOV dword ptr [EBP + local_18],0x0
080485f4 eb 08 JMP LAB_080485fe
LAB_080485f6 XREF[1]: 08048604(j)
4-1.c:29 (4)
080485f6 83 45 ec 01 ADD dword ptr [EBP + local_1c],0x1
4-1.c:28 (4)
080485fa 83 45 f0 01 ADD dword ptr [EBP + local_18],0x1
LAB_080485fe XREF[1]: 080485f4(j)
4-1.c:28 (8)
080485fe 8b 45 e8 MOV EAX,dword ptr [EBP + local_20]
08048601 39 45 f0 CMP dword ptr [EBP + local_18],EAX
08048604 7e f0 JLE LAB_080485f6
流程是先给循环控制变量 a2 赋初值 0,判断是否小于等于变量 c,满足的话变量 a1 就自增,然后变量 a2 自增
for (a2 = 0; a2 <= c; a2++)
{
a1++;
}
循环结束后就是一个分支语句
4-1.c:31 (6)
08048606 83 7d ec 09 CMP dword ptr [EBP + local_1c],0x9
0804860a 75 12 JNZ LAB_0804861e
4-1.c:32 (16)
0804860c 83 ec 0c SUB ESP,0xc
0804860f 68 7b 87 04 08 PUSH s_success!_0804877b = "success! "
08048614 e8 67 fd ff ff CALL libc.so.6::puts int puts(char * __s)
08048619 83 c4 10 ADD ESP,0x10
4-1.c:36 (2)
0804861c eb 23 JMP LAB_08048641
LAB_0804861e XREF[1]: 0804860a(j)
4-1.c:34 (16)
0804861e 83 ec 0c SUB ESP,0xc
08048621 68 72 87 04 08 PUSH s_failed!_08048772 = "failed! "
08048626 e8 55 fd ff ff CALL libc.so.6::puts int puts(char * __s)
0804862b 83 c4 10 ADD ESP,0x10
4-1.c:36 (2)
0804862e eb 11 JMP LAB_08048641
把变量 a1 与 9 比较,如果不相等,就输出 failed! , switch 分支结束;如果相等,就输出 success! ,switch 分支结束
if (a1 != 9)
{
puts("failed! ");
}
else
{
puts("success! ");
}
break;
switch 语句第四个分支
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
a = a << 3;
if (a <= 15 || a > 16)
{
puts("failed! ");
}
else
{
// [EBP + local_1c] [EBP + local_18]
int a1 = 0, a2 = 0;
switch (b)
{
case 5:
puts("failed! ");
break;
case 6:
puts("failed! ");
break;
case 7:
puts("failed! ");
break;
case 8:
for (a2 = 0; a2 <= c; a2++)
{
a1++;
}
if (a1 != 9)
{
puts("failed! ");
}
else
{
puts("success! ");
}
break;
case 9: ...;
}
}
}
switch 语句最后一个分支
switchD_080485b5::caseD_9 XREF[2]: 080485b5(j), 08048798(*)
4-1.c:38 (16)
08048630 83 ec 0c SUB ESP,0xc
08048633 68 72 87 04 08 PUSH s_failed!_08048772 = "failed! "
08048638 e8 43 fd ff ff CALL libc.so.6::puts int puts(char * __s)
0804863d 83 c4 10 ADD ESP,0x10
4-1.c:39 (1)
08048640 90 NOP
LAB_08048641 XREF[5]: 080485c7(j), 080485d9(j),
080485eb(j), 0804861c(j),
0804862e(j)
4-1.c:14 (2)
08048641 eb 12 JMP LAB_08048655
也是一个打印
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
a = a << 3;
if (a <= 15 || a > 16)
{
puts("failed! ");
}
else
{
// [EBP + local_1c] [EBP + local_18]
int a1 = 0, a2 = 0;
switch (b)
{
case 5:
puts("failed! ");
break;
case 6:
puts("failed! ");
break;
case 7:
puts("failed! ");
break;
case 8:
for (a2 = 0; a2 <= c; a2++)
{
a1++;
}
if (a1 != 9)
{
puts("failed! ");
}
else
{
puts("success! ");
}
break;
case 9:
puts("failed! ");
break;
}
}
}
函数返回前并未看到将某个值移到寄存器内,只检查了栈,估计没有返回值,最终的代码:
#include <stdio.h>
void main(int argc, char* argv[])
{
// [EBP + local_28] [EBP + local_24] [EBP + local_20]
int a = 0, b = 0, c = 0;
puts("请依次输入a、b、c的值(正整数),使程序输出 success!");
puts("请输入a的值:");
scanf("%d",&a);
puts("请输入b的值:");
scanf("%d",&b);
puts("请输入c的值:");
scanf("%d",&c);
a = a << 3;
if (a <= 15 || a > 16)
{
puts("failed! ");
}
else
{
// [EBP + local_1c] [EBP + local_18]
int a1 = 0, a2 = 0;
switch (b)
{
case 5:
puts("failed! ");
break;
case 6:
puts("failed! ");
break;
case 7:
puts("failed! ");
break;
case 8:
for (a2 = 0; a2 <= c; a2++)
{
a1++;
}
if (a1 != 9)
{
puts("failed! ");
}
else
{
puts("success! ");
}
break;
case 9:
puts("failed! ");
break;
}
}
}
最后附上源代码
#include <stdio.h>
void main(int argc, char* argv[]){
int a=0;
int b=0;
int c=0;
printf("请依次输入a、b、c的值(正整数),使程序输出 success!\n");
printf("请输入a的值:\n");
scanf("%d",&a);
printf("请输入b的值:\n");
scanf("%d",&b);
printf("请输入c的值:\n");
scanf("%d",&c);
a=a<<3;
if(a>15 && a<17){
int tmp=0;
int i=0;
switch(b){
case 5:
printf("failed! \n");
break;
case 6:
printf("failed! \n");
break;
case 7:
printf("failed! \n");
break;
case 8:
for(i=0;i<=c;i++){
tmp++;
}
if(tmp==9){
printf("success! \n");
}else{
printf("failed! \n");
}
break;
case 9:
printf("failed! \n");
break;
}
}else{
printf("failed! \n");
}
}
更多推荐


所有评论(0)