简单的main方法调用一个加减法函数背后的细节

测试程序

/*
 * 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(栈顶)偏移(正偏移)的内存传数据,我理解成一个意思,不过是内存定位的方式不一样罢了























相关文章
相关标签/搜索