乙個十幾行簡單的C程式引發的思考

2022-08-02 11:33:10 字數 1852 閱讀 4203

今天碰到乙個很好玩的程式,我糾結了很久才弄明白。。。

下面解釋都是在debug模式下的:

在vc6.0下輸出的結果是

這下我就奇怪了,*p為什麼是e9呢??毫無根據可言額.....(沒學過彙編的人就是傻額

)我就開始除錯了,*p是233 = 0xe9

疑問1.為什麼*p的值是e9呢?

疑問2.fun的值怎麼是0x00401060呢?列印出來不是0x401005嗎?

這是為什麼呢??p的值不就是該函式的入口位址嗎??函式名就是函式的入口位址啊?為什麼就對了呢??

我繼續除錯,跑到裡頭去看看了····

首先可以知道一點就是,p = (byte *)fun; 和 printf("fun = %x\n",fun);是通過乙個偏移獲取的乙個位址,目前不知道這個位址是不是真正的函式入口位址。

這下可就差不多可以解釋了,這才是真正的函式入口位址啊!!

那前面那個 0x00401005是什麼呢???

我現在可以推斷的就是編譯器通過0x00401005來找到函式真正的函式入口位址(0x00401060) 。也就是說p =  00401005,這裡存在乙個跳轉指令(e9)跳到了真正的函式入口位址。

再引入下函式輸入表(不知道是不是這麼叫的

)的一些知識,程式一跑起來,會有乙個函式的輸入表,這裡記錄了部分呼叫函式的位址。看看那麼多的dll是怎樣運作的呢?不需要把函式**都嵌入到程式裡面,到了執行的時候直接去找到對應的函式入口位址就行了,那麼函式入口位址怎麼找呢?就是通過函式輸入表(專業的好像叫符號列表,也叫匯出段)。在debug模式下面訪問乙個函式的時候往往都是先通過乙個相對位址跳轉找到函式輸入表,然後找到函式輸入表指定條目-------這裡面就是函式入口位址,再通過跳轉到真正的函式入口位址,執行函式。

上面的兩個疑問就解決了

之後我用od除錯了下debug模式,下面是部分截圖:

這裡是相對偏移偏移位址,也就是p = (byte *)fun;這句**,從這裡可以看出debug模式下確實是通過相對偏移來找到輸入表中函式的位址。並且p = (byte *)fun;和printf("fun = %x\n",fun);都是通過下面這種形式----即通過相對位址找到函式輸入表,然後訪問到真正函式來實現的。

這裡是函式呼叫處,也就是執行fun();這句**的地方,指令就是e9 後面的56000000是雙位元組的偏移量,再來看 p = 0x00401005,*p就是第乙個位元組(byte型別),也就是jmp指令(e9)。這調指令執行後就到了fun()過程。

這裡是fun函式的入口點,位址是0x00401060,在反彙編裡面叫做過程····

剛剛在請教醒哥的時候,聽了他講了很多,還是只是了解了一小部分,全都是似有似無的概念,不過醒哥確實厲害,講了些基本的理念之後,提醒我叫我自己去除錯,並且告訴了我debug模式下和release模式下是不一樣的。回到寢室我重新調了下,自己好好分析了才發現原來真是很不一樣,不過這時候才真正理解了醒哥說的那些。。。

首先程式的輸出就不一樣了

下面是release模式下的od除錯結果:

上面的反彙編我都做了些注釋,可能有不對,因為自己不是很會,所以···(菜鳥只能這樣,勤能補拙)。這裡要注意的一點是這裡**中的0x00401060可不是上面那個fun()

函式的位址額,這裡應該只是巧合吧····(不是很懂,有點困了)。。。

從上面可以看出了release模式下和debug下的很大區別。在release模式下就沒有了函式輸入表這個概念,訪問函式的時候直接到了函式的真正的記憶體中的位址(不是實體地址(*^__^*) ),p = (byte *)fun;和printf("fun = %x\n",fun);都是採用的都是真正位址,這樣就比上面debug模式少了一次訪問,這個更加高效,這樣就是為什麼成型產品是乙個debug模式的乙個原因吧。

額····有點累了,睡覺了···(*^__^*) 

幾行彙編幾行C 實現乙個最簡單的核心

1 現有的作業系統都是用什麼語言開發出來的?2 grub是什麼?3 grub 能獲得呢?4 我們要實現乙個hello os,那hello os的引導流程是怎樣的?5 上圖中的bios是什麼?6 為什麼寫作業系統一上來不能直接用c寫?7 基本環境的彙編 是怎樣的?8 能解釋一下上面 的含義嗎?9 上面...

乙個簡單的verlig程式 乙個簡單C程式的介紹

我們前面學了c語言的一些理論知識,今天通過乙個簡單的程式先來看一看c語言程式是什麼樣子。然後再對程式中的 進行介紹。這個語句的功能是進行有關的預處理操作。include稱為檔案包含命令,後面尖括號的內容稱為標頭檔案或首檔案。此處指包含stdio.h系統標頭檔案,在下面主函式中使用的printf 函式...

乙個小程式引發的思考

既然是乙個小程式引發的思考,那麼我們就先看看這個小程式,看看他有何神奇之處 i s.val,i mymethod s,i console.writeline s.val i s.val,i console.read static void mymethod myclass f1,int f2 cla...