测试程序

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













































简单的main方法调用一个加减法函数背后的细节的更多相关文章

  1. [Inside HotSpot] hotspot的启动流程与main方法调用

    hotspot的启动流程与main方法调用 虚拟机的使命就是执行public static void main(String[])方法,从虚拟机创建到main方法执行会经过一系列流程.这篇文章详细讨论 ...

  2. 【M12】了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异

    1.方法参数的声明语法和catch语句的语法是一样的,你可能会认为主调方法调用一个方法,并向其传递参数,与抛出一个异常传递到catch语句是一样的,是的,有相同之处,但也有更大的不同. 2.主调方法调 ...

  3. 从一个简单的main方法执行谈谈JVM工作机制

    本来JVM的工作原理浅到可以泛泛而谈,但如果真的想把JVM工作机制弄清楚,实在是很难,涉及到的知识领域太多.所以,本文通过简单的mian方法执行,浅谈JVM工作原理,看看JVM里面都发生了什么. 先上 ...

  4. python+selenium之中类/函数/模块的简单介绍和方法调用

    # coding=utf-8 class ClassA (object): string1 = "这是一个字符串." def instancefunc(self): print ( ...

  5. 使用main方法调用http请求本地服务器的某个servlet报错问题

    java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:8081/test/myS ...

  6. java 主类的main方法调用其他方法

    方法1:A a=new test().new A(); 内部类对象通过外部类的实例对象调用其内部类构造方法产生,如下: public class test{ class A{ void fA(){ S ...

  7. C++调用一个成员函数的需求this指针的情况

    1.虚成员函数,因为需要this展望虚表指针的指针 2.在数据成员的操作部件的功能 #include "stdafx.h" #include <iostream> #i ...

  8. 用Main方法调用freemarker生成文件

    MyGenerator.java package com.comp.common; import java.io.BufferedWriter; import java.io.File; import ...

  9. java本地方法如何调用其他程序函数,方法详解

    JNI是Java Native Interface的缩写,中文为JAVA本地调用.从Java 1.1 开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许J ...

随机推荐

  1. PyQt5绘图

    QPainter 功能:QPainter实现在QWidget上画图功能 说明:绘图必须在paintEvent中完成,且要在bengin和end之间作图 接口: 方法 描述 begin 开始画图 end ...

  2. MySQL数据库---前言

    MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是最好的 RDBMS ...

  3. FaaS 给前端带来了什么?

    一.Serverless 与 FaaS Serverless 是一种云计算理念,即无服务器计算(Serverless Computing): Serverless suggests that the ...

  4. spring tx——@EnableTransactionManagement

    @EnableTransactionManagement import了TransactionManagementConfigurationSelector,而TransactionManagemen ...

  5. 关联吸纳的remote首次push报错rejected

    F:\abb-iot\DmsAPI\DmsAPI (master -> origin) λ git push --set-upstream github master To github.com ...

  6. js冒泡排序和数组去重

    1.冒泡排序 <script>//声明一个数组 var arr=[1,88,66,22,35,65,4,52];//自执行函数 (function maopao(){ for(var i= ...

  7. 《Head First 设计模式》:抽象工厂模式

    正文 一.定义 抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类. 要点: 抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产品的具体产品是什么.这样 ...

  8. 部署SpringBoot到阿里云

    目录 安装Mysql 1. 下载命令 2. 进行repo的安装: 3. 安装mysql 部署SpringBoot到阿里云服务器 1.IDEA下载插件 2.进入 Preference 配置一个 Acce ...

  9. ubuntu的docker安装

    安装docker 安装 介绍一下docker 的中央仓库们 Docker官方中央仓库: https://hub.docker.com/ 因为docker 网站在国外所以访问速度和你的运气有关还有网络. ...

  10. 环境篇:数据同步工具DataX

    环境篇:数据同步工具DataX 1 概述 https://github.com/alibaba/DataX DataX是什么? DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 ...