純凈水企業(yè)怎樣做網(wǎng)站競價(jià)外包
目錄
- 一、緩沖區(qū)溢出的HelloWorld
- 二、永不停止的HelloWorld
- 三、基礎(chǔ)知識(shí)
- 3.1 變量的聲明
- 3.2 類型轉(zhuǎn)換(一般用于小轉(zhuǎn)大)
- 3.3 表達(dá)式
- 3.4 語句和程序塊
- 3.5 參數(shù)與返回值
- 3.6 關(guān)系運(yùn)算符
- 3.7 邏輯運(yùn)算符:&& || !
- 3.8 單目運(yùn)算符
- 3.9 三目運(yùn)算符
- 四、作業(yè)
- 1、交換兩個(gè)變量值
- 2、將一個(gè)數(shù)組中的數(shù)倒序輸出
- 3、找出數(shù)組里面最大的值,并返回
- 4、將數(shù)組所有的元素相加,將結(jié)果返回
- 5、將兩個(gè)等長數(shù)組相同位置的值相加,存儲(chǔ)到另外一個(gè)等長的數(shù)組中
- 6、寫一個(gè)函數(shù)int prime(int x),如果x是素?cái)?shù)返回值為1,否則返回0
- 7、倆倆比較數(shù)組的值,將最大的一個(gè)存儲(chǔ)到數(shù)組的最后一個(gè)位置
- 8、編寫程序?qū)崿F(xiàn)一個(gè)冒泡排序的算法
- 9、判斷數(shù)組是否是對稱的,如果是返回1,不是返回0
- 05 循環(huán)語句
一、緩沖區(qū)溢出的HelloWorld
void HelloWorld(){printf("Hello World");getchar();
}
void Fun(){int arr[5] = {1,2,3,4,5};arr[6] = (int)HelloWorld;
}
int main(int argc, char* argv[]){Fun();return 0;
}
原理:arr[5]是ebp的位置,而arr[6]是ebp+0x4的位置,即函數(shù)的返回地址,賦值給arr[6]相當(dāng)于是修改了eip寄存器。
二、永不停止的HelloWorld
void Fun(){int i;int arr[5] = {0};for(i = 0; i <= 7; i++){arr[i] = 0;printf("Hello World %d\n", i); //0-6循環(huán)出現(xiàn)}
}
int main(int argc, char* argv[]){Fun();return 0;
}
反匯編:i等于7時(shí),修改了rbp+0x1c-0x20即rbp-0x4位置的值,將其置為0,而該位置為i的值,所以每一輪for過后將i重新置0,就造成了不停的循環(huán)。
三、基礎(chǔ)知識(shí)
3.1 變量的聲明
- 聲明一個(gè)變量就是告訴計(jì)算機(jī),程序要用一塊內(nèi)存,這塊內(nèi)存需要保留,寬度和存儲(chǔ)格式由數(shù)據(jù)類型決定;
- 計(jì)算機(jī)什么時(shí)候把這塊內(nèi)存給你,取決于變量的作用范圍,如果是全局變量,在程序編譯完就已經(jīng)分配了空間,如果是局部變量,只有所在的程序被調(diào)用的時(shí)候,才會(huì)分配空間;
- 全局變量如果不賦初始值,默認(rèn)是0,但局部變量在使用前一定要賦初值。
3.2 類型轉(zhuǎn)換(一般用于小轉(zhuǎn)大)
- MOVSX 先符號(hào)擴(kuò)展(前面符號(hào)位是什么,就填充什么)
適用于有符號(hào)數(shù)
MOV AL,0xFF 000000FF
MOVSX CX,AL 0000FFFF
MOV AL,0x80 00000080
MOVSX CX,AL 0000FF80
- MOVZX 先零擴(kuò)展
適用于無符號(hào)數(shù)
MOV AL,0xFF 000000FF
MOVZX CX,AL 000000FF
MOV AL,0x80 00000080
MOVZX CX,AL 00000080
- 類型轉(zhuǎn)換舉例
有符號(hào)數(shù)擴(kuò)展 無符號(hào)數(shù)擴(kuò)展
char i = 0xFF; unsigned char i = 0xFF;
short k = 0xFFFF; unsigned short k = 0x00FF;
int h = 0xFFFFFFFF; unsigned int h = 0x00000000FF;
- 示例代碼
//有符號(hào)小轉(zhuǎn)大
void Function1(){char ci = 0xFF;short si = ci;int ni = ci;
}
//無符號(hào)小轉(zhuǎn)大
void Function2(){unsigned char ci = 0xFF;unsigned short si = ci;unsigned int ni = ci;
}
//有符號(hào)數(shù)大轉(zhuǎn)小
//截取低位
void Function1(){int ni = 0x12345678;short si = ni;char ci = si;
}
3.3 表達(dá)式
- 表達(dá)式的特點(diǎn)
- 表達(dá)式無論多么復(fù)雜,都只有一個(gè)結(jié)果;
- 只有表達(dá)式,可以編譯通過,但并不生成代碼,需要與賦值或者其他流程控制語句一起組合的時(shí)候才有意義;
- 當(dāng)表達(dá)式中存在不同寬度的變量時(shí),將結(jié)果轉(zhuǎn)換為寬度最大的那個(gè)。
char a;
int b;
a = 10;
b = 20;
printf("%d",a+b);
- 當(dāng)表達(dá)式中同時(shí)存在有符號(hào)和無符號(hào)數(shù)的時(shí)候,表達(dá)式的結(jié)構(gòu)將轉(zhuǎn)換為無符號(hào)數(shù)
unsigned char a;
char b;
a = 0xFE;
b = 1;
printf("%d",a+b);
char b = 1;
unsigned int a = 0xFFFFFFFE;
printf("%d",a+b);//結(jié)果為-1
原因:
? char b = 1;的匯編代碼是mov byte ptr [ebp-4],1
? unsigned int a = 0xFFFFFFFE;的匯編代碼是mov dword ptr [ebp-8],0xFFFFFFFE
? 執(zhí)行a+b的操作前,首先將b的值使用有符號(hào)擴(kuò)展,movsx eax,byte ptr [ebp-4],即0x00000001
? 接著執(zhí)行相加操作0xFFFFFFFE+0x00000001=0xFFFFFFFF,在計(jì)算機(jī)的底層,架構(gòu)存儲(chǔ)32位1。
? 輸出時(shí),因?yàn)槭褂玫氖恰癲%”,所以計(jì)算機(jī)將0xFFFFFFFF當(dāng)做有符號(hào)的-1輸出,反之使用“u%”時(shí)則輸出無符號(hào)的0xFFFFFFFF。(計(jì)算機(jī)底層存的東西是一樣的,有無符號(hào)只對人類有意義)
3.4 語句和程序塊
語句對cpu或內(nèi)存有影響
if-else語句是整體
3.5 參數(shù)與返回值
略
3.6 關(guān)系運(yùn)算符
“==”、“!=”、“>=”、“<=”、“>”、“<”
3.7 邏輯運(yùn)算符:&& || !
3.8 單目運(yùn)算符
輸出11-11
輸出11-10
3.9 三目運(yùn)算符
四、作業(yè)
1、交換兩個(gè)變量值
代碼:
void exchange(int x, int y){int temp;temp = x;x = y;y = temp;
}
2、將一個(gè)數(shù)組中的數(shù)倒序輸出
代碼:
void fun(){int arr[8] = {0,1,2,3,4,5,6,7};int n = 7;while (n>=0){printf("%d\n", arr[n]);n--;}
}int main()
{fun();return 0;
}
3、找出數(shù)組里面最大的值,并返回
代碼:
int fun(){int arr[8] = {0,1,2,3,4,5,6,7};int len = 8;int i;int max = 0;for(i = 0; i < len; i++){if(max <= arr[i]){max = arr[i];}}return max;
}int main()
{printf("%d\n", fun());return 0;
}
4、將數(shù)組所有的元素相加,將結(jié)果返回
代碼:
int fun(){int arr[8] = {0,1,2,3,4,5,6,7};int len = 8;int i;int num = 0;for(i = 0; i < len; i++){num += arr[i];}return num;
}
int main()
{printf("%d\n", fun());return 0;
}
5、將兩個(gè)等長數(shù)組相同位置的值相加,存儲(chǔ)到另外一個(gè)等長的數(shù)組中
代碼:
int arr1[8] = {0,1,2,3,4,5,6,7};
int arr2[8] = {0,1,2,3,4,5,6,7};
int arr3[8] = {0};
void fun(){int len = 8;int i;for(i = 0; i < len; i++){arr3[i] = arr1[i] + arr2[i];}
}
6、寫一個(gè)函數(shù)int prime(int x),如果x是素?cái)?shù)返回值為1,否則返回0
代碼:
int prime(int x){
int i;
for(i = 2; i < x; i++){if(x % i == 0){return 0;}
}return 1;
}
7、倆倆比較數(shù)組的值,將最大的一個(gè)存儲(chǔ)到數(shù)組的最后一個(gè)位置
代碼:
int arr[8] = {7,1,2,3,4,5,6,0};
void Max(){int g_r;for(int i = 0; i < 8-1; i++){if(arr[i] >= arr[i+1]){g_r = arr[i];arr[i] = arr[i+1];arr[i+1] = g_r;}}
}
8、編寫程序?qū)崿F(xiàn)一個(gè)冒泡排序的算法
代碼:
int n[8] = {7, 6, 5, 4, 3, 2, 1, 0};
void fun(){int i, j, temp;int len = 8;for (i = 0; i <= len - 2 ; i++){for (j = 0; j <= len - 1 - i; j++){if (n[j] > n[j + 1]){temp = n[j];n[j] = n[j + 1];n[j + 1] = temp;}}}
}
9、判斷數(shù)組是否是對稱的,如果是返回1,不是返回0
代碼:
int arr[10] = {0};
int fun(){int i, temp;int len = 10;for (i = 0; i < len/2 ; i++){if(arr[i] == arr[len-1-i]){continue;}else{return 0;}}return 1;
}