堆栈

GDB调试汇编堆栈

半腔热情 提交于 2019-12-25 06:37:12
GDB调试汇编堆栈 准备工作 终端编译工具: 编译64位Linux版本32位的二进制文件,需要安装一个库,使用指令sudo apt-get install libc6-dev-i386 测试代码: test.c 分析过程 1.生成汇编代码:gcc -g gdbtest.c -o gdbtest -m32 2.调试:gdb test 3.设置断点,因为目的是分析而不是调试bug,所以我们将断点设置在main函数 4.开始gdb调试:r(un),如若想获取此时的汇编代码,可用指令:disassemble 5.此时可以用指令查看寄存器的值:i(nfo) r(egisters),显示的格式为3列: 第1列:寄存器名称 第2列:寄存器的地址 第3列:寄存器中存的值 6:结合display命令和寄存器或pc内部变量,做如下设置:display /i $pc,这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。下面展示每一步时%esp、%ebp和堆栈内容的变化: 过程(截图中的指令实际上是待执行指令) 初始 push $0x7 call 0x80483e8 call调用f(0x80483e8) push %ebp 执行f函数,f初始化帧指针,将上一个函数的基址入栈,将当前%esp作为新基址 mov %esp,%ebp 分配栈空间,为传参做准备 pushl 0x8(%ebp) 将

AVR汇编初探之一《AVR单片机的CPU内部结构》

别说谁变了你拦得住时间么 提交于 2019-12-24 10:57:39
学单片机那么久了,感觉想要深入,还得看汇编语言,至少得了解单片机内部结构。 下面就以ATmega16为例,介绍一下AVR单片机结构和汇编语言。 AVR单片机的CPU内核结构 如上两图,左图是虚线框内AVR CPU的内核结构,右图是AVR单片机内核结构的方框图,可以看出AVR单片机的数据总线(CPU字长)是8位的,也就说它是8位单片机。 AVR采用了Harvard结构,具有独立的数据和程序总线,CPU在执行一条指令的同时,就将PC中指定的下一条指令取出,构成了一级流水线运行方式,实现了一个时钟周期执行一条指令,数据吞吐量高达1MIPS/MHz。 AVR CPU内核由几个重要的部分组成,它们分别是: A.算数逻辑单元ALU(Arithmetic Logic Unit) AVR ALU与32个通用工作寄存器直接相连。寄存器与寄存器之间、寄存器与立即数之间的ALU运算只需要一个时钟周期。ALU操作分为3类:算术、逻辑和位操作,此外还提供了支持无/有符号数和分数乘法的乘法器,操作结果的状态将影响到状态寄存器SREG(Status Register)。 B.程序计数器PC、指令寄存器和指令译码器 程序计数器PC用来存放下一条需要执行指令在程序存储器(ROM)空间的地址(指向FlashROM空间),取出的指令存放在指令寄存器中,然后送入指令译码器中产生各种控制信号,控制CPU的运行(执行指令)。

计算机组成与结构复习整理(五)

霸气de小男生 提交于 2019-12-24 01:27:53
指令系统与中央处理机组织 指令系统 基本概念 指令格式 一般格式 按指令所包含的地址个数将指令划分 指令长度 寻址方式 指令类型 指令类型 堆栈和堆栈存取方式 中央处理机组织 CPU的三种实现方式 CPU中的主要寄存器 单总线数据通路 CPU四项基本功能 CPU时序控制方式 CPU控制流程 一条完整指令的执行 ①Add (R3),R1 ②无条件转移指令的控制序列 CPU性能设计 指令系统 基本概念 ①程序员用各种语言编写的程序最后要翻译(解释或编译)成以指令形式表示的机器语言以后,才能在计算机上运行。计算机的指令有微指令、机器指令和宏指令之分。 微指令是微程序级的命令,属于硬件;宏指令是由若干机器指令组成的,属于软件;机器指令介于二者之间,因而是硬件和软件的界面。 ②一台计算机能执行的机器指令的集合统称位该机的指令系统。 指令格式 一般格式 操作码 地址码 OP D 按指令所包含的地址个数将指令划分 a.三地址指令:(D1)OP(D2)→ D3 b.二地址指令:(D1)OP(D2)→D2 c.单地址指令:(D)OP (A)→ A(累加寄存器) d.零地址指令:空操作、停机 指令长度 选取原则: ①指令长度应为存储器基本字长的整数倍。 ②指令字长应尽量短。 寻址方式 ①立即寻址:| OP | 操作数地址 | ②直接寻址:| OP | @间接地址 | ③间接寻址:| OP | Rx |

Java学习之JVM中的堆和栈

Deadly 提交于 2019-12-23 18:23:37
 JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。    我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译原理中的活动纪录的概念是差不多的.    从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。   每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。 来源:

JVM调优之jstack找出最耗cpu的线程并定位代码

北战南征 提交于 2019-12-23 16:03:07
jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。 第一步先找出Java进程ID,服务器上的Java应用名称为mrf-center: root@ubuntu:/# ps -ef | grep mrf-center | grep -v grep root 21711 1 1 14:47 pts/3 00:02:10 java -jar mrf-center.jar 得到进程ID为21711,第二步找出该进程内最耗费CPU的线程,可以使用 1)ps -Lfp pid 2)ps -mp pid -o THREAD, tid, time 3)top -Hp pid 用第三个,输出如下: TIME列就是各个Java线程耗费的CPU时间,CPU时间最长的是线程ID为21742的线程,用 printf "%x\n" 21742 得到21742的十六进制值为54ee,下面会用到。 OK,下一步终于轮到jstack上场了,它用来输出进程21711的堆栈信息,然后根据线程ID的十六进制值grep,如下: root@ubuntu:/# jstack 21711 | grep 54ee

C#中struct与class的区别

我与影子孤独终老i 提交于 2019-12-23 03:12:18
一. 类与结构的差别   1.值类型与引用类型   结构是值类型:值类型在堆栈上分配地址,所有的基类型都是结构类型,例如:in t 对应System.int32 结构,string 对应 system.string 结构 ,通过使用结构可以创 建更多的值类型   类是引用类型:引用类型在堆上分配地址   堆栈的执行效率要比堆的执行效率高,可是堆栈的资源有限,不适合处理大的逻辑 复杂的对象。所以结构处理作为基类型对待的小对象,而类处理某个商业逻辑   因为结构是值类型所以结构之间的赋值可以创建新的结构,而类是引用类型,类之 间的赋值只是复制引用   注:   1.虽然结构与类的类型不一样,可是他们的基类型都是对象(object),c#中所有类 型的基类型都是object   2.虽然结构的初始化也使用了New 操作符可是结构对象依然分配在堆栈上而不是堆 上,如果不使用“新建”(new),那么在初始化所有字段之前,字段将保持未赋值状态, 且对象不可用   2.继承性   结构:不能从另外一个结构或者类继承,本身也不能被继承,虽然结构没有明确的 用sealed声明,可是结构是隐式的sealed .   类:完全可扩展的,除非显示的声明sealed 否则类可以继承其他类和接口,自身也 能被继承   注:虽然结构不能被继承 可是结构能够继承接口,方法和类继承接口一样 例如:结构实现接口  

GDB调试汇编堆栈过程分析

£可爱£侵袭症+ 提交于 2019-12-23 00:57:19
GDB 调试汇编堆栈 准备工作 · 终端编译工具: · 编译 64位 Linux版本 32位的二进制文件,需要安装一个库,使用指令 sudo apt-get install libc6-dev-i386 分析过程 · 1.生成汇编代码: gcc -g test.c -o test -m32 · 2.调试: gdb test · · 3.设置断点,因为目的是分析而不是调试 bug,所以我们将断点设置在 main函数 · · 4.开始 gdb调试: r(un),如若想获取此时的汇编代码,可用指令: disassemble · · 5.此时可以用指令查看寄存器的值: i(nfo) r(egisters),显示的格式为 3列: · · 第 1列:寄存器名称 · 第 2列:寄存器的地址 · 第 3列:寄存器中存的值 · 6:结合 display命令和寄存器或 pc内部变量,做如下设置: display /i $pc,这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。下面展示每一步时 %esp、 %ebp和堆栈内容的变化: · 过程(截图中的指令实际上是待执行指令) · 初始 · · push $0x1 · · · call 0x804840d call调用 f(0x804840d) · push %ebp 执行 f函数, f初始化帧指针,将上一个函数的基址入栈,将当前

程序员的真情告白

匆匆过客 提交于 2019-12-22 08:23:04
                           我能抽象出整个世界   但是我不能抽象出你   因为你在我心中是那么的具体   所以我的世界并不完整   我可以重载甚至覆盖这个世界里的任何一种方法   但是我却不能重载对你的思念   也许命中注定了 你在我的世界里永远的烙上了静态的属性   而我不慎调用了爱你这个方法   当我义无返顾的把自己作为参数传进这个方法时   我才发现爱上你是一个死循环   它不停的返回对你的思念压入我心里的堆栈   在这无尽的黑夜中   我的内存里已经再也装不下别人   我不停的向系统申请空间   但却捕获一个异常---我爱的人不爱我   为了解决这个异常   我愿意虚拟出最后一点内存   把所有我能实现的方法地址压入堆栈   并且在栈尾压入最后一个方法---将字符串"我爱你,你爱我吗?"传递给你   如果返回值为真--我将用尽一生去爱你   否则--我将释放掉所有系统资源 来源: https://www.cnblogs.com/azai/archive/2010/04/05/1704690.html

003_FREERTOS任务基础知识

别来无恙 提交于 2019-12-20 05:02:20
(一)任务状态 FreeRTOS 中的任务永远处于下面几个状态中的某一个: ● 运行态 当一个任务正在运行时,那么就说这个任务处于运行态,处于运行态的任务就是当前正在 使用处理器的任务。如果使用的是单核处理器的话那么不管在任何时刻永远都只有一个任务处 于运行态。 ● 就绪态 处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起),可以运行的任务, 但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行! ● 阻塞态 如果一个任务当前正在等待某个外部事件的话就说它处于阻塞态,比如说如果某个任务调 用了函数 vTaskDelay()的话就会进入阻塞态,直到延时周期完成。任务在等待队列、信号量、事 件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过 这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临! ● 挂起态 像阻塞态一样,任务进入挂起态以后也不能被调度器调用进入运行态,但是进入挂起态的 任务没有超时时间。任务进入和退出挂起态通过调用函数 vTaskSuspend()和 xTaskResume()。 (二)任务优先级 如果所使用的硬件平台支持类似计算前导零这样的指令(可以通过该指令选 择 下 一 个 要 运 行 的 任 务 , Cortex-M 处 理 器 是 支 持 该 指 令 的 ) , 并 且 宏

7-22 堆栈模拟队列 (25分)

北慕城南 提交于 2019-12-20 02:37:17
7-22 堆栈模拟队列 (25分) AC代码 # include <iostream> # include <cstdio> # include <stack> # include <algorithm> using namespace std ; stack < int > s1 , s2 ; int main ( ) { int m , n , num ; scanf ( "%d%d" , & m , & n ) ; if ( m > n ) swap ( m , n ) ; char ch ; getchar ( ) ; while ( scanf ( "%c" , & ch ) && ch != 'T' ) { if ( ch == ' ' ) continue ; if ( ch == 'A' ) { scanf ( "%d" , & num ) ; if ( s1 . size ( ) < m ) s1 . push ( num ) ; else if ( s1 . size ( ) == m ) { if ( s2 . empty ( ) ) { while ( ! s1 . empty ( ) ) { s2 . push ( s1 . top ( ) ) ; s1 . pop ( ) ; } s1 . push ( num ) ; } else printf (