首先,我們有如下輸出
hello,world!程序: - hello.c
[code] #include <stdio.h> #if 1 //argument count //argument value int main(int argc, char **argv) { printf("hello, world!\n"); return 5; } #endif
在Linux環境下,不以文件拓展名作為區分文件的標准。
編譯:
[code]root@aemonair:~/tmp# gcc hello.c -o hello運行:
[code]root@aemonair:~/tmp# ./hello hello, world!
[code]root@aemonair:~/tmp# gcc -E hello.c -o hello.i
[code]root@aemonair:~/tmp# vim hello.i
使用
vim或者任意編輯器打開
hello.i可以看到是將頭文件展開去掉注釋等操作的預處理之後的文件。
[code]root@aemonair:~/tmp# gcc -S hello.i -o hello.s打開hello.s可以看到,是輸出
hello,worl!的匯編代碼。
[code]root@aemonair:~/tmp# gcc -c hello.s -o hello.o
這時用file命令查看hello.o則發現:
[code]root@aemonair:~/tmp# file hello.o hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped此時
hello.o是一個二進制64位的可重定位的目標文件。
[code]root@aemonair:~/tmp# gcc hello.o -o hello生成可執行文件。
[code]root@aemonair:~/tmp# ls -l hello* -rwxr-xr-x 1 root root 6728 May 27 14:40 hello -rw-r--r-- 1 root root 148 May 27 13:25 hello.c -rw-r--r-- 1 root root 17187 May 27 13:26 hello.i -rw-r--r-- 1 root root 1504 May 27 13:30 hello.o -rw-r--r-- 1 root root 497 May 27 13:28 hello.s
file命令,
得以辨識該文件的類型。
[code]root@aemonair:~/tmp# file hello.c hello.c: C source, ASCII text # C語言ASCII碼源文件 root@aemonair:~/tmp# file hello.i hello.i: C source, ASCII text root@aemonair:~/tmp# file hello.s hello.s: assembler source, ASCII text # ASCII碼匯編文件 root@aemonair:~/tmp# file hello.o hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped # 二進制64位的可重定位的目標文件 root@aemonair:~/tmp# file hello hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=1420b36f9837a8d7ba2f4a9ec6b968d16c403d23, not stripped #可執行的二進制文件objdump
objdump命令是Linux下的反匯編目標文件或者可執行文件的命令
[code]root@aemonair:~/tmp# objdump -s -d hello.o hello.o: file format elf64-x86-64 Contents of section .text: 0000 554889e5 4883ec10 897dfc48 8975f0bf UH..H....}.H.u.. 0010 00000000 e8000000 00b80500 0000c9c3 ................ Contents of section .rodata: 0000 68656c6c 6f2c2077 6f726c64 2100 hello, world!. Contents of section .comment: 0000 00474343 3a202844 65626961 6e20352e .GCC: (Debian 5. 0010 332e312d 38292035 2e332e31 20323031 3.1-8) 5.3.1 201 0020 36303230 3500 60205. Contents of section .eh_frame: 0000 14000000 00000000 017a5200 01781001 .........zR..x.. 0010 1b0c0708 90010000 1c000000 1c000000 ................ 0020 00000000 20000000 00410e10 8602430d .... ....A....C. 0030 065b0c07 08000000 .[...... Disassembly of section .text: 0000000000000000 <main>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 83 ec 10 sub $0x10,%rsp 8: 89 7d fc mov %edi,-0x4(%rbp) b: 48 89 75 f0 mov %rsi,-0x10(%rbp) f: bf 00 00 00 00 mov $0x0,%edi 14: e8 00 00 00 00 callq 19 <main+0x19> 19: b8 05 00 00 00 mov $0x5,%eax 1e: c9 leaveq 1f: c3 retq-s 除了顯示test的全部Header信息,還顯示他們對應的十六進制文件代碼
-d 反匯編test中的需要執行指令的那些section
readelf命令
readelf用來顯示ELF格式目標文件的信息.可通過參數選項來控制顯示哪些特定信息。
[code]root@aemonair:~/tmp# readelf -s -d hello.o Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.c 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 5: 0000000000000000 0 SECTION LOCAL DEFAULT 5 6: 0000000000000000 0 SECTION LOCAL DEFAULT 7 7: 0000000000000000 0 SECTION LOCAL DEFAULT 8 8: 0000000000000000 0 SECTION LOCAL DEFAULT 6 9: 0000000000000000 32 FUNC GLOBAL DEFAULT 1 main 10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
-若要在
Bash中獲得函數運行的返回值,則在終端中輸入以下代碼並回車。
[code]echo $?
[code]root@aemonair:~/tmp# echo $? 5一般的正確返回則返回0;這裡的5是我們為了查看效果。
若我們再執行一次
echo $?則會是多少呢?
[code] root@aemonair:~/tmp# echo $? 0
因為我們這時的返回值是成功執行了
echo的成功返回值,故為0。main函數參數:
int argc:參數的個數
char **argv: 參數的值 //也可寫成
char *argv[];
[code]/*argtest.c*/ #include <stdio.h> //argument count //argument value int main(int argc, char **argv) { int i = 0 ; printf("argc: %d\n",argc); for(i = 0; i < argc ;++i) { printf("argv[%d]:%s\n",i,argv[i]); } return 0; }編譯源文件為可執行文件:
[code]root@aemonair:~/tmp# gcc argtest.c -o argtest
./argtest.c 1 2 c def $運行得到:
[code]root@aemonair:~/tmp# ./argtest 1 2 c def $ argc: 6 argv[0]:./argtest argv[1]:1 argv[2]:2 argv[3]:c argv[4]:def argv[5]:$可見,argc是命令行傳入的參數個數,argv是一個二位指針,可以通過[ ]將其值
%s打印出來。
而且,argv[0]即是程序名本身。
條件編譯:
-此時,codes2的內容將不會運行。
[code]#if 1 //codes #else //cods 2 #endif可用來作為注釋或程序運行時的條件決策。