if…else語句
程序在執行的時候都是一行一行執行的,例如下面這行代碼:
#include <stdio.h> //頭文件
#include <windows.h>
void main() //程序入口
{
int x = 10; //賦值
int y = 20;
printf("x>y \n"); //輸出結果
return; //程序結束
}
如果我們想要讓程序按照我們的意思來執行,就要使用兩個語句:一個是分支語句(if),一個是循環語句(while),這篇文章主要說一下if語句。
if語句格式:
if(表達式)
語句;
else
語句;
或者
if(表達式)
{
語句1;
語句2;
}
else
{
語句1;
語句2;
}
例子:
#include <stdio.h> //頭文件
#include <windows.h>
void main() //程序入口
{
int x = 10; //賦值
int y = 20;
if(x>y) //進行判斷
printf("x>y \n"); //輸出判斷結果
else //若不符合上面的判斷條件輸出下面的結果
printf("x<y \n");
return; //程序結束
}
運行結果:
或者:
#include <stdio.h> //頭文件
#include <windows.h>
void main() //程序入口
{
int x = 10; //賦值
int y = 20;
if(x>y) //進行判斷
{
printf("*****計算結果爲*****\n"); //輸出判斷結果
printf("x>y \n");
}
else //若不符合上面的判斷條件輸出下面的結果
{
printf("*****計算結果爲*****\n");
printf("x<y \n");
}
printf("程序結束!\n"); //輸出結束語
return; //程序結束
}
if…else if…else if…else
這個就比較複雜了,如果第一次判斷不成立,那麼就會進行第二次判斷、第三次判斷等等,如果都不成立,那麼就會輸出else的語句。
格式
if(表達式)
{
語句1;
}
else if(表達式)
{
語句2;
}
else if(表達式)
{
語句3;
}
else
{
語句4;
}
例子:
#include <stdio.h> //頭文件
#include <windows.h>
void main() //程序入口
{
int x = 10; //變量賦值
if(x>11) //第一次判斷
{
printf("A \n"); //若成立輸出語句
}
else if(x<10) //第二次判斷
{
printf("B \n"); //若成立輸出語句
}
else if(x=10) //第三次判斷
{
printf("C \n"); //若成立輸出語句
}
else //若前三次判斷都不成立,輸出else語句
{
printf("D \n");
}
printf("程序結束! \n"); //輸出結束語
return; //程序結束
}
運行結果:
if語句嵌套
格式
if(表達式)
{
if...
}
else
{
if..
}
這裏舉一個例子,要求實現輸出三個數中的最大數:
#include <stdio.h> //頭文件
#include <windows.h>
int Max(int x,int y,int z) //定義函數Max
{
int r = 0; //定義一個可以儲存返回值的變量r
if(x>y) //判斷若成立執行下面的if語句
{
if(x>z) //若成立把值賦給r
{
r = x;
}
else //否則執行else語句
{
r = z; //把值賦給r
}
}
else //若上面的都不成立則執行else語句
{
if(y>z) //同上
{
r = y;
}
else
{
r = z;
}
}
return r; //把值返回到r裏
}
void main() //程序入口
{
int key = Max(1,2,3); //往函數裏傳參數
printf("最大數爲:%d\n",key); //輸出最終結果
return; //程序結束
}
運行效果:
從底層分析if語句
我們看一下if語句在彙編裏究竟是怎麼實現的,先上一段代碼:
#include <stdio.h> //頭文件
#include <windows.h>
void main() //程序入口
{
int x = 10; //賦值
int y = 20;
if(x>y) //執行判斷
{
printf("x>y"); //輸出結果
}
else //判斷不成立執行else語句
{
printf("x<y"); //輸出結果
}
return; //程序結束
}
這是它的彙編代碼:
先分析if語句
if(x>y)
{
printf("x>y");
}
彙編指令:
mov eax,dword ptr [ebp-4] //把10傳到eax裏
cmp eax,dword ptr [ebp-8] //10與20進行比較
jle main+3Dh (0040d73d) //若結果小於等於則跳轉
push offset string "x>y" (0042201c) //壓入字符串
call printf (00401070) //調用printf()函數
add esp,4 //外平棧進行堆棧平衡
這裏明顯會跳,10小於20,這裏如果跳的話,就跳到這段else代碼了:
else
{
printf("x<y");
}
彙編指令:
jmp main+4Ah (0040d74a) //無條件跳轉,這裏不會跳,因爲上面的jie跳過它了
push offset string "%d\n" (00422fb4) //壓入字符串
call printf (00401070) //調用printf()函數
add esp,4 //外平棧進行堆棧平衡
程序運行到else就會輸出結果到控制檯了,這裏主要是體會jie與jmp的邏輯關係,jie實現了跳轉,程序就會輸出x<y,如果沒有執行跳轉,那麼就會輸出x<y,然後跳過else語句,假如這是一個註冊機制的話,那這裏就是一個突破口。
逆一下自己的程序
還是以這段代碼爲例,這裏明明10小於20,我們讓它輸出x>y,也就是10>20。
#include <stdio.h> //頭文件
#include <windows.h>
void main() //程序入口
{
int x = 10; //賦值
int y = 20;
if(x>y) //執行判斷
{
printf("x>y"); //輸出結果
}
else //判斷不成立執行else語句
{
printf("x<y"); //輸出結果
}
return; //程序結束
}
我們先在斷尾下斷,不然程序閃一下就沒了,然後搜一下關鍵字來到程序判斷的地方。
我們把這裏的jle改爲je,也就是相等時則跳轉,這裏明顯不相等,所以不會挑。
然後單步往下走,看下結果:
這樣就成功的讓10>20了,下面的else語句也在程序執行到jmp指令的時候跳過了。如果這段代碼是實現充值或者註冊的話,結果就可想而知了。