汇编指令

Windows中进程的内存结构

落爺英雄遲暮 提交于 2019-11-26 17:39:09
基础知识: 堆栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表。允许插入或删除操作的一端称为栈顶,另一端称为栈底,对堆栈的插入和删除操作被称为入栈和出栈。有一组CPU指令可以实现对进程的内存实现堆栈访问。其中,POP指令实现出栈操作,PUSH指令实现入栈操作。CPU的ESP寄存器存放当前线程的栈顶指针,EBP寄存器中保存当前线程的栈底指针。CPU的EIP寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。 接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论。下文中的C语言代码如没有特别声明,默认都使用VC编译的release版。 首先,来了解一下 C 语言的变量是如何在内存分部的。C 语言有全局变量(Global)、本地变量(Local),静态变量(Static)、寄存器变量(Register)。每种变量都有不同的分配方式。先来看下面这段代码: #include <stdio.h> int g1=0, g2=0, g3=0; int main() { static int s1=0, s2=0, s3=0; int v1=0, v2=0, v3=0; //打印出各个变量的内存地址

ARM 常用汇编指令

爷,独闯天下 提交于 2019-11-26 13:21:15
ARM 汇编程序的框架结构 .section .data < 初始化的数据 > .section.bss < 未初始化的数据 > .section .text .global _start _start: < 汇编代码 > 注意: 一般是将上面结构进行简化 .text .global _start _start: < 汇编代码 > 具体参见ARM嵌入式系统基础教程 周立功那本红宝书 来源: https://www.cnblogs.com/idyllcheung/p/11321988.html

计算机组成原理题库(唐朔飞)

醉酒当歌 提交于 2019-11-26 12:27:42
计算机组成原理题库 ~~02|01|1|2|A0400047_010_1|871 ^^通常划分计算机发展时代是以( )为标准的。 A、所用电子器件 B、运算速度 C、计算机结构 D、所用语言 ^^A ~~02|01|1|2|A0400047_010_2|872 ^^能够被计算机硬件直接识别的语言是( )。 A、符号语言 B、机器语言 C、汇编语言 D、机器语言和汇编语言 ^^B ~~02|01|1|2|A0400047_010_3|873 ^^计算机能直接执行的程序是( )。 A、命令文件 B、汇编程序 C、机器语言程序 D、源程序 ^^C ~~02|01|1|2|A0400047_010_4|874 ^^计算机内的信息都是以( )形式表示的。 A、BCD码 B、二进制码 C、字母码 D、符号码 ^^B ~~02|01|1|2|A0400047_010_5|875 ^^至今为止,计算机中的所有信息仍以二进制方式表示,其理由是( )。 A、节省物理器件 B、运算速度快 C、物理器件容易实现 D、信息处理方便 ^^C ~~02|01|1|2|A0400047_010_6|876 ^^电子计算机技术在半个世纪中虽有很大进步,但至今其运行仍遵循着一位科学家提出的基本原理。他就是( )。 A、牛顿 B、爱因斯坦 C、爱迪生 D、冯·诺依曼 ^^D ~~02|01|1|2|A0400047

浅谈汇编

爷,独闯天下 提交于 2019-11-26 11:59:48
创建编写汇编文件: 首先创建一个空文件 命名方式以.s结尾 第一行需要声明一个代码段 .text 第二行声明一个global + 方法名 .global test 指令: 汇编代码注释在行前加上 ; ret:返回 mov指令:目的寄存器,源操作数 举例:mov x0, #0x8 将8赋值给x0 add指令:将两个寄存器相加 sub指令:将两个寄存器相减 cmp指令:比较指令 操作数1 操作数2:cmp x0, x1 用x0减去x1,并将结果放到cpsr(程序状态寄存器)寄存器里 b 指令:跳转指令,相当于jump b 目标地址 bl指令:带返回的跳转指令,与b指令的区别是使用bl指令,ret指令才会生效 内存操作: 1、load,从内存中装载数据 ldr指令:从内存中读取数据 ldr x0, [x1] ldur指令: ,一般如果数据为负数,会用ldur ldp指令:从内存中读取数据,放到一对寄存器中 ldp w0, w1, [x2, #0x10] 2、store,往内存中存储数据 str指令:往内存中写入数据 str w0, [x1],将w0的数据写入到x1中 stur指令:参考ldur指令 stp指令:参考ldp指令 wzr指令:零寄存器 xzr指令:零寄存器 程序计数器: pc(Program Counter) 记录CPU当前指令是哪一条指令

汇编学习笔记二

守給你的承諾、 提交于 2019-11-26 10:25:54
指令的执行 指令的长度是可以是多个字节 cpu从cs:ip所指向的内存单元中读取指令,存放到指令缓存器中 ip=ip+所读指令的长度,从而指向下一条指令 执行指令缓存器的内容,回到下一个步骤 这个顺序是很重要的,为什么要使用2和3的顺序哪,这是因为当我们调用一个函数时使用这种方式很好用 我们可以得出结论,数据和指令是没有差别的,当使用读取cs:ip指向的地址,cpu便将其当成指令执行 debug使用 -u 表示显示出当前位置的代码 -u 段地址:偏移地址 显示指定位置的代码 -d 表示显示当前位置的数据 -u 段地址:偏移地址 显示指定位置的数据 -a 表示直接在当前位置写入指令 -a 段地址:偏移地址 表示在指定的位置写入指令 -r 表示显示当前寄存器的内容 -r 寄存器 然后显示指定寄存器的内容在下一行写入 :2000表示将这个寄存器的内容设置成2000 -e 段地址:偏移地址 可以改写内存的内容 jmp指令 jmp是转移指令是jump的简写,表示跳跃的意思。 指令的格式: jmp 2000:0表示将cs设置成2000,将ip设置成0,因此这个指令能够改变指令执行的位置 cs和ip寄存器是不能够使用mov来进行更改的,只能使用jmp来改变 比如 mov cs,1000是错误的 还可以使用 jmp 寄存器 的方式来更改ip的内容 call 函数名 表示函数的开始

程序的机器级表示(一)

[亡魂溺海] 提交于 2019-11-26 06:07:55
程序编码 假设一个C程序,有两个文件p1.c和p2.c。我们用Unix命令行编译这些代码: linux> gcc -Og-o p p1.c p2.c    命令gcc就是GCC编译器,这是Linux默认的编译器。编译选项-Og告诉编译器使用会生成符合原始C代码整体结构的机器代码的优化等级,使用较高级别的优化产生的代码会严重变形,以至于产生的机器代码和初始源代码之间的关系难以理解。 实际上,gcc命令调用了一整套程序,将源代码转换为可执行代码。首先,C预处理器扩展源代码,插入所有用#include命令指定的文件,并扩展所有用#define声明指定的宏。其次,编译器产生两个源文件的汇编代码,名字分别为p1.s和p2.s。接下来,汇编器会将汇编代码转换为二进制目标代码文件p1.o和p2.o。目标代码是机器代码的一种形式,它包含所有指令的二进制表示,但是还没填入全局值的地址。最后,链接器将两个目标代码文件与实现函数(如printf)的代码合并,并产生最终的可执行文件p(由-o p指定的)。 机器级代码 对机器级编程来说,其中两种抽象尤为重要。第一种是由指令集体系结构或指令集架构(Instruction Set Architecture,ISA)来定义机器级程序的格式和行为,它定义了处理器状态、指令的格式,以及每条指令对状态的影响。大多数ISA,包括x86-64

深入iOS系统底层之指令集介绍

蹲街弑〆低调 提交于 2019-11-26 03:32:53
不以规矩.不能成方圆。--《孟子·离娄上》 说到指令集以及CPU架构体系,大家就会想到计算机专业课程里面的计算机体系结构的方面的内容。既然课程中已经有了的内容我就不想那么枯燥的去复述一遍,而是先看一个类的定义: //定义寄存器编号 typedef enum : int { Reg0, Reg1, Reg2, Reg3 } RegNum; //定义系统调用编号 typedef enum : int { Int3 //设备输出,将寄存器Reg0中的内容输出到屏幕 } Interrupt; //定义指令索引 typedef int Instruct; /** 虚拟CPU类,模拟CPU所提供的指令。 虚拟CPU由4个寄存器和运算部件组成。四个寄存器的编号分别定义在RegNum中;运算部件提供了赋值、加减、比较、跳转9个指令。 */ @interface VCPU : NSObject //将一个常量值赋值给编号为reg的寄存器中。 -(void)moveFromConst:(int)val toReg:(RegNum)reg; //将编号为reg1的寄存器中的值赋值给编号为reg2的寄存器中。 -(void)moveFromReg:(RegNum)reg1 toReg:(RegNum)reg2; //将编号为reg的寄存器中的值赋值给地址为addr的内存中。 -(void

深入iOS系统底层之CPU寄存器介绍

南笙酒味 提交于 2019-11-26 02:28:42
一弹指六十刹那,一刹那九百生灭。 --《仁王经》 组件 计算机是一种数据处理设备,它由CPU和内存以及外部设备组成。CPU负责数据处理,内存负责存储,外部设备负责数据的输入和输出,它们之间通过总线连接在一起。CPU内部主要由控制器、运算器和寄存器组成。控制器负责指令的读取和调度,运算器负责指令的运算执行,寄存器负责数据的存储,它们之间通过CPU内的总线连接在一起。每个外部设备(例如:显示器、硬盘、键盘、鼠标、网卡等等)则是由外设控制器、I/O端口、和输入输出硬件组成。外设控制器负责设备的控制和操作,I/O端口负责数据的临时存储,输入输出硬件则负责具体的输入输出,它们间也通过外部设备内的总线连接在一起。 上面的计算机系统结构图中我们可以看出 硬件系统的这种组件化的设计思路总是贯彻到各个环节。在这套设计思想(冯.诺依曼体系架构)里面,总是有一部分负责控制、一部分负责执行、一部分则负责存储,它之间进行交互以及接口通信则总是通过总线来完成。这种设计思路一样的可以应用在我们的软件设计体系里面:组件和组件之间通信通过事件的方式来进行解耦处理,而一个组件内部同样也需要明确好各个部分的职责(一部分负责调度控制、一部分负责执行实现、一部分负责数据存储)。 缓存 一个完整的CPU系统里面有控制部件、运算部件还有寄存器部件。其中寄存器部件的作用就是进行数据的临时存储。既然有内存作为数据存储的场所

C++的栈空间和堆空间

久未见 提交于 2019-11-25 20:08:49
https://www.csdn.net/gather_2b/NtDaIg5sMTktYmxvZwO0O0OO0O0O.html 一直都把堆栈放一起,所以很多人会误以为他们的组合是一个词语,就像“衣服”一样简单,其实不然,今天在下就将最近学习总结的一些与大家分享。 一个由C/C++编译的程序占用的内存分为以下几个部分: 1、栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构的栈。 2、堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是类似于数据结构的链表。 3、全局区(static):也叫静态数据内存空间,存储全局变量和静态变量,全局变量和静态变量的存储是放一块的,初始化的全局变量和静态变量放一块区域,没有初始化的在相邻的另一块区域,程序结束后由系统释放。 4、文字常量区:常量字符串就是放在这里,程序结束后由系统释放。 5、程序代码区:存放函数体的二进制代码。 堆和栈的区别: 一、由以上综述就可以得知,他们程序的内存分配方式不同。 二、申请和响应不同: 1、申请方式:stack由系统自动分配,heap需要程序员自己申请,C中用函数malloc分配空间,用free释放,C++用new分配,用delete释放。 2、申请后系统的响应: 栈