手写了一个错误,打算用gdb练练手
![dbc52850c97bcf1e3235492750e5d50d.png](https://img-blog.csdnimg.cn/img_convert/dbc52850c97bcf1e3235492750e5d50d.png)
显然,第一个函数是错误的写法,返回临时变量的引用
下面编译 运行一下 可以看出编译给出了警告 运行结果可以看出 执行到第二次调用时发生错误
![fc020302ca54206d6117bfd417b8e11b.png](https://img-blog.csdnimg.cn/img_convert/fc020302ca54206d6117bfd417b8e11b.png)
接下来开始调试
gdb a.out
run
![d8eb154d0228b335eb3597ae1be041cc.png](https://img-blog.csdnimg.cn/img_convert/d8eb154d0228b335eb3597ae1be041cc.png)
然后
backtrace
frame n
![d7af049aaa7f3a71140fd39b6a7a6bf2.png](https://img-blog.csdnimg.cn/img_convert/d7af049aaa7f3a71140fd39b6a7a6bf2.png)
成功找到 是 name_referce = GetNameReferce();出了问题
![bba8d592505ca00036641361ed51bf58.png](https://img-blog.csdnimg.cn/img_convert/bba8d592505ca00036641361ed51bf58.png)
请接着下面的一篇文章开始读,是以前遇到的然后记录的刚好接这个,相信你一定会有所收获
它说明了 什么是core 文件 为什么会有提示Segmentation fault (core dumped) 。 而这些正是这个代码的错误
知乎用户www.zhihu.com以下个人笔记,阅读容易引起不适
反汇编
g++ -S main.cpp //S要大写 //生成.s文件 //打开查看即可
源代码main.cpp
int age_;
void SetAge(int age){
age_ = age;
}
int main(){
SetAge(520);
return 0;
}
g++ -g main.cpp
gdb a.out
//进入gdb后,输入layout asm切换到反汇编视图,同时在main函数处下断点:
layout asm
b main
run //启动程序
si //来逐条指令执行并观察寄存器变化情况
![7b1f867a50de9a9e4283fd07cc47c504.png](https://img-blog.csdnimg.cn/img_convert/7b1f867a50de9a9e4283fd07cc47c504.png)
红框里的内容很容易理解
![79b6b4a5b4fbf87108a455ad999c24f1.png](https://img-blog.csdnimg.cn/img_convert/79b6b4a5b4fbf87108a455ad999c24f1.png)
想要在64位系统(x86_64系统)编译32位程序 或者说生成32位汇编代码
得加个参数 -m32 例如
gcc -m32 -S -o main.s main.c
另外说明下在ubuntu上如果要用 -m32 参数就要安装如下的库:
sudo apt-get install build-essential module-assistant
sudo apt-get install gcc-multilib g++-multilib
参考:https://www.cnblogs.com/exiahan/p/4310010.html
GCC帮我们生成的汇编代码,这里需要说明下AT&T格式和intel格式,这两种格式GCC是都可以生成的,如果要生成intel格式的汇编代码,只需要加上 -masm=intel选项即可
但是Linux下默认是使用AT&T格式来书写汇编代码,Linux Kernel代码中也是AT&T格式,我们要慢慢习惯使用AT&T格式书写汇编代码。
这里最需要注意的AT&T和intel汇编格式不同点是:
AT&T格式的汇编指令是“源操作数在前,目的操作数在后”,而intel格式是反过来的,即如下:
AT&T格式:movl %eax, %edx
Intel格式:mov edx, eax
表示同一个意思,即把eax寄存器的内容放入edx寄存器。
这里需要注意的是AT&T格式的movl里的l表示指令的操作数都是32位
类似的还是有movb,movw,movq,分别表示8位,16位和64位的操作数。
原文:https://blog.csdn.net/qq_42832800/article/details/89238402#commentBox
栈:一种在计算机内部模拟“先进后出”的数据结构。
栈指针寄存器:ESP寄存器,指向栈的顶部。
帧指针寄存器:EBP寄存器,指向栈的底部。
栈帧:每条语句,或每个过程都有自己的栈区。所以栈帧在栈指针和帧指针之间。
原文: 链接:https://zhuanlan.zhihu.com/p/77663680
从技术上说,栈就是CPU寄存器里的某个指针所指向的一片内存区域。这里所说的“某个指针”通常位于x86/x64平台的ESP寄存器
/RSP寄存器
,以及ARM平台的SP寄存器
。
操作栈的最常见的指令时PUSH
(压栈)和POP
(弹栈)。PUSH
指令会对ESP
/RSP
/SP
寄存器的值进行减法运算,使之减去4(32位)或8(64位),然后将操作数写到上述寄存器里的指针所指向的内存中。
函数入口参数的压栈顺序为(C/C++):从右到左。
例如: void function(int x,int y,int z){ // 先Z入栈,再y,再z
}
栈的存储区域为:从高地址向低地址存放,高地址在栈底,低地址趋向栈顶。
z的地址 高于 y的地址 高于 x的地址
与栈相关的汇编指令:
PUSH POP MOV 分别用于元素的入栈、出栈、入栈操作。
函数被调用过程中的汇编指令:
CALL 调用函数指令,在跳转到被调用的函数前,先把返回地址压栈。
RET 函数结果返回指令,在返回调用过程之前从栈中取回返回地址。
总结:调用指令CALL和返回指令RET。都属于无条件转移指令,会改变程序的执行过程。
C++内存分为5个区域:
堆 heap :
由new分配的内存块,其释放编译器不去管,由我们程序自己控制(一个new对应一个delete)。如果程序员没有释放掉,在程序结束时OS会自动回收。涉及的问题:“缓冲区溢出”、“内存泄露”
栈 stack :
是那些编译器在需要时分配,在不需要时自动清除的存储区。存放局部变量、函数参数。
。。。
学的全都忘了 艹
1. 寄存器是中央处理器内的组成部份。它们可用来暂存指令、数据和地址。2. Cache :即高速缓冲存储器,是位于CPU与主内存间的一种容量较小但速度很高的存储器。
总结:大致来说数据是通过内存-Cache-寄存器,Cache缓存则是为了弥补CPU与内存之间运算速度的差异而设置的的部件。
参考:同上
g++ -m32 -S -o a.s main.cpp
执行完上述命令后,当前目录下就会有一个a.s的文件,使用vim打开,不需要的链接信息[以"."开头的行]都删除了,得到如下汇编代码:(部分)
_Z6SetAgei:
pushl %ebp
movl %esp, %ebp
call __x86.get_pc_thunk.ax
addl $_GLOBAL_OFFSET_TABLE_, %eax
movl 8(%ebp), %edx
movl %edx, age_@GOTOFF(%eax)
popl %ebp
固定套路:是用来保护堆栈的,常常出现在函数的开头,后面也常常会跟着很多push来保护寄存器;
push ebp
mov ebp, esp
调用一个函数时,先将堆栈原先的基址(EBP)入栈,以保存之前任务的信息。
然后将栈顶指针的值赋给EBP,将之前的栈顶作为新的基址(栈底),然后再这个基址上开辟相应的空间用作被调用函数的堆栈。
函数返回后,从EBP中可取出之前的ESP值,使栈顶恢复函数调用前的位置;再从恢复后的栈顶可弹出之前的EBP值,因为这个值在函数调用前一步被压入堆栈。这样,EBP和ESP就都恢复了调用前的位置,堆栈恢复函数调用前的状态。
为什么突然记这些?刚在看汇编代码发现竟然cpu架构不同,和多少位不同(32 /64)产生的汇编代码不同,看来组成原理是白学了。。。。
给自己补补电脑常识,giao 连这都不知道
dpkg --print-architecture
输出amd64
dpkg --print-foreign-architectures
输出i386
什么是amd64?
intel 和 amd是两家不同的公司 生产自己的cpu
Windows 7,有32位(x86)和64位(x64)两种版本,什么是x86?
X86就是一般用的32位的系统,X64就是64位的系统
X64本质上也是X86的一个版本,确切来说,应该叫x86_64,可以简单理解成X86的下一代版本。由于X86已经淘汰,因此X64早已经是主流了
目前的电脑CPU都是基于64位设计,也就是X64,只有很早以前的一些古董CPU才是X86(32位)版本,因此一般我们下载系统版本,是选择X64,不建议X86,除非是CPU为X86架构,很老的电脑
原问题:https://zhidao.baidu.com/question/160810416.html
什么是64位处理器?
64位处理器是采用64位处理技术的CPU,相对32位而言,64位指的是CPU GPRs(General-Purpose Registers,通用寄存器)的数据宽度为64位,
64位指令集 就是处理64位数据的指令,处理器一次运行64bit数据。
Intel和AMD两大处理器厂商都发布了多个系列多种规格的64位处理器;
AMD64的位技术是在原始32位X86指令集的基础上加入了X86-64扩展64位X86指令集,使这款芯片在硬件上兼容原来的32位X86软件,并同时支持X86-64的扩展64位计算,使得这款芯片成为真正的64位X86芯片。这是一个真正的64位的标准,X86-64具有64位的寻址能力。
Intel 8086是什么?
Intel 8086是一款微处理器,包括了具有300个操作的指令集
x86架构是什么?
x86泛指 一系列基于Intel 8086且向后兼容的中央处理器 指令集 架构
x86-64架构是什么?
x86-64( x64)是 x86架构 的64位拓展,兼容16位 及 32位的x86架构。
x64于1999年由AMD设计,AMD首次公开64位集以扩展给x86,称为“AMD64”。其后也为英特尔所采用
所以第一个问题 AMD64是什么?
我想再做的各位都已经知道了答案
首先可以简化一个概念bai,i386=Intel 80386。其du实i386通常被用来作为对Intel(英特zhi尔)32位微处理器的统称。
AMD64,又称“x86-64”或“x64”,是一种64位元的电脑处理器架构。它是建基于现有32位元的x86架构,由AMD公司所开发