if语句
几乎没有只会按照预先设计好的流程执行的程序。本章学习条件语句来改变程序流程的方法。
if语句.其1
通过程序来进行判断,如果输入放入整数不能被5整除,就显示相应的信息。
代码清单3-1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int no;
printf("请输入一个整数:"); scanf("%d", &no);
if (no % 5) { puts("输入的整数不能被5整除"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| 00C55260 push ebp 00C55261 mov ebp,esp 00C55263 sub esp,0D0h 00C55269 push ebx 00C5526A push esi 00C5526B push edi 00C5526C lea edi,[ebp-10h] 00C5526F mov ecx,4 00C55274 mov eax,0CCCCCCCCh 00C55279 rep stos dword ptr es:[edi] 00C5527B mov eax,dword ptr [__security_cookie (0C5A020h)] 00C55280 xor eax,ebp 00C55282 mov dword ptr [ebp-4],eax 00C55285 mov ecx,offset _FC42537F_mjc@cpp (0C5C008h) 00C5528A call @__CheckForDebuggerJustMyCode@4 (0C51307h)
00C5528F push offset string "\xc7\xeb\xca\xe4\xc8\xeb\xd2\xbb\xb8\xf6\xd5\xfb\xca\xfd\xa3\xba" (0C57E28h) 00C55294 call _printf (0C513ACh) 00C55299 add esp,4
00C5529C lea eax,[no] 00C5529F push eax 00C552A0 push offset string "%d" (0C57B30h) 00C552A5 call _scanf (0C513F2h) 00C552AA add esp,8
00C552AD mov eax,dword ptr [no] 00C552B0 cdq 00C552B1 mov ecx,5 00C552B6 idiv eax,ecx 00C552B8 test edx,edx 00C552BA je __$EncStackInitStart+67h (0C552D3h)
00C552BC mov esi,esp 00C552BE push offset string "\xca\xe4\xc8\xeb\xb5\xc4\xd5\xfb\xca\xfd\xb2\xbb\xc4\xdc\xb1\xbb5\xd5\xfb\xb3\xfd" (0C57BD8h) 00C552C3 call dword ptr [__imp__puts (0C5B170h)] 00C552C9 add esp,4 00C552CC cmp esi,esp 00C552CE call __RTC_CheckEsp (0C51230h)
00C552D3 xor eax,eax 00C552D5 push edx 00C552D6 mov ecx,ebp 00C552D8 push eax 00C552D9 lea edx,ds:[0C55304h] 00C552DF call @_RTC_CheckStackVars@8 (0C511D1h) 00C552E4 pop eax 00C552E5 pop edx 00C552E6 pop edi 00C552E7 pop esi 00C552E8 pop ebx 00C552E9 mov ecx,dword ptr [ebp-4] 00C552EC xor ecx,ebp 00C552EE call @__security_check_cookie@4 (0C5113Bh) 00C552F3 add esp,0D0h 00C552F9 cmp ebp,esp 00C552FB call __RTC_CheckEsp (0C51230h) 00C55300 mov esp,ebp 00C55302 pop ebp 00C55303 ret
|
if判断语句使用 JCC 跳转指令来实现。
奇数的判断
通过判断输入的整数是否被2整除,就可以确认该整数是不是奇数了。
代码清单3-2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int no;
printf("请输入一个整数:"); scanf("%d", &no);
if (no % 2) { puts("输入的整数是奇数。"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 00D9528F push offset string "\xc7\xeb\xca\xe4\xc8\xeb\xd2\xbb\xb8\xf6\xd5\xfb\xca\xfd\xa3\xba" (0D97E28h) 00D95294 call _printf (0D913ACh) 00D95299 add esp,4
00D9529C lea eax,[no] 00D9529F push eax 00D952A0 push offset string "%d" (0D97B30h) 00D952A5 call _scanf (0D913F2h) 00D952AA add esp,8
00D952AD mov eax,dword ptr [no] 00D952B0 and eax,80000001h 00D952B5 jns __$EncStackInitStart+50h (0D952BCh) 00D952B7 dec eax 00D952B8 or eax,0FFFFFFFEh 00D952BB inc eax 00D952BC test eax,eax 00D952BE je __$EncStackInitStart+6Bh (0D952D7h)
00D952C0 mov esi,esp 00D952C2 push offset string "\xca\xe4\xc8\xeb\xb5\xc4\xd5\xfb\xca\xfd\xca\xc7\xc6\xe6\xca\xfd\xa1\xa3" (0D97BD8h) 00D952C7 call dword ptr [__imp__puts (0D9B170h)] 00D952CD add esp,4 00D952D0 cmp esi,esp 00D952D2 call __RTC_CheckEsp (0D91230h)
00D952D7 xor eax,eax
|
这里的取余算法有点变动,需要多注意一下。
if语句.其2
代码清单3-3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int no;
printf("请输入一个整数:"); scanf("%d", &no);
if (no % 5) { puts("该整数不能被5整除。"); } else { puts("该整数能被5整除。"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 0045528F push offset string "\xc7\xeb\xca\xe4\xc8\xeb\xd2\xbb\xb8\xf6\xd5\xfb\xca\xfd\xa3\xba" (0457E28h) 00455294 call _printf (04513ACh) 00455299 add esp,4
0045529C lea eax,[no] 0045529F push eax 004552A0 push offset string "%d" (0457B30h) 004552A5 call _scanf (04513F2h) 004552AA add esp,8
004552AD mov eax,dword ptr [no] 004552B0 cdq 004552B1 mov ecx,5 004552B6 idiv eax,ecx 004552B8 test edx,edx 004552BA je __$EncStackInitStart+69h (04552D5h)
004552BC mov esi,esp 004552BE push offset string "\xca\xe4\xc8\xeb\xb5\xc4\xd5\xfb\xca\xfd\xca\xc7\xc6\xe6\xca\xfd\xa1\xa3" (0457BD8h) 004552C3 call dword ptr [__imp__puts (045B170h)] 004552C9 add esp,4 004552CC cmp esi,esp 004552CE call __RTC_CheckEsp (0451230h) 004552D3 jmp __$EncStackInitStart+80h (04552ECh)
004552D5 mov esi,esp 004552D7 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xc4\xdc\xb1\xbb5\xd5\xfb\xb3\xfd\xa1\xa3" (0457CD8h) 004552DC call dword ptr [__imp__puts (045B170h)] 004552E2 add esp,4 004552E5 cmp esi,esp 004552E7 call __RTC_CheckEsp (0451230h) }
004552EC xor eax,eax
004552EE push edx 004552EF mov ecx,ebp 004552F1 push eax 004552F2 lea edx,ds:[455320h] 004552F8 call @_RTC_CheckStackVars@8 (04511D1h) 004552FD pop eax 004552FE pop edx 004552FF pop edi 00455300 pop esi 00455301 pop ebx 00455302 mov ecx,dword ptr [ebp-4] 00455305 xor ecx,ebp 00455307 call @__security_check_cookie@4 (045113Bh) 0045530C add esp,0D0h 00455312 cmp ebp,esp 00455314 call __RTC_CheckEsp (0451230h) 00455319 mov esp,ebp 0045531B pop ebp 0045531C ret
|
IF-ELSE 语句架构
1 2 3 4 5 6 7
| test(cmp) reg,reg jCC L1 语句块1 jmp end L1: 语句块2 end:
|
奇数.偶数的判断
代码清单3-4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int no;
printf("请输入一个整数:"); scanf("%d", &no);
if (no % 2) { puts("该整数是奇数。"); } else { puts("该整数是偶数。"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 0094528F push offset string "\xc7\xeb\xca\xe4\xc8\xeb\xd2\xbb\xb8\xf6\xd5\xfb\xca\xfd\xa3\xba" (0947E28h) 00945294 call _printf (09413ACh) 00945299 add esp,4
0094529C lea eax,[no] 0094529F push eax 009452A0 push offset string "%d" (0947B30h) 009452A5 call _scanf (09413F2h) 009452AA add esp,8
009452AD mov eax,dword ptr [no] 009452B0 and eax,80000001h 009452B5 jns __$EncStackInitStart+50h (09452BCh) 009452B7 dec eax 009452B8 or eax,0FFFFFFFEh 009452BB inc eax 009452BC test eax,eax 009452BE je __$EncStackInitStart+6Dh (09452D9h)
009452C0 mov esi,esp 009452C2 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xca\xc7\xc6\xe6\xca\xfd\xa1\xa3" (0947BD8h) 009452C7 call dword ptr [__imp__puts (094B170h)] 009452CD add esp,4 009452D0 cmp esi,esp 009452D2 call __RTC_CheckEsp (0941230h) 009452D7 jmp __$EncStackInitStart+84h (09452F0h)
009452D9 mov esi,esp 009452DB push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xca\xc7\xc5\xbc\xca\xfd\xa1\xa3" (0947CD8h) 009452E0 call dword ptr [__imp__puts (094B170h)] 009452E6 add esp,4 009452E9 cmp esi,esp 009452EB call __RTC_CheckEsp (0941230h)
009452F0 xor eax,eax
|
非0的判断
判断输入的值是否为 0 的程序。
代码清单3-5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int num;
printf("请输入一个整数:"); scanf("%d", &num);
if (num) { puts("该整数不是0。"); } else { puts("该整数是0。"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 002252AD cmp dword ptr [num],0 002252B1 je __$EncStackInitStart+60h (02252CCh) 002252B3 mov esi,esp 002252B5 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xb2\xbb\xca\xc70\xa1\xa3" (0227BD8h) 002252BA call dword ptr [__imp__puts (022B170h)] 002252C0 add esp,4 002252C3 cmp esi,esp 002252C5 call __RTC_CheckEsp (0221230h) 002252CA jmp __$EncStackInitStart+77h (02252E3h)
002252CC mov esi,esp 002252CE push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xca\xc70\xa1\xa3" (0227CD8h) 002252D3 call dword ptr [__imp__puts (022B170h)] 002252D9 add esp,4 002252DC cmp esi,esp 002252DE call __RTC_CheckEsp (0221230h)
002252E3 xor eax,eax
|
相等运算符
输入两个整数的值,判断他们是否相等。
代码清单3-6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1, n2;
puts("请输入两个整数:"); printf("整数1:"); scanf("%d", &n1); printf("整数2:"); scanf("%d", &n2);
if (n1 == n2) { puts("它们相等。"); } else { puts("它们不相等。"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 00A552E2 mov eax,dword ptr [n1] 00A552E5 cmp eax,dword ptr [n2] 00A552E8 jne __$EncStackInitStart+97h (0A55303h)
00A552EA mov esi,esp 00A552EC push offset string "\xcb\xfc\xc3\xc7\xcf\xe0\xb5\xc8\xa1\xa3" (0A57BDCh) 00A552F1 call dword ptr [__imp__puts (0A5B170h)] 00A552F7 add esp,4 00A552FA cmp esi,esp 00A552FC call __RTC_CheckEsp (0A51230h) 00A55301 jmp __$EncStackInitStart+0AEh (0A5531Ah) 00A55303 mov esi,esp 00A55305 push offset string "\xcb\xfc\xc3\xc7\xb2\xbb\xcf\xe0\xb5\xc8\xa1\xa3" (0A57BE8h) 00A5530A call dword ptr [__imp__puts (0A5B170h)] 00A55310 add esp,4 00A55313 cmp esi,esp 00A55315 call __RTC_CheckEsp (0A51230h)
00A5531A xor eax,eax
|
代码清单3-7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1, n2;
puts("请输入两个整数:"); printf("整数1:"); scanf("%d", &n1); printf("整数2:"); scanf("%d", &n2);
if (n1 != n2) { puts("它们不相等。"); } else { puts("它们相等。"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 007552E2 mov eax,dword ptr [n1] 007552E5 cmp eax,dword ptr [n2] 007552E8 je __$EncStackInitStart+97h (0755303h) 007552EA mov esi,esp 007552EC push offset string "\xcb\xfc\xc3\xc7\xb2\xbb\xcf\xe0\xb5\xc8\xa1\xa3" (0757CE0h) 007552F1 call dword ptr [__imp__puts (075B170h)] 007552F7 add esp,4 007552FA cmp esi,esp 007552FC call __RTC_CheckEsp (0751230h) 00755301 jmp __$EncStackInitStart+0AEh (075531Ah) 00755303 mov esi,esp 00755305 push offset string "\xcb\xfc\xc3\xc7\xcf\xe0\xb5\xc8\xa1\xa3" (0757BE8h) 0075530A call dword ptr [__imp__puts (075B170h)] 00755310 add esp,4 00755313 cmp esi,esp 00755315 call __RTC_CheckEsp (0751230h)
0075531A xor eax,eax
|
余数的判断
判断所输入的整数的个数是否为5,并显示相应信息的程序。
代码清单3-8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int num;
printf("请输入一个整数:"); scanf("%d", &num);
if (num % 10 == 5) { puts("该整数的个位数是5。"); } else { puts("该整数的个位数不是5。"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 00FD52AD mov eax,dword ptr [num] 00FD52B0 cdq 00FD52B1 mov ecx,0Ah 00FD52B6 idiv eax,ecx 00FD52B8 cmp edx,5 00FD52BB jne __$EncStackInitStart+6Ah (0FD52D6h)
00FD52BD mov esi,esp 00FD52BF push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xb5\xc4\xb8\xf6\xce\xbb\xca\xfd\xca\xc75\xa1\xa3" (0FD7CF0h) 00FD52C4 call dword ptr [__imp__puts (0FDB170h)] 00FD52CA add esp,4 00FD52CD cmp esi,esp 00FD52CF call __RTC_CheckEsp (0FD1230h) 00FD52D4 jmp __$EncStackInitStart+81h (0FD52EDh)
00FD52D6 mov esi,esp 00FD52D8 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xb5\xc4\xb8\xf6\xce\xbb\xca\xfd\xb2\xbb\xca\xc75\xa1\xa3" (0FD7E3Ch) 00FD52DD call dword ptr [__imp__puts (0FDB170h)] 00FD52E3 add esp,4 00FD52E6 cmp esi,esp 00FD52E8 call __RTC_CheckEsp (0FD1230h)
00FD52ED xor eax,eax
|
关系运算符
输入一个整数,判断该整数的符号
代码清单3-9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int no;
printf("请输入一个整数:"); scanf("%d", &no);
if (no == 0) puts("该整数为0。"); else if (no > 0) printf("该整数为正数。"); else puts("该整数为负数"); return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 00BD52AD cmp dword ptr [no],0 00BD52B1 jne __$EncStackInitStart+60h (0BD52CCh)
00BD52B3 mov esi,esp 00BD52B5 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xce\xaa0\xa1\xa3" (0BD7CF0h) 00BD52BA call dword ptr [__imp__puts (0BDB170h)] 00BD52C0 add esp,4 00BD52C3 cmp esi,esp 00BD52C5 call __RTC_CheckEsp (0BD1230h) 00BD52CA jmp __$EncStackInitStart+8Ch (0BD52F8h)
00BD52CC cmp dword ptr [no],0 00BD52D0 jle __$EncStackInitStart+75h (0BD52E1h) 00BD52D2 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xce\xaa\xd5\xfd\xca\xfd\xa1\xa3" (0BD7E3Ch) 00BD52D7 call _printf (0BD13ACh) 00BD52DC add esp,4 00BD52DF jmp __$EncStackInitStart+8Ch (0BD52F8h)
00BD52E1 mov esi,esp 00BD52E3 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xce\xaa\xb8\xba\xca\xfd" (0BD7BD8h) 00BD52E8 call dword ptr [__imp__puts (0BDB170h)] 00BD52EE add esp,4 00BD52F1 cmp esi,esp 00BD52F3 call __RTC_CheckEsp (0BD1230h)
00BD52F8 xor eax,eax
|
else-if 反汇编框架
1 2 3 4 5 6 7 8 9 10 11 12
| cmp xxx,xxx JCC L1 语句块1 jmp end L1: cmp xxx,xxx JCC L2 语句块2 jmp end L2: 语句块3 end:
|
嵌套if语句
代码清单3-10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int no;
printf("请输入一个整数:"); scanf("%d", &no);
if (no > 0) { if (no % 2 == 0) puts("该整数为偶数。"); else puts("该整数为奇数。"); } else { puts("您输入的不是正数。"); } return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| 00F452AD cmp dword ptr [no],0 00F452B1 jle __$EncStackInitStart+8Ch (0F452F8h)
00F452B3 mov eax,dword ptr [no] 00F452B6 and eax,80000001h 00F452BB jns __$EncStackInitStart+56h (0F452C2h) 00F452BD dec eax 00F452BE or eax,0FFFFFFFEh 00F452C1 inc eax 00F452C2 test eax,eax 00F452C4 jne __$EncStackInitStart+73h (0F452DFh)
00F452C6 mov esi,esp 00F452C8 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xce\xaa\xc5\xbc\xca\xfd\xa1\xa3" (0F47CF0h) 00F452CD call dword ptr [__imp__puts (0F4B170h)] 00F452D3 add esp,4 00F452D6 cmp esi,esp 00F452D8 call __RTC_CheckEsp (0F41230h) 00F452DD jmp __$EncStackInitStart+8Ah (0F452F6h) 00F452DF mov esi,esp 00F452E1 push offset string "\xb8\xc3\xd5\xfb\xca\xfd\xce\xaa\xc6\xe6\xca\xfd\xa1\xa3" (0F47E3Ch) 00F452E6 call dword ptr [__imp__puts (0F4B170h)] 00F452EC add esp,4 00F452EF cmp esi,esp 00F452F1 call __RTC_CheckEsp (0F41230h) 00F452F6 jmp __$EncStackInitStart+0A3h (0F4530Fh)
00F452F8 mov esi,esp 00F452FA push offset string "\xc4\xfa\xca\xe4\xc8\xeb\xb5\xc4\xb2\xbb\xca\xc7\xd5\xfd\xca\xfd\xa1\xa3" (0F47BD8h) 00F452FF call dword ptr [__imp__puts (0F4B170h)] 00F45305 add esp,4 00F45308 cmp esi,esp 00F4530A call __RTC_CheckEsp (0F41230h)
|
嵌套 if 语句架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| cmp xxx,xxx JCC if_1
{cmp xxx,xxx JCC if_2
嵌套if语句块 jmp con
if_2: 嵌套else语句块 con:jmp end}
{if_1:xxx}
end:
|
计算较大值
输入两个整数,显示其中较大的值。
代码清单3-11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1,n2;
puts("输入两个整数。"); printf("整数1:"); scanf("%d", &n1); printf("整数2:"); scanf("%d", &n2);
if (n1 > n2) printf("较大的数是%d。\n", n1); else printf("较大的数是%d。 \n", n2); return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 00E252E2 mov eax,dword ptr [n1] 00E252E5 cmp eax,dword ptr [n2] 00E252E8 jle __$EncStackInitStart+91h (0E252FDh) 00E252EA mov eax,dword ptr [n1] 00E252ED push eax 00E252EE push offset string "\xbd\xcf\xb4\xf3\xb5\xc4\xca\xfd\xca\xc7%d\xa1\xa3\n" (0E27BD8h) 00E252F3 call _printf (0E213ACh) 00E252F8 add esp,8 00E252FB jmp __$EncStackInitStart+0A2h (0E2530Eh)
00E252FD mov eax,dword ptr [n2] 00E25300 push eax 00E25301 push offset string "\xbd\xcf\xb4\xf3\xb5\xc4\xca\xfd\xca\xc7%d\xa1\xa3 \n" (0E27CD8h) 00E25306 call _printf (0E213ACh) 00E2530B add esp,8
00E2530E xor eax,eax
|
代码清单3-12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1,n2,max;
puts("请输入两个整数。"); printf("整数1:"); scanf("%d", &n1); printf("整数2:"); scanf("%d", &n2);
if (n1 > n2) max = n1; else max = n2;
printf("较大的数是%d。\n", max); return 0; }
|
计算三个数的最大值
这次输入三个整数,显示出其中的最大值。
代码清单3-13
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1,n2,n3,max;
puts("请输入三个整数。"); printf("整数1:"); scanf("%d", &n1); printf("整数2:"); scanf("%d", &n2); printf("整数3:"); scanf("%d", &n3);
max = n1; if (n2 > max) max = n2; if (n3 > max) max = n3;
printf("较大的数是%d。\n", max); return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13
| 00165306 mov eax,dword ptr [n2] 00165309 cmp eax,dword ptr [max] 0016530C jle __$EncStackInitStart+0A8h (0165314h) 0016530E mov eax,dword ptr [n2] 00165311 mov dword ptr [max],eax
00165314 mov eax,dword ptr [n3] 00165317 cmp eax,dword ptr [max] 0016531A jle __$EncStackInitStart+0B6h (0165322h) 0016531C mov eax,dword ptr [n3] 0016531F mov dword ptr [max],eax
|
条件运算符
代码清单3-14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1,n2,max;
puts("请输入三个整数。"); printf("整数1:"); scanf("%d", &n1); printf("整数2:"); scanf("%d", &n2);
max = (n1 > n2) ? n1 : n2;
printf("较大的数是%d。\n", max); return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11
| max = (n1 > n2) ? n1 : n2; 00C352E2 mov eax,dword ptr [n1] 00C352E5 cmp eax,dword ptr [n2] 00C352E8 jle __$EncStackInitStart+89h (0C352F5h) 00C352EA mov ecx,dword ptr [n1] 00C352ED mov dword ptr [ebp-0ECh],ecx 00C352F3 jmp __$EncStackInitStart+92h (0C352FEh) 00C352F5 mov edx,dword ptr [n2] 00C352F8 mov dword ptr [ebp-0ECh],edx 00C352FE mov eax,dword ptr [ebp-0ECh] 00C35304 mov dword ptr [max],eax
|
差值运算
使用条件运算符计算输入的两个整数差值的程序。
代码清单3-15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1,n2;
puts("请输入两个整数。"); printf("整数1:"); scanf("%d", &n1); printf("整数2:"); scanf("%d", &n2);
printf("较大的数是%d。\n", (n1 > n2) ? n1 - n2 : n2 - n1); return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 00A152E2 mov eax,dword ptr [n1] 00A152E5 cmp eax,dword ptr [n2] 00A152E8 jle __$EncStackInitStart+8Ch (0A152F8h) 00A152EA mov ecx,dword ptr [n1] 00A152ED sub ecx,dword ptr [n2] 00A152F0 mov dword ptr [ebp-0E0h],ecx 00A152F6 jmp __$EncStackInitStart+98h (0A15304h) 00A152F8 mov edx,dword ptr [n2] 00A152FB sub edx,dword ptr [n1] 00A152FE mov dword ptr [ebp-0E0h],edx 00A15304 mov eax,dword ptr [ebp-0E0h] 00A1530A push eax 00A1530B push offset string "\xbd\xcf\xb4\xf3\xb5\xc4\xca\xfd\xca\xc7%d\xa1\xa3\n" (0A17CD8h) 00A15310 call _printf (0A113ACh) 00A15315 add esp,8
|
复合语句
计算输入的两个整数中的较大值和较小值的程序。
代码清单3-16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1,n2,max,min;
puts("请输入两个整数。"); printf("整数1:"); scanf("%d", &n1); printf("整数2:"); scanf("%d", &n2);
if (n1 > n2) { max = n1; min = n2; } else { max = n2; min = n1; }
printf("较大的数是%d。\n", max); printf("较小的数是%d。\n", min); return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 001B52E2 mov eax,dword ptr [n1] 001B52E5 cmp eax,dword ptr [n2] 001B52E8 jle __$EncStackInitStart+8Ch (01B52F8h) 001B52EA mov eax,dword ptr [n1] 001B52ED mov dword ptr [max],eax 001B52F0 mov eax,dword ptr [n2] 001B52F3 mov dword ptr [min],eax 001B52F6 jmp __$EncStackInitStart+98h (01B5304h)
001B52F8 mov eax,dword ptr [n2] 001B52FB mov dword ptr [max],eax 001B52FE mov eax,dword ptr [n1] 001B5301 mov dword ptr [min],eax
|
逻辑运算符
代码清单3-17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int month;
printf("请输入月份:"); scanf("%d", &month);
if (month >= 3 && month <= 5) printf("%d月是春季。\n", month); else if (month >= 6 && month <= 8) printf("%d月是夏季。\n", month); else if (month >= 9 && month <= 11) printf("%d月是秋季。\n", month); else if (month == 1 || month == 2) printf("%d月是冬季。\n", month); else printf("%d月不存在!!\a\n", month); return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 007052AD cmp dword ptr [month],3 007052B1 jl __$EncStackInitStart+60h (07052CCh) 007052B3 cmp dword ptr [month],5 007052B7 jg __$EncStackInitStart+60h (07052CCh) 007052B9 mov eax,dword ptr [month] 007052BC push eax 007052BD push offset string "%\xd4\xc2\xca\xc7\xb4\xba\xbc\xbe\xa1\xa3\n" (0707CF0h) 007052C2 call _printf (07013ACh) 007052C7 add esp,8 007052CA jmp __$EncStackInitStart+0CEh (070533Ah)
007052CC cmp dword ptr [month],6 007052D0 jl __$EncStackInitStart+7Fh (07052EBh) 007052D2 cmp dword ptr [month],8 007052D6 jg __$EncStackInitStart+7Fh (07052EBh) 007052D8 mov eax,dword ptr [month] 007052DB push eax 007052DC push offset string "%d\xd4\xc2\xca\xc7\xcf\xc4\xbc\xbe\xa1\xa3\n" (0707E3Ch) 007052E1 call _printf (07013ACh) 007052E6 add esp,8 007052E9 jmp __$EncStackInitStart+0CEh (070533Ah)
007052EB cmp dword ptr [month],9 007052EF jl __$EncStackInitStart+9Eh (070530Ah) 007052F1 cmp dword ptr [month],0Bh 007052F5 jg __$EncStackInitStart+9Eh (070530Ah) 007052F7 mov eax,dword ptr [month] 007052FA push eax 007052FB push offset string "%d\xd4\xc2\xca\xc7\xc7\xef\xbc\xbe\xa1\xa3\n" (0707CD8h) 00705300 call _printf (07013ACh) 00705305 add esp,8 00705308 jmp __$EncStackInitStart+0CEh (070533Ah)
0070530A cmp dword ptr [month],1 0070530E je __$EncStackInitStart+0AAh (0705316h) 00705310 cmp dword ptr [month],2 00705314 jne __$EncStackInitStart+0BDh (0705329h) 00705316 mov eax,dword ptr [month] 00705319 push eax 0070531A push offset string "%d\xd4\xc2\xca\xc7\xb6\xac\xbc\xbe\xa1\xa3\n" (0707BD8h) 0070531F call _printf (07013ACh) 00705324 add esp,8 00705327 jmp __$EncStackInitStart+0CEh (070533Ah)
00705329 mov eax,dword ptr [month] 0070532C push eax 0070532D push offset string "%d\xd4\xc2\xb2\xbb\xb4\xe6\xd4\xda!!\x07\n" (0707BE8h) 00705332 call _printf (07013ACh) 00705337 add esp,8
0070533A xor eax,eax
|
短路求值
在《80386汇编-条件处理》这篇笔记中有演示使用短路求值优化代码,这里也是一个意思。我们优先判断重要的表达式,如果该表达式不成立,那么后续就不需要再去判断;如果表达式成立,再去判断第二个表达式。
switch语句
if语句是将程序分成两个分支,switch 语句,则会将程序分为多个分支。
switch 语句和break语句
显示输入的整数除以3所得余数的程序
代码清单3-18
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int no;
printf("请输入一个整数:"); scanf("%d", &no);
if (no % 3 == 0) puts("该数能被3整除。"); else if (no % 3 == 1) puts("该数除以3的余数是1。"); else puts("该数除以3的余数是2。");
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 005A52AD mov eax,dword ptr [no] 005A52B0 cdq 005A52B1 mov ecx,3 005A52B6 idiv eax,ecx 005A52B8 test edx,edx 005A52BA jne __$EncStackInitStart+69h (05A52D5h) 005A52BC mov esi,esp 005A52BE push offset string "\xb8\xc3\xca\xfd\xc4\xdc\xb1\xbb3\xd5\xfb\xb3\xfd\xa1\xa3" (05A7CF0h) 005A52C3 call dword ptr [__imp__puts (05AB170h)] 005A52C9 add esp,4 005A52CC cmp esi,esp 005A52CE call __RTC_CheckEsp (05A1230h) 005A52D3 jmp __$EncStackInitStart+0A9h (05A5315h)
005A52D5 mov eax,dword ptr [no] 005A52D8 cdq 005A52D9 mov ecx,3 005A52DE idiv eax,ecx 005A52E0 cmp edx,1 005A52E3 jne __$EncStackInitStart+92h (05A52FEh) 005A52E5 mov esi,esp 005A52E7 push offset string "\xb8\xc3\xca\xfd\xb3\xfd\xd2\xd43\xb5\xc4\xd3\xe0\xca\xfd\xca\xc71\xa1\xa3" (05A7E3Ch) 005A52EC call dword ptr [__imp__puts (05AB170h)] 005A52F2 add esp,4 005A52F5 cmp esi,esp 005A52F7 call __RTC_CheckEsp (05A1230h) 005A52FC jmp __$EncStackInitStart+0A9h (05A5315h)
005A52FE mov esi,esp 005A5300 push offset string "\xb8\xc3\xca\xfd\xb3\xfd\xd2\xd43\xb5\xc4\xd3\xe0\xca\xfd\xca\xc72\xa1\xa3" (05A7CD8h) 005A5305 call dword ptr [__imp__puts (05AB170h)] 005A530B add esp,4 005A530E cmp esi,esp 005A5310 call __RTC_CheckEsp (05A1230h)
|
代码清单3-19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int no;
printf("请输入一个整数:"); scanf("%d", &no);
switch (no % 3) { case 0: puts("该数能被3整除。"); break; case 1: puts("该数除以3的余数是1。"); break; case 2: puts("该数除以3的余数是2。"); break; }
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| 007D52AD mov eax,dword ptr [no] 007D52B0 cdq 007D52B1 mov ecx,3 007D52B6 idiv eax,ecx 007D52B8 mov dword ptr [ebp-0D4h],edx 007D52BE cmp dword ptr [ebp-0D4h],0 007D52C5 je __$EncStackInitStart+6Fh (07D52DBh) 007D52C7 cmp dword ptr [ebp-0D4h],1 007D52CE je __$EncStackInitStart+88h (07D52F4h) 007D52D0 cmp dword ptr [ebp-0D4h],2 007D52D7 je __$EncStackInitStart+0A1h (07D530Dh) 007D52D9 jmp __$EncStackInitStart+0B8h (07D5324h) 007D52DB mov esi,esp 007D52DD push offset string "\xb8\xc3\xca\xfd\xc4\xdc\xb1\xbb3\xd5\xfb\xb3\xfd\xa1\xa3" (07D7CF0h) 007D52E2 call dword ptr [__imp__puts (07DB170h)] 007D52E8 add esp,4 007D52EB cmp esi,esp 007D52ED call __RTC_CheckEsp (07D1230h) 007D52F2 jmp __$EncStackInitStart+0B8h (07D5324h)
007D52F4 mov esi,esp 007D52F6 push offset string "\xb8\xc3\xca\xfd\xb3\xfd\xd2\xd43\xb5\xc4\xd3\xe0\xca\xfd\xca\xc71\xa1\xa3" (07D7E3Ch) 007D52FB call dword ptr [__imp__puts (07DB170h)] 007D5301 add esp,4 007D5304 cmp esi,esp 007D5306 call __RTC_CheckEsp (07D1230h) 007D530B jmp __$EncStackInitStart+0B8h (07D5324h)
007D530D mov esi,esp 007D530F push offset string "\xb8\xc3\xca\xfd\xb3\xfd\xd2\xd43\xb5\xc4\xd3\xe0\xca\xfd\xca\xc72\xa1\xa3" (07D7CD8h) 007D5314 call dword ptr [__imp__puts (07DB170h)] 007D531A add esp,4 007D531D cmp esi,esp 007D531F call __RTC_CheckEsp (07D1230h)
007D5324 xor eax,eax
|
当case判断语句小于等于3个时:switch语句是将 case 后面的整数作为判断值进行判断并跳转到相应位置。break 语句就是使用jmp 指令跳出switch语句。关键特征:会有连续的cmp和JCC指令。
代码清单3-19-1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int sw;
printf("整数:"); scanf("%d", &sw);
switch (sw%3) { case 0: puts("A"); break; case 1: puts("C"); case 2: puts("D"); break; case 3: puts("B"); }
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 00F152AD mov eax,dword ptr [sw] 00F152B0 cdq 00F152B1 mov ecx,3 00F152B6 idiv eax,ecx 00F152B8 mov dword ptr [ebp-0D4h],edx 00F152BE cmp dword ptr [ebp-0D4h],3 00F152C5 ja $LN7+17h (0F15334h) 00F152C7 mov edx,dword ptr [ebp-0D4h] 00F152CD jmp dword ptr [edx*4+0F15380h] 00F152D4 mov esi,esp 00F152D6 push offset string "A" (0F17CF0h) 00F152DB call dword ptr [__imp__puts (0F1B170h)] 00F152E1 add esp,4 00F152E4 cmp esi,esp 00F152E6 call __RTC_CheckEsp (0F11230h) 00F152EB jmp $LN7+17h (0F15334h) 00F152ED mov esi,esp 00F152EF push offset string "C" (0F17E3Ch) 00F152F4 call dword ptr [__imp__puts (0F1B170h)] 00F152FA add esp,4 00F152FD cmp esi,esp 00F152FF call __RTC_CheckEsp (0F11230h) 00F15304 mov esi,esp 00F15306 push offset string "D" (0F17CD8h) 00F1530B call dword ptr [__imp__puts (0F1B170h)] 00F15311 add esp,4 00F15314 cmp esi,esp 00F15316 call __RTC_CheckEsp (0F11230h) 00F1531B jmp $LN7+17h (0F15334h) 00F1531D mov esi,esp 00F1531F push offset string "B" (0F17B34h) 00F15324 call dword ptr [__imp__puts (0F1B170h)] 00F1532A add esp,4 00F1532D cmp esi,esp 00F1532F call __RTC_CheckEsp (0F11230h)
00F15334 xor eax,eax
|
当case判断语句大于3个,且判断的整数是连续时,switch 语句会生成一个地址表。switch 语句会先去判断当前整数是否大于 case 语句中【最大的整数-最小整数】的值(因此是指令 cmp xxx,[3-0]),如果大于就退出switch语句,如果不大于,switch 就会将【switch的整数*4+地址表的偏移地址】,以此来跳转到相应的case语句。
代码清单3-19-2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int sw;
printf("整数:"); scanf("%d", &sw);
switch (sw%3) { case 1: puts("A"); break; case 2: puts("C"); case 3: puts("D"); break; case 4: puts("B"); }
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 008652AD mov eax,dword ptr [sw] 008652B0 cdq 008652B1 mov ecx,3 008652B6 idiv eax,ecx 008652B8 mov dword ptr [ebp-0D4h],edx 008652BE mov edx,dword ptr [ebp-0D4h] 008652C4 sub edx,1 008652C7 mov dword ptr [ebp-0D4h],edx 008652CD cmp dword ptr [ebp-0D4h],3 008652D4 ja $LN7+17h (0865343h) 008652D6 mov eax,dword ptr [ebp-0D4h] 008652DC jmp dword ptr [eax*4+86538Ch] 008652E3 mov esi,esp 008652E5 push offset string "A" (0867CF0h) 008652EA call dword ptr [__imp__puts (086B170h)] 008652F0 add esp,4 008652F3 cmp esi,esp 008652F5 call __RTC_CheckEsp (0861230h) 008652FA jmp $LN7+17h (0865343h) 008652FC mov esi,esp 008652FE push offset string "C" (0867E3Ch) 00865303 call dword ptr [__imp__puts (086B170h)] 00865309 add esp,4 0086530C cmp esi,esp 0086530E call __RTC_CheckEsp (0861230h) 00865313 mov esi,esp 00865315 push offset string "D" (0867CD8h) 0086531A call dword ptr [__imp__puts (086B170h)] 00865320 add esp,4 00865323 cmp esi,esp 00865325 call __RTC_CheckEsp (0861230h) 0086532A jmp $LN7+17h (0865343h) 0086532C mov esi,esp 0086532E push offset string "B" (0867B34h) 00865333 call dword ptr [__imp__puts (086B170h)] 00865339 add esp,4 0086533C cmp esi,esp 0086533E call __RTC_CheckEsp (0861230h)
00865343 xor eax,eax
|
代码清单3-19-3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int sw;
printf("整数:"); scanf("%d", &sw);
switch (sw%3) { case 2: puts("A"); break; case 3: puts("C"); case 4: puts("D"); break; case 5: puts("B"); }
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 000A52AD mov eax,dword ptr [sw] 000A52B0 cdq 000A52B1 mov ecx,3 000A52B6 idiv eax,ecx 000A52B8 mov dword ptr [ebp-0D4h],edx 000A52BE mov edx,dword ptr [ebp-0D4h] 000A52C4 sub edx,2 000A52C7 mov dword ptr [ebp-0D4h],edx 000A52CD cmp dword ptr [ebp-0D4h],3 000A52D4 ja $LN7+17h (0A5343h) 000A52D6 mov eax,dword ptr [ebp-0D4h] 000A52DC jmp dword ptr [eax*4+0A538Ch] 000A52E3 mov esi,esp 000A52E5 push offset string "A" (0A7CF0h) 000A52EA call dword ptr [__imp__puts (0AB170h)] 000A52F0 add esp,4 000A52F3 cmp esi,esp 000A52F5 call __RTC_CheckEsp (0A1230h) 000A52FA jmp $LN7+17h (0A5343h) 000A52FC mov esi,esp 000A52FE push offset string "C" (0A7E3Ch) 000A5303 call dword ptr [__imp__puts (0AB170h)] 000A5309 add esp,4 000A530C cmp esi,esp 000A530E call __RTC_CheckEsp (0A1230h) 000A5313 mov esi,esp 000A5315 push offset string "D" (0A7CD8h) 000A531A call dword ptr [__imp__puts (0AB170h)] 000A5320 add esp,4 000A5323 cmp esi,esp 000A5325 call __RTC_CheckEsp (0A1230h) 000A532A jmp $LN7+17h (0A5343h) 000A532C mov esi,esp 000A532E push offset string "B" (0A7B34h) 000A5333 call dword ptr [__imp__puts (0AB170h)] 000A5339 add esp,4 000A533C cmp esi,esp 000A533E call __RTC_CheckEsp (0A1230h)
000A5343 xor eax,eax
|
当case判断不是从0开始,switch 语句会增加指令 【sub switch的整数,case最小的整数】
代码清单3-19-4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int sw;
printf("整数:"); scanf("%d", &sw);
switch (sw%3) { case 1: puts("A"); break; case 2: puts("C"); case 5: puts("D"); break; case 6: puts("B"); case 7: puts("E"); break; }
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| 003052AD mov eax,dword ptr [sw] 003052B0 cdq 003052B1 mov ecx,3 003052B6 idiv eax,ecx 003052B8 mov dword ptr [ebp-0D4h],edx 003052BE mov edx,dword ptr [ebp-0D4h] 003052C4 sub edx,1 003052C7 mov dword ptr [ebp-0D4h],edx 003052CD cmp dword ptr [ebp-0D4h],6 003052D4 ja $LN8+17h (030535Eh) 003052DA mov eax,dword ptr [ebp-0D4h] 003052E0 jmp dword ptr [eax*4+3053A8h] 003052E7 mov esi,esp 003052E9 push offset string "A" (0307CF0h) 003052EE call dword ptr [__imp__puts (030B170h)] 003052F4 add esp,4 003052F7 cmp esi,esp 003052F9 call __RTC_CheckEsp (0301230h) 003052FE jmp $LN8+17h (030535Eh) 00305300 mov esi,esp 00305302 push offset string "C" (0307E3Ch) 00305307 call dword ptr [__imp__puts (030B170h)] 0030530D add esp,4 00305310 cmp esi,esp 00305312 call __RTC_CheckEsp (0301230h) 00305317 mov esi,esp 00305319 push offset string "D" (0307CD8h) 0030531E call dword ptr [__imp__puts (030B170h)] 00305324 add esp,4 00305327 cmp esi,esp 00305329 call __RTC_CheckEsp (0301230h) 0030532E jmp $LN8+17h (030535Eh) 00305330 mov esi,esp 00305332 push offset string "B" (0307B34h) 00305337 call dword ptr [__imp__puts (030B170h)] 0030533D add esp,4 00305340 cmp esi,esp 00305342 call __RTC_CheckEsp (0301230h) 00305347 mov esi,esp 00305349 push offset string "E" (0307B38h) 0030534E call dword ptr [__imp__puts (030B170h)] 00305354 add esp,4 00305357 cmp esi,esp 00305359 call __RTC_CheckEsp (0301230h)
0030535E xor eax,eax
|
如果case语句判断值不是连续的整数,那么switch地址表空出来的位置都会用 switch 语句后的地址作为填充。特征:填充的地址与break语句(jmp)跳转的地址是一样的。
代码清单3-19-5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int sw;
printf("整数:"); scanf("%d", &sw);
switch (sw) { case 1: puts("A"); break; case 2: puts("C"); case 5: puts("D"); break; case 6: case 7: puts("E"); break; }
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| 010152AD mov eax,dword ptr [sw] 010152B0 mov dword ptr [ebp-0D4h],eax 010152B6 mov ecx,dword ptr [ebp-0D4h] 010152BC sub ecx,1 010152BF mov dword ptr [ebp-0D4h],ecx 010152C5 cmp dword ptr [ebp-0D4h],6 010152CC ja $LN8+17h (0101533Bh) 010152CE mov edx,dword ptr [ebp-0D4h] 010152D4 jmp dword ptr [edx*4+1015384h] 010152DB mov esi,esp 010152DD push offset string "A" (01017CF0h) 010152E2 call dword ptr [__imp__puts (0101B170h)] 010152E8 add esp,4 010152EB cmp esi,esp 010152ED call __RTC_CheckEsp (01011230h) 010152F2 jmp $LN8+17h (0101533Bh) 010152F4 mov esi,esp 010152F6 push offset string "C" (01017E3Ch) 010152FB call dword ptr [__imp__puts (0101B170h)] 01015301 add esp,4 01015304 cmp esi,esp 01015306 call __RTC_CheckEsp (01011230h) 0101530B mov esi,esp 0101530D push offset string "D" (01017CD8h) 01015312 call dword ptr [__imp__puts (0101B170h)] 01015318 add esp,4 0101531B cmp esi,esp 0101531D call __RTC_CheckEsp (01011230h) 01015322 jmp $LN8+17h (0101533Bh) 01015324 mov esi,esp 01015326 push offset string "E" (01017B34h) 0101532B call dword ptr [__imp__puts (0101B170h)] 01015331 add esp,4 01015334 cmp esi,esp 01015336 call __RTC_CheckEsp (01011230h)
0101533B xor eax,eax
|
如果有case判断中没有语句块,那么switch地址表中填充相邻的下一个case语句的地址。
例如:
此时switch表中就会填充 case 6 的地址。
代码清单3-19-6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int sw;
printf("整数:"); scanf("%d", &sw);
switch (sw) { case 1: puts("A"); break; case 2: puts("C"); case 5: break; case 6: case 7: puts("E"); break; }
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| 009552AD mov eax,dword ptr [sw] 009552B0 mov dword ptr [ebp-0D4h],eax 009552B6 mov ecx,dword ptr [ebp-0D4h] 009552BC sub ecx,1 009552BF mov dword ptr [ebp-0D4h],ecx 009552C5 cmp dword ptr [ebp-0D4h],6 009552CC ja $LN8+17h (0955324h) 009552CE mov edx,dword ptr [ebp-0D4h] 009552D4 jmp dword ptr [edx*4+955370h] 009552DB mov esi,esp 009552DD push offset string "A" (0957CF0h) 009552E2 call dword ptr [__imp__puts (095B170h)] 009552E8 add esp,4 009552EB cmp esi,esp 009552ED call __RTC_CheckEsp (0951230h) 009552F2 jmp $LN8+17h (0955324h) 009552F4 mov esi,esp 009552F6 push offset string "C" (0957E3Ch) 009552FB call dword ptr [__imp__puts (095B170h)] 00955301 add esp,4 00955304 cmp esi,esp 00955306 call __RTC_CheckEsp (0951230h) 0095530B jmp $LN8+17h (0955324h) 0095530D mov esi,esp 0095530F push offset string "E" (0957CD8h) 00955314 call dword ptr [__imp__puts (095B170h)] 0095531A add esp,4 0095531D cmp esi,esp 0095531F call __RTC_CheckEsp (0951230h)
00955324 xor eax,eax
|
如果case没有语句块,且下面相邻的case也没有语句块,那么 switch 表中填充switch语句后的地址。
复杂的 switch 语句
通过复杂的switch语句来加深对该语句的理解。
代码清单3-20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int sw;
printf("整数:"); scanf("%d", &sw);
switch (sw) { case 1: puts("A"); break; case 2: puts("C"); case 5: puts("D"); break; case 6: case 7: puts("E"); break; default:puts("F"); break; }
return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| 00F552AD mov eax,dword ptr [sw] 00F552B0 mov dword ptr [ebp-0D4h],eax 00F552B6 mov ecx,dword ptr [ebp-0D4h] 00F552BC sub ecx,1 00F552BF mov dword ptr [ebp-0D4h],ecx 00F552C5 cmp dword ptr [ebp-0D4h],6 00F552CC ja $LN8+19h (0F5533Dh) 00F552CE mov edx,dword ptr [ebp-0D4h] 00F552D4 jmp dword ptr [edx*4+0F553A0h] 00F552DB mov esi,esp 00F552DD push offset string "A" (0F57CF0h) 00F552E2 call dword ptr [__imp__puts (0F5B170h)] 00F552E8 add esp,4 00F552EB cmp esi,esp 00F552ED call __RTC_CheckEsp (0F51230h) 00F552F2 jmp $LN8+30h (0F55354h) 00F552F4 mov esi,esp 00F552F6 push offset string "C" (0F57E3Ch) 00F552FB call dword ptr [__imp__puts (0F5B170h)] 00F55301 add esp,4 00F55304 cmp esi,esp 00F55306 call __RTC_CheckEsp (0F51230h) 00F5530B mov esi,esp 00F5530D push offset string "D" (0F57CD8h) 00F55312 call dword ptr [__imp__puts (0F5B170h)] 00F55318 add esp,4 00F5531B cmp esi,esp 00F5531D call __RTC_CheckEsp (0F51230h) 00F55322 jmp $LN8+30h (0F55354h) 00F55324 mov esi,esp 00F55326 push offset string "E" (0F57B34h) 00F5532B call dword ptr [__imp__puts (0F5B170h)] 00F55331 add esp,4 00F55334 cmp esi,esp 00F55336 call __RTC_CheckEsp (0F51230h) 00F5533B jmp $LN8+30h (0F55354h) 00F5533D mov esi,esp 00F5533F push offset string "F" (0F57B38h) 00F55344 call dword ptr [__imp__puts (0F5B170h)] 00F5534A add esp,4 00F5534D cmp esi,esp 00F5534F call __RTC_CheckEsp (0F51230h)
00F55354 xor eax,eax
|
添加default语句后,switch地址表中空出来的位置都会插入 default 语句的地址。
switch 语句和if语句
选择语句: 本章学习的 if 语句和 switch 语句,都是用来实现程序流程的选择性分支的,因此统称为选择语句。
总结
summary1.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int month;
printf("请输入月份:"); scanf("%d", &month);
if (month < 1 || month>12) printf("%d月不存在!!\a\n", month); else if (month <= 2 || month == 12) printf("%d月是冬季。\n", month); else if (month >= 9) printf("%d月是秋季。\n", month); else if (month >= 6) printf("%d月是夏季。\n", month); else printf("%d月是春季。\n", month);
return 0; }
|
summary2.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int sw;
printf("请输入整数:"); scanf("%d", &sw);
switch (sw) { case 1: printf("红色"); break; case 2: printf("蓝色"); break; case 3: printf("白色"); break; }
return 0; }
|
summary3.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
#define _CRT_SECURE_NO_DEPRECATE #include <stdio.h>
int main(void) { int n1, n2; printf("请输入两个整数;"); scanf("%d%d", &n1,&n2);
if (n1 > n2) { printf("较大的数是n1。\n"); printf("它们的差是%d。\n", n1 - n2); } else { printf("较大的数是n2。\n"); printf("它们的差是%d。\n", n2 - n1); }
return 0; }
|
课后练习
练习3-1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y; printf("请输入两个整数:"); scanf("%d%d", &x, &y);
if (x % y) { printf("%d不是%d的约数。\n", y, x); } else { printf("%d是%d的约数。", y, x); } return 0; }
|
练习3-2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y; printf("请输入一个数字:"); scanf("%d", &x);
if (x > 0) { puts("输入的值是正数"); } else if (x < 0) { puts("输入的值是负数"); } else if (x == 0) { puts("输入的值是0"); } return 0; }
|
练习3-3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x; printf("请输入一个整数:"); scanf("%d", &x);
if (x > 0) { printf("绝对值是%d.\n", x); } else if (x == 0) { puts("绝对值是0."); } else { printf("绝对值是%d.\n", -x); } return 0; }
|
练习3-4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y; printf("请输入两个整数:"); scanf("%d%d", &x, &y);
if (x > y) { printf("%d大于%d.\n", x, y); } else if (x == y) { printf("%d等于%d.\n", x, y); } else { printf("%d小于%d.\n", x, y); } return 0; }
|
练习3-5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x; printf("请输入整数:"); scanf("%d", &x);
if ((x > 0) == 1) { printf("%d是正数.\n", x); } else if ((x == 0) == 1) { printf("输入的值是0.\n"); } else { printf("%d是负数.\n", x); } return 0; }
|
练习3-6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y, z, min; printf("请输入三个整数:"); scanf("%d%d%d", &x, &y, &z);
min = x; if (x > y) min = y; if (x > z) min = z; printf("三个整数中最小的是%d.\n", min);
return 0; }
|
练习3-7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y, z, o, max; printf("请输入四个整数:"); scanf("%d%d%d%d", &x, &y, &z, &o);
max = x; if (x < y) max = y; if (x < z) max = z; if (x < o) max = o; printf("四个整数中最大的是%d.\n", max);
return 0; }
|
练习3-8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y, z; printf("请输入两个整数:"); scanf("%d%d", &x, &y);
if (x > y) z = x - y; else z = y - x;
printf("两个整数的差为%d.\n", z);
return 0; }
|
练习3-9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y; printf("请输入第一个数字:"); scanf("%d", &x); printf("请输入第二个数字:"); scanf("%d", &y);
(x == y) ? printf("输入的两个值相等\n") : printf("输入的两个值不相等\n");
return 0; }
|
练习3-10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y, z; printf("请输入三个整数:"); scanf("%d%d%d", &x, &y, &z);
if (x == y == z) { puts("三个值都相等。"); } else if ((x != z) && (x == y)) { puts("有两个值相等。"); } else if ((x != y) && (x == z)) { puts("有两个值相等。"); } else if ((y != x) && (y == z)) { puts("有两个值相等。"); } else { puts("三个值各不相同。"); } return 0; }
|
练习3-11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x, y, z; printf("请输入两个整数:"); scanf("%d%d", &x, &y); z = (x > y) ? (x - y) : (y - x);
if (z <= 10) { puts("它们的差小于等于10"); } else { puts("它们的差大于等于 11 。"); } return 0; }
|
练习 3-12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x; printf("请输入一个整数:"); scanf("%d", &x);
(x % 3 == 0) ? printf("输入的整数是奇数。\n") : printf("输入的整数是偶数\n");
return 0; }
|
练习3-13
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
int main(void) { int x; printf("请输入一个整数:"); scanf("%d", &x);
switch (x) { case 1: printf("%d月份是冬季。\n", x); break; case 2: printf("%d月份是冬季。\n", x); break; case 3: printf("%d月份是冬季。\n", x); break; case 4: printf("%d月份是春季。\n", x); break; case 5: printf("%d月份是春季。\n", x); break; case 6: printf("%d月份是春季。\n", x); break; case 7: printf("%d月份是夏季。\n", x); break; case 8: printf("%d月份是夏季。\n", x); break; case 9: printf("%d月份是夏季。\n", x); break; case 10: printf("%d月份是秋季。\n", x); break; case 11: printf("%d月份是秋季。\n", x); break; case 12: printf("%d月份是秋季。\n", x); break; default: printf("输入错误。\n"); }
return 0; }
|