指令寄存器

x86 汇编的基础知识

北慕城南 提交于 2020-01-31 05:33:12
x86 汇编器编程 基于x86 实现编译器首先得了解x86 平台的指令调度, 以下是一些我在实现编译器过程中用到的基础知识! 大部分内容参考了 青木的自制编译器, 基于GNU汇编器 c语言使用gcc 编译, 而gcc 编译器将c代码转化为汇编之后, 也是用的GNU as 的汇编器将汇编语言 .s 转化为.o,然后再连接, 因此如果自制编译器, 也是做到汇编这一步, 所以又得学x86 汇编器的使用方法! gcc 用的 GNU, 那我就直接使用gcc! 基本使用 编译: as hello.s //默认生成 a.out 也可以指定名字: as - o hello . o hello . s 生成目标文件后还要连接才可以执行。 gcc hello.o -o hello 最后就是 . / hello 语法 指令 指令包括 助记符 和 操作数 组成,比如 movl %esp, %ebp , movl 助记符, 后面两个为操作数, 操作数可以为多个!逗号分隔。 这个是由cpu直接执行的指令 汇编伪操作 以点 “.” 开头的, 末尾没有冒号 “:” 的 行 都是汇编伪操作行。 由汇编器执行,记录元数据和设定指令的属性。 汇编的首行缩进是没有影响的 标签 以冒号“:” 结尾的 行 都是标签行 冒号是语法, 标签名为冒号前面的值。 一般命名加上 . ,避免和代码里面的名字重复。 助记符后缀 后缀 大小

《操作系统真象还原》读书笔记 第3章

扶醉桌前 提交于 2020-01-30 03:20:16
0x1 地址、section、vstart 0x1.1 什么是地址 地址只是数字,描述各种符号在源程序中的位置,它是源代码文件中各符号偏移文件开头的距离。由于指令和变量所占内存大小不同,故他们相对于文件开头偏移量参差不齐。源码文件中各符号地址是由编译器来规划的。 编译器的工作就是给各符号编址。编译器根据所在硬件平台特性,将源代码中的每一个符号(指令和数据)都按照硬件平台的特性分配空间,在不考虑对齐情况下,这些符号都在空间上彼此相邻,连续分布,它们在程序中距第一个符号的距离便是他们载程序中的地址。(ps:跟文件文件偏移一个意思) 本质上,程序中各种数据结构的访问,就是通过“该数据结构的起始地址+该数据结构所占内存大小决定的”来实现的。这就解释了为什么要给出变量类型,因为变量类型规定了变量所占内存的大小,每种类型都有其对应的内存容量。 程序中定义的任何一个变量,在编译后的可执行文件中都会占据一席之地。此变量在文件中的位置是编译器来安排的。编译器无论怎么安排程序中的数据,必然有一个先后顺序,而占据第一位的数据,其地址便是整个程序的起始地址,在它后面的数据依次排开。 0x1.2 什么是section 编译器提供的关键字Section只是为了让程序员在逻辑上将程序划分成几个部分,因为它是伪指令,CPU不知道这是什么东西。一般section的应用场所是根据不同的属性人为地将程序划分几部分

异常入口流程的细节

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-29 04:18:27
当异常发生时,以下的情况会随之发生: 1 压栈,并且栈指针更新; 2 处理器取出异常向量并且将其写入PC 3 寄存器更新(LR、IPSR和NVIC寄存器) 压栈 当异常发生时, 八个寄存器 会被自动压栈 这些寄存器包括R0-R3,R12,R14(链接寄存器),返回地址(下一条指令的地址或程序计数器),程序状态寄存器(xPSR)。 将寄存器R0-R3,R12,PC,LR和xPSR保存到栈中的原因是,这些寄存器被称为“ 调用者保存寄存器 ” 使用进程栈PSP ——异常发生时处理器处于线程模式并且CONTROL【1】置一, 使用主栈MSP ——对于嵌套异常,压栈时总是使用主栈,因为处理器当前处于处理模式,这种情况下只能使用主栈 ——异常发生时,处理器处于线程模式,CONTROL【1】为0,使用主栈。 C函数不需要保存这些寄存器的值,为了使异常处理能够像普通C函数一样使用,这些寄存器需要由硬件进行保存和恢复,这样在回到线程模式时,中断前的程序能够正常运行。 栈帧 ——压栈时保存到栈里的数据。 当压栈结束后,栈指针会得到更新,并且主栈指针会被选择为当前栈指针,处理模式使用的总是主栈MSP,然后异常向量也会被取出。 寄存器的压栈顺序如图 xPSR是组合状态寄存器 其中的三个寄存器之一:IPSR中断程序状态寄存器,包含了当前的中断服务程序(ISR)编号,由此可以取出异常向量。

闲逛计算机系统(二):说说计算机硬件系统

我怕爱的太早我们不能终老 提交于 2020-01-28 04:02:43
  上一篇《闲逛计算机系统(一):从helloworld说起》中,我们说了一个helloworld程序从编写到执行的整个过程。这篇我们来说说计算机硬件组成,然后结合helloworld程序来说明helloworld是怎样利用计算机硬件资源运行的。   首先介绍计算机的硬件组成,下面是一个IntelPentium系列的结构图:   总线     总线是贯穿整个系统的一个电子管道,用来在各个部件间传递数据信息。总线传送的字节长度是固定的,称为字。一个字中的字节数根据系统的不同而不同,在常见的32位机器上字长就是4个字节,64位机器上就是8个字节。   2.  I/O设备     I/O设备就是系统与外界世界的联系通道。一般系统包括4个I/O设备:鼠标,键盘,显示器以及磁盘设备。我们编写好的helloworld程序就放在磁盘上。     每个I/O设备都有一个控制器或者适配器与I/O总线相连。他们的功能就是在I/O设备和I/O总线之间传递信息。   3.  主存     主存就是我们平常所说的内存,在处理器执行程序时,用来存放程序和程序处理的数据。从物理上来说,主存就是由一组动态随机存取存储器芯片组成的。从逻辑上来说,主存就是一个线性的字节数组,每个字节都有一个唯一的地址。   4.  处理器     处理器是计算机的核心,是解释存储在主存中指令的引擎。处理器的核心是一个字长的存储设备

如何在Linux下写汇编

对着背影说爱祢 提交于 2020-01-26 03:37:40
本文为翻译文章,原文参见: http://docs.cs.up.ac.za/programming/asm/derick_tut/ 1.NASM编译器 目前Linux下的汇编器主要有:as、as86和gas,但是本文使用的是NASM(The Netwide Assembler)。它使用Intel形式的汇编格式,和Intel形式相对的是AT&T形式的汇编格式。 2.Linux下汇编介绍 2.1DOS和Linux下汇编的主要不同 (1)DOS下的汇编,主要通过 int 21h 中断来实现各种DOS功能调用,而BIOS调用则是主要通过 int 10h 和 int 16h 中断来实现。但是在Linux中, 所有以上的功能调用都是通过内核来实现的。因此所有的功能都是通过“系统调用”来实现,而我们可以通过使用 int 80h 中断来实现系统调用。其中,Linux大约有190个左右的系统调用,比DOS下的要少。 (2)Linux是一个真正32位保护模式的操作系统,因此我们使用的是32为的汇编程序。32位汇编程序运行我们使用全部的内存(4G),这意味着我们不用在考虑段基址了,也不用在修改和操作段寄存器了,从某种程度上来说,变的更容易了。 (3)在32为汇编程序中,我们可以使用32位的寄存器 EAX、EBX、ECX等代替传统的16位寄存器 AX、BX、CX等寄存器。 2.2Linux下汇编的编写

JVM介绍(入门知识)

◇◆丶佛笑我妖孽 提交于 2020-01-26 00:17:25
Java 虚 拟 机 (JVM) 是可运行 Java 代 码 的假想 计 算机。只要根据 JVM 规 格描述将解 释 器移植到特定的 计 算机上,就能保 证经过编译 的任何 Java 代 码 能 够 在 该 系 统 上运行。本文首先 简 要介 绍 从 Java 文件的 编译 到最 终执 行的 过 程,随后 对 JVM 规 格描述作一 说 明。       一 .Java 源文件的 编译 、下 载 、解 释 和 执 行    Java 应 用程序的 开发 周期包括 编译 、下 载 、解 释 和 执 行几个部分。 Java 编译 程序将 Java 源程序翻 译为 JVM 可 执 行 字 节码 。 这 一 编译过 程同 C/C++ 的 编译 有些不同。当 C 编译 器 编译 生成一个 对 象的代 码时 , 该 代 码 是 为 在某一特定硬件平台运行而 产 生的。因此,在 编译过 程中, 编译 程序通 过查 表将所有 对 符号的引用 转换为 特定的内存偏移量,以保 证 程序运行。 Java 编译 器却不将 对变 量和方法的引用 编译为 数 值 引用,也不确定程序 执 行 过 程中的内存布局,而是将 这 些符号引用信息保留在字 节码 中,由解 释 器在运行 过 程中 创 立内存布局,然后再通 过查 表来确定一个方法所在的地址。 这样 就有效的保 证 了 Java 的可移植性和安全性。   

JVM(JAVA虚拟机)

↘锁芯ラ 提交于 2020-01-26 00:16:35
Java虚拟机(JVM)是可运行Java代码的假想计算机。只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行。本文首先简要介绍从Java文件的编译到最终执行的过程,随后对JVM规格描述作一说明。   一.Java源文件的编译、下载、解释和执行   Java应用程序的开发周期包括编译、下载、解释和执行几个部分。Java编译程序将Java源程序翻译为JVM可执行代码—字节码。这一编译过程同C/C++的编译有些不同。当C编译器编译生成一个对象的代码时,该代码是为在某一特定硬件平台运行而产生的。因此,在编译过程中,编译程序通过查表将所有对符号的引用转换为特定的内存偏移量,以保证程序运行。Java编译器却不将对变量和方法的引用编译为数值引用,也不确定程序执行过程中的内存布局,而是将这些符号引用信息保留在字节码中,由解释器在运行过程中创立内存布局,然后再通过查表来确定一个方法所在的地址。这样就有效的保证了Java的可移植性和安全性。   运行JVM字节码的工作是由解释器来完成的。解释执行过程分三部进行:代码的装入、代码的校验和代码的执行。装入代码的工作由"类装载器"(class loader)完成。类装载器负责装入运行一个程序需要的所有代码,这也包括程序代码中的类所继承的类和被其调用的类。当类装载器装入一个类时,该类被放在自己的名字空间中

Java编译器、JVM、解释器

徘徊边缘 提交于 2020-01-26 00:15:51
Java虚拟机(JVM)是可运行Java代码的假想计算机。只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行。本文首先简要介绍从Java文件的编译到最终执行的过程,随后对JVM规格描述作一说明。      一.Java源文件的编译、下载 、解释和执行   Java应用程序的开发周期包括编译、下载 、解释和执行几个部分。Java编译程序将Java源程序翻译为JVM可执行的字节码。这一编译过程同C/C++ 的编译有些不同。当C编译器编译生成一个对象的代码时,该代码是为在某一特定硬件平台运行而产生的。因此,在编译过程中,编译程序通过查表将所有对符号的引用转换为特定的内存偏移量,以保证程序运行。Java编译器却不将对变量和方法的引用编译为数值引用,也不确定程序执行过程中的内存布局,而是将这些符号引用信息保留在字节码中,由解释器在运行过程中创立内存布局,然后再通过查表来确定一个方法所在的地址。这样就有效的保证了Java的可移植性和安全性。      运行JVM字节码的工作是由解释器来完成的。解释执行过程分三部进行:代码的装入、代码的校验和代码的执行。装入代码的工作由"类装载器"(class loader)完成。类装载器负责装入运行一个程序需要的所有代码,这也包括程序代码中的类所继承的类和被其调用的类。当类装载器装入一个类时

DSP程序中常出现的EINT、DINT、ERTM、DRTM、EALLOW、EDIS的理解

风格不统一 提交于 2020-01-25 10:06:48
对DSP程序中常出现的EINT、DINT、ERTM、DRTM、EALLOW、EDIS的理解 在看DSP 的初始化程序中经常会看到 void DisableDog ( void ) { EALLOW ; SysCtrlRegs . WDCR = 0x0068 ; EDIS ; } EALLOW与EDIS究竟有什么含义呢? 在.h文件中会发现,这两条其实是汇编指令 # define EALLOW asm(" EALLOW") # define EDIS asm(" EDIS") 同样的还有: # define EINT asm(" clrc INTM") //INTM置0,开中断 # define DINT asm(" setc INTM") //INTM置1,关中断 # define ERTM asm(" clrc DBGM") //使能调试事件 # define DRTM asm(" setc DBGM") //禁止调试事件 解释: TI系列DSP为了提高安全性能,将很多关键寄存器作了保护处理。通过状态寄存器1(ST1)的位6设置与复位,来决定是否允许DSP指令对关键寄存器进行操作。这些关键寄存器包括:器件仿真寄存器、FLASH寄存器、CSM寄存器、PIE矢量表、系统控制寄存器、GPIOMux寄存器等等。 DSP由于在上电复位之后,状态寄存器基本上都是清零

一步步学习汇编系列(7)

夙愿已清 提交于 2020-01-24 21:45:29
寄存器(内存访问) 从访问内存的角度继续学习几个寄存器 首先理解几个要点: 1. 内存中字的存储 n 在 0 地址处开始存放 20000 : n 0 号单元是低地址单元, 1 号单元是高地址单元。 备注:任何两个地址连续的内存单元, N 号单元和 N+1 号单元,可以将它们看成两个内存单元 ,也可以看成一个地址为 N 的字单元中的高位字节单元和低位字节单元。 2. DS 和 [address] n CPU 要读取一个内存单元的时候,必须先给出这个内存单元的地址; n 在 8086PC 中,内存地址由段地址和偏移地址组成。 n 8086CPU 中有一个 DS 寄存器,通常用来存放要访问的数据的段地址。 n 例如:我们要读取 10000H 单元的内容可以用如下程序段进行: mov bx,1000H mov ds,bx mov al,[0] n 上面三条指令将 10000H ( 1000:0 )中的数据读到 al 中。 mov 指令的格式: mov 寄存器名,内存单元地址 “[…]” 表示一个内存单元, “[…]” 中的 0 表示内存单元的偏移地址。 那么内存单元的段地址是多少呢?就是上面的 ds 备注: 8086CPU 不支持将数据直接送入段寄存器的操作, ds 是一个段寄存器。 (硬件设计的问题) mov ds,1000H 是非法的。 数据-一般的寄存器-段寄存器 明白了以上原理