测试程序

/*
* 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. tk.mybatis selectByPrimaryKey无法正确识别主键

    selectByPrimaryKey无法正确识别主键,查看日志,发现报如下错误: ==> Preparing: SELECT username,password,name,age,sex,bir ...

  2. 题解 洛谷 P5303 【[GXOI/GZOI2019]逼死强迫症】

    可以先去考虑没有\(1 \times 1\)的砖块的情况,对于最后一个位置只有两种情况,一个是竖着用一块砖铺设\(2 \times 1\),另一个为横着用两块砖铺设\(2 \times 2\). 设没 ...

  3. tomcat 认证爆破之custom iterator使用

    众所周知,BurpSuite是渗透测试最基本的工具,也可是神器,该神器有非常之多的模块:反正,每次翻看大佬们使用其的骚操作感到惊叹,这次我用其爆破模块的迭代器模式来练练手[不喜勿喷] 借助vulhub ...

  4. seaborn分布数据可视化:直方图|密度图|散点图

    系统自带的数据表格(存放在github上https://github.com/mwaskom/seaborn-data),使用时通过sns.load_dataset('表名称')即可,结果为一个Dat ...

  5. 00_01_使用Parallels Desktop创建WindosXP虚拟机

    打开paralles软件,选择文件->新建 继续 选择手动选择,之后勾选没有指定源也继续 选择要创建的操作系统(这里以XP为例,其他的windows系统安装基本都差不多) 根据需要选择,这里选择 ...

  6. PHP mkdir() 函数

    定义和用法 mkdir() 函数创建目录. 如果成功该函数返回 TRUE,如果失败则返回 FALSE. 语法 mkdir(path,mode,recursive,context) 参数 描述 path ...

  7. PHP exp() 函数

    实例 返回 'e' 的不同次方: <?phpecho(exp(0) . "<br>");echo(exp(1) . "<br>") ...

  8. PHP crc32() 函数

    实例 输出 crc32() 的结果:高佣联盟 www.cgewang.com <?php $str = crc32("Hello World!"); printf(" ...

  9. 4.19 ABC F path pass i 容斥 树形dp

    LINK:path pass i 原本想了一个点分治 yy了半天 发现重复的部分还是很难减掉 况且统计答案的时候有点ex. (点了别人的提交记录 发现dfs就过了 于是yy了一个容斥 发现可以直接减掉 ...

  10. SQLServer 把ID相同的多行数据合并到一起

    我们现在有以下GameArea表,以及与其关联的Proveince表: 我们现在需要把GameArea表中GameId相同的数据合并到一行显示,可以使用以下写法: SELECT GameID,STUF ...