/* * AddTest.c * * Created on: 2019年10月13日 * Author: appweb */ #include <stdio.h> int add(int a, int b) { int c = addAgain(a, b); return c; } int addAgain(int a, int b) { int c = a + b; return c; } int sub(int a, int b) { int c = a - b; return c; } int main() { int s = add(5, 3); int d = sub(5, 3); return 0; }
makefilehtml
PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) OBJS = AddTest.o # 若是在命令行直接執行make 須要export BUILD_MODE=debug 或者run ifeq ($(BUILD_MODE),debug) CFLAGS += -g else ifeq ($(BUILD_MODE),run) CFLAGS += -O2 else $(error Build mode $(BUILD_MODE) not supported by this Makefile) endif all: InvokeFunction # $@ 表示規則中的目標文件集。在模式規則中,若是有多個目標,那麼,"$@"就是匹配於目標中模式定義的集合。 # $^ 全部的依賴目標的集合。以空格分隔。若是在依賴目標中有多個重複的,那個這個變量會去除重複的依賴目標,只保留一份。 # $< 依賴目標中的第一個目標名字。若是依賴目標是以模式(即"%")定義的,那麼"$<"將是符合模式的一系列的文件集。注意,其是一個一個取出來的。 # $? 全部比目標新的依賴目標的集合。以空格分隔。 # 輸出變量可使用以下辦法 $(info $$OBJS is [${OBJS}]) $(info $$(CXX) is [$(CXX)]) $(info $$(PROJECT_ROOT) is [$(PROJECT_ROOT)]) AddTest: $(OBJS) $(CXX) -o $@ $^ %.o: $(PROJECT_ROOT)src/%.c $(CXX) -c $(CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -o $@ $< clean: rm -fr AddTest $(OBJS)
一如既往的使用CDT,寄存器監視(我須要觀察的幾個)、內存監視 、反編譯的彙編指令窗口弄在一塊兒,調試起來真是方便
打包好的工程web
開始調試shell
添加寄存器監視app
添加內存監視函數
啓用指令單步調試測試
rsp
是棧頂
,rbp
是棧底
,大小及棧分配的生長方向以下:優化
棧分配生長方向 <-------------------------------------+ rsp 棧頂 rbp 棧底 +------------------+------------------+ | | | | | | +------------------+------------------+ 內存低位地址 內存高位地址
如今rsp是0xfffffffd750,執行完下圖的ui
00000000000004195598: mov %rsp,%rbp 00000000000004195601: sub $0x10,%rsp
這兩條彙編指令後,rbp是0xfffffffd750,rsp是0xfffffffd740,這就是 函數棧幀空間分配this
在執行完callq與push指令以後,棧頂再往前的內存(就是緊靠着棧頂比棧頂還小的內存)會發生變化,看圖中內存監視器紅色部分,按有些書上說法此處是保存了rip和rbp,可是我沒能太理解,看數值不怎麼能對上spa
注意看 進入addAagin方法後,並非像某些書上說的會分配函數棧幀控空間,我猜想是編譯器作了優化吧,由於addAagin方法再也不調用其餘方法了。
看了R大的文章,這種函數應該是 葉函數,葉函數是不調用別的函數的函數。
00000000000004195547: mov %edi,-0x14(%rbp) 00000000000004195550: mov %esi,-0x18(%rbp)
看上圖,從edi和esi集羣器向 相對於rbp(棧底)偏移(負偏移)的內存傳數據,這個稱之爲壓棧
不過有些書上講的是 向 相對rsp(棧頂)偏移(正偏移)的內存傳數據,我理解成一個意思,不過是內存定位的方式不一樣罷了