数据寄存器

精确解释java的volatile之可见性、原子性、有序性(通过汇编语言)

我是研究僧i 提交于 2019-12-02 18:52:00
一、实验环境: 1、Idea代码编辑器 2、jdk1.8.0_92 3、win10_x64 二、易产生误解的Java字段Volatile volatile保证了可见性,但是并不保证原子性!!! 1.volatile关键字的两层语义   一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:   1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。   2)禁止进行指令重排序。 volatile的可见性,即任何时刻只要有任何线程修改了volatile变量的值,其他线程总能获取到该最新值。具体更多实现可以参阅缓存一致性协议。 2.那么volatile为什么又不能保证原子性呢? 以volatile int i = 10;i++;为例分析: i++实际为load、Increment、store三个操作。 某一时刻线程1将i的值load取出来,放置到cpu缓存中,然后再将此值放置到寄存器A中,然后A中的值自增1(寄存器A中保存的是中间值,没有直接修改i,因此其他线程并不会获取到这个自增1的值)。如果在此时线程2也执行同样的操作,获取值i==10,自增1变为11,然后马上刷入主内存。此时由于线程2修改了i的值,实时的线程1中的i==10的值缓存失效,重新从主内存中读取,变为11

四、保护模式之内存分段管理机制

江枫思渺然 提交于 2019-12-02 18:51:07
以我的理解,内存的分段管理机制,就是人为的把内存分成几个小段(Segment),各段独立使用。 为什么要把内存分成很多小段使用呢?原因一是要多个程序同时运行:开QQ勾搭妹子,开网易云音乐听歌,开浏览器看网页。。。。。。好几个程序一起开着呢!如果几个程序都用同一块内存,那就乱了!所以,把内存分成几段:QQ用一段,别的程序不能访问; 网易云音乐用另一段,其他程序也不能访问。。。。。。原因二是不同程序的权力不一样:操作系统可以启动、关闭应用程序,应用程序可不能对操作系统指手画脚,也就是各段内存的被访问权限是不同的。 很明显,要准确定义一个段要三个参数:该段从物理内存的哪个位置开始(段开始的实际内存地址)、该段占用多大的内存空间(段的长度)、该段能被哪些程序访问(段的属性),用专业术语说就是段基址(Segment Base)、段界限(Segment Limit)、段属性(Segment Attritbute)。 用一个数据结构来描述段的三个属性,这个数据结构就叫 段 描述符(Descriptor)。由于历史的原因( 为了和80286兼容 ),这个数据结构看起来相当纠结: 三个参数竟然不各自独立连续存放,而是被拆开混存的! ; 段描述符图示 ; ; ------ ┏━━┳ ━ ━ ━┓内存高地址 ; ┃ 7 ┃ 段 ┃ ; ┣━━┫ 基 ┃ ; ┆ ┆ 址 ┆ ; 字节 ┆ ┆ 高 ┆ ;

STM32F767/429->CAN通信实验

笑着哭i 提交于 2019-12-02 15:07:55
CAN 简介 特点 CAN协议进行方法:帧 数据帧 基本构成 各段简介 CAN的位时序 CAN协议仲裁功能的实现 bxCAN 的主要特点 CAN 发送流程 CAN 接收流程 寄存器 主控制寄存器(CAN_MCR) CAN 位时序寄存器(CAN_BTR) CAN 发送邮箱标识符寄存器(CAN_TIxR)(x=0~3) CAN 发送邮箱数据长度和时间戳寄存器 (CAN_TDTxR) (x=0~2) CAN 发送邮箱低字节数据寄存器 (CAN_TDLxR) (x=0~2) CAN 接收 FIFO 邮箱标识符寄存器 (CAN_RIxR) (x=0/1) CAN 过滤器模式寄存器(CAN_FM1R) CAN 过滤器位宽寄存器(CAN_FS1R) CAN 过滤器 FIFO 关联寄存器(CAN_FFA1R) CAN 过滤器激活寄存器(CAN_FA1R) CAN 的过滤器组 i 的寄存器 x(CAN_FiRx)(i=0~27;x=1/2) 功能实现 CAN 的初始化配置步骤 1)配置相关引脚的复用功能(AF9),使能 CAN 时钟 2)设置 CAN 工作模式及波特率等 3)设置滤波器 硬件设计 STM32F767/429 与 TJA1050 连接关系 软件设计 其中重要函数讲解 CAN_Mode_Init Can_Tx_Msg Can_Msg_Pend Can_Rx_Msg can.h 的 CAN

GDB print

邮差的信 提交于 2019-12-02 14:48:34
1.命令格式:print 变量名 简写为: p 变量名 2. print 操作符 @ 是一个和数组有关的操作符,在后面会有更详细的说明。 :: 指定一个在文件或是一个函数中的变量。 {} 表示一个指向内存地址的类型为type的一个对象。 3. 察看内容 全局变量(所有文件可见的) 静态全局变量(当前文件可见的) 局部变量(当前Scope可见的) 如果你的局部变量和全局变量发生冲突(也就是重名),一般情况下是局部变量会隐藏全局变量。如果此时你想查看全局变量的值时,你可以使用“::”操作符: file::variable function::variable eg: 查看文件f2.c中的全局变量x的值: gdb) p 'f2.c'::x 注:如果你的程序编译时开启了优化选项,那么在用GDB调试被优化过的程序时,可能会发生某些变量不能访问,或是取值错误码的情况。对付这种情况时,需要在编译程序时关闭编译优化。GCC,你可以使用“-gstabs” 选项来解决这个问题。 4. 查看数组 (1)动态数组: p *array@len array:数组的首地址,len:数据的长度 eg: (gdb) p *array@len $1 = {2, 4, 6, 8, 10} (2)静态数组 可以直接用print数组名,就可以显示数组中所有数据的内容了。 5. 输出格式 x 按十六进制格式显示变量。 d

STM32第一周复习

Deadly 提交于 2019-12-02 14:45:58
资料可以去意法半导体官网 最底层(了解)CM3权威指南/CM4权威指南 芯片参考手册(了解)STM32F10x中文参考手册 官方其他资源教程(了解)固件库包(含参考源码),官方培训PPT 熟练掌握C语言 熟练掌握一种开发环境 库函数和寄存器对比学习 入门一款单片机的学习目标 基本外设 GPIO输入输出, 外部中断 定时器 串口 基本外设接口 SPI IIC WDG FSMC ADC/DAC SDIO 高级功能 UCOS FATFS EMWIN 外什么选择STM32 什么是STM32 Cortex-M3属于ARMv7架构 A系列 面对尖端的基于虚拟内存系统的操作系统和用户 R系列 针对于实时系统 M系列 对微控制器 性价比高,更稳定,所以可以替换ARM7 芯片有哪些资源 ZET6 144个引脚 112个IO 512K 64K RCT6 64个引脚 51个IO 256K 48K 强大的时钟系统 上电复位,掉电复位 低功耗 AD 3个12位 内置参考电压 内置温度 DA 2个12位 DMA 12个DMA通道 定时器 多达11个定时器 通信接口 2个I2C 5个串口 3个SPI 1个CAN2.0 1个USB FS 1个SDIO 最小系统 供电 复位 时钟 boot启动模式选择 下载电路 后备电池 程序下载 串口下载 STM32的ISP下载只能通过串口1,也就是对应的PA9,PA10

《ucore lab1 练习4》实验报告

时光总嘲笑我的痴心妄想 提交于 2019-12-02 14:44:49
[练习4]分析bootloader加载ELF格式的OS的过程 通过阅读bootmain.c,了解bootloader如何加载ELF文件。通过分析源代码和通过qemu来运行并调试bootloader&OS,理解: 1.bootloader如何读取硬盘扇区的? 2.bootloader是如何加载ELF格式的OS? 问题1:bootloader如何读取硬盘扇区 分析原理 阅读材料其实已经给出了读一个扇区的大致流程: 1.等待磁盘准备好 2.发出读取扇区的命令 3.等待磁盘准备好 4.把磁盘扇区数据读到指定内存 实际操作中,需要知道怎样与硬盘交互。阅读材料中同样给出了答案:所有的IO操作是通过CPU访问硬盘的IO地址寄存器完成。硬盘共有8个IO地址寄存器,其中第1个存储数据,第8个存储状态和命令,第3个存储要读写的扇区数,第4~7个存储要读写的起始扇区的编号(共28位)。了解这些信息,就不难编程实现啦。 分析代码 bootloader读取扇区的功能是在boot/bootmain.c的readsect函数中实现的,先贴代码: static void waitdisk ( void ) { //如果0x1F7的最高2位是01,跳出循环 while ( ( inb ( 0x1F7 ) & 0xC0 ) != 0x40 ) /* do nothing */ ; } /* readsect -

速读《深入理解计算机系统》

时光毁灭记忆、已成空白 提交于 2019-12-02 13:04:31
本周速读了《深入理解计算机系统》这本书,这本书从程序员的角度介绍了计算机系统的内在运作,展示了一些本质概念是如何实际的影响应用程序的正确性、性能和实用性的。收获如下: 1、关于进程和线程 进程是操作系统对运行程序的一种抽象,是指计算机中已运行的程序,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。 线程有时被称为轻量级进程,是操作系统能够进行运算调度的最小单位。线程是进程中的一个实体,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源,同一进程中的多个线程之间可以并发执行。 2、几种数据传送指令 movl:传送双字,源操作数指定一个值,可以是立即数,可以存放在寄存器或存储器中。目的操作数指定一个位置,可以是寄存器或存储器地址。 movw:传送两个字节,当一个操作数为寄存器时,必须为下图中八个双字节寄存器元素中的一个。 movb:传递一个字节,当一个操作数为寄存器时,必须为下图中八个单字节寄存器元素中的一个。 movsbl和movzbl负责拷贝一个字节,并设置目的操作数中其余的位。 movsbl的源操作数是单字节的,并将高24位设置为源字节的最高位,然后拷贝到双字的目的中。 movzbl的源操作数是单字节的,在前面加24个0扩展到32位,然后拷贝到双字的目的中。 3、寄存器的使用惯例

8086的7种寻址方式

99封情书 提交于 2019-12-02 12:15:13
七种寻址方式: 1. 立即寻址: 操作数包含在指令中,是指令的一部分。此时的操作数称为立即数 MOV EAX, 1234H 2. 寄存器寻址: 操作数在CPU寄存器中,指令中指定寄存器编号 MOV SI, AX MOV AL, AH 3. 直接寻址: 操作数在存储器中,指令直接包含操作数的有效地址。此时操作数一般存放在数据段DS中,采用换段前缀可以使用其它段寄存器。 MOV AX, [1234H] 4. 寄存器间接寻址: 操作数在存储器中,操作数有效地址在ESI、EDI、EBX、EBP之一种。在不使用换段前缀的情况下, 若有效地址在 SI/DI/BX 中,则以 DS 的值为段值; 若有效地址在 BP 中,则以段寄存器 SS 的值为段值。 MOV AX, [SI] MOV [BP], CX 5. 寄存器相对寻址: 操作数在存储器中,操作数的有效地址是一个基址寄存器(BX、BP)或变址寄存器(SI、DI)内容加上指令中给定的8位或16位位移量之和。即: EA = (BX/BP/SI/DI) + (8/16位位移量) 在不使用换段前缀的情况下,若SI/DI/BX的内容作为有效地址的一部分,则以DS的值为段值;若BP的内容作为有效地址的一部分,则以段寄存器SS的值为段值。 在指令中给定的8位或16位位移量以补码形式表示。在计算有效地址时,若位移量是8位,则将其有符号扩展为16位

牛客 C++刷题day51

扶醉桌前 提交于 2019-12-02 06:58:47
1. 顺序存取:当“打开”文件进行读或写操作时总是从文件的开头开始,从头到尾顺序读或写。 直接存取:又称随机存取文件,可以通过调用C语言的库函数来指定开始读(写)的字节号,然后直接对此位置上的数据进行读或写操作 2. register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度。 、但是使用register修饰符有几点限制 (1)register变量必须是能被CPU所接受的类型。 这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。不过,有些机器的寄存器也能存放浮点数。 (2)因为register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址。 (3)只有局部自动变量和形式参数可以作为寄存器变量,其它(如全局变量)不行。 在调用一个函数时占用一些寄存器以存放寄存器变量的值,函数调用结束后释放寄存器。此后,在调用另外一个函数时又可以利用这些寄存器来存放该函数的寄存器变量。 (4)局部静态变量不能定义为寄存器变量。不能写成:register static int a, b, c; (5)由于寄存器的数量有限(不同的cpu寄存器数目不一),不能定义任意多个寄存器变量,而且某些寄存器只能接受特定类型的数据(如指针和浮点数)

操作系统第五章

北战南征 提交于 2019-12-02 06:51:05
输入输出设备分为块设备(硬盘)和字符设备(鼠标,键盘) 硬盘的输入输出以磁盘块(扇区)为单位 鼠标键盘以字符为单位,通过中断机制输入 ----------------------------------------------------------------------------------------------------------------------------------------------- IO设备由 机械部件和电子部件 两部分组成,电子部件就是电路板,也就是IO控制器。IO控制器作为CPU控制IO设备机械部件的中介。它含有控制寄存器(存放CPU命令的参数),状态寄存器(设备是否能进行读写操作),数据寄存器(数据中转站)。由于IO控制器中含有多个寄存器,当CPU发出命令后,IO控制器要进行地址转换(由IO控制器的IO逻辑部分完成),找到对应的寄存器。 IO控制器由三部分组成,分别为 CPU与控制器的接口,IO逻辑,以及控制器与设备的接口 CPU与控制器的接口: 数据寄存器,状态寄存器,控制寄存器位于这里 IO逻辑: CPU 通过控制线告诉IO逻辑指令类型,通过地址线告诉IO逻辑要操作的设备地址,IO逻辑通过访问控制寄存器和状态寄存器得出指令。如果是输出指令的话,IO逻辑将数据寄存器中的数据 转移到 控制器与设备的接口。 控制器与设备的接口:输出命令的话