首页 > 其他 > 详细

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

时间:2019-10-13 22:17:50      阅读:203      评论:0      收藏:0      [点我收藏+]

测试程序

/*
 * 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方法不再调用其他方法了。

技术分享图片
技术分享图片

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

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

技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片

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

原文:https://www.cnblogs.com/simoncook/p/11668473.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!