• 简单的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;
    }
    

    makefile

    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,寄存器监视(我需要观察的几个)、内存监视 、反编译的汇编指令窗口弄在一起,调试起来真是方便
    打包好的工程

    先编译下然后开始调试并观察


    开始调试



    添加寄存器监视


    添加内存监视


    启用指令单步调试


    rsp栈顶rbp栈底,大小及栈分配的生长方向如下:

                         栈分配生长方向
         <-------------------------------------+
                          rsp 栈顶           rbp 栈底
         +------------------+------------------+
         |                  |                  |
         |                  |                  |
         +------------------+------------------+
    内存低位地址                                 内存高位地址
    

    现在rsp是0xfffffffd750,执行完下图的

    00000000000004195598:   mov     %rsp,%rbp
    00000000000004195601:   sub     $0x10,%rsp 
    

    这两条汇编指令后,rbp是0xfffffffd750,rsp是0xfffffffd740,这就是 函数栈帧空间分配





    在执行完callq与push指令之后,栈顶再往前的内存(就是紧靠着栈顶比栈顶还小的内存)会发生变化,看图中内存监视器红色部分,按有些书上说法此处是保存了rip和rbp,但是我没能太理解,看数值不怎么能对上

    注意看 进入addAagin方法后,并不是像某些书上说的会分配函数栈帧控空间,我猜测是编译器做了优化吧,因为addAagin方法不再调用其他方法了。
    看了R大的文章,这种函数应该是 叶函数,叶函数是不调用别的函数的函数。


    00000000000004195547:   mov     %edi,-0x14(%rbp)
    00000000000004195550:   mov     %esi,-0x18(%rbp)
    

    看上图,从edi和esi集群器向 相对于rbp(栈底)偏移(负偏移)的内存传数据,这个称之为压栈
    不过有些书上讲的是 向 相对rsp(栈顶)偏移(正偏移)的内存传数据,我理解成一个意思,不过是内存定位的方式不同罢了























  • 相关阅读:
    Key ssd_300_vgg/block3_box/L2Normalization/gamma not found in checkpoint的解决方案
    微调(Fine-tune)原理
    TensorFlow的数据读取机制
    卷积神经网络CNN识别MNIST数据集
    TensorFlow基本计算单元与基本操作
    一些小软件闪退的解决方案
    机器学习之SVM调参实例
    机器学习之支持向量机算法(二)
    机器学习之支持向量机算法(一)
    机器学习项目实战----新闻分类任务(二)
  • 原文地址:https://www.cnblogs.com/simoncook/p/11668473.html
Copyright © 2020-2023  润新知