汇编-数据处理指令-笔记
- 格式:doc
- 大小:239.00 KB
- 文档页数:35
Knowledge问题谁在DSP的汇编语言中加入了NOP指令?NOP指令加入的条件是什么?About DSP1.DSP是实时数字信号处理的核心和标志。
2.DSP分为专用和通用两种类型。
专用DSP一般采用定点数据结构(一般不支持小数),数据结构简单,处理速度快;通用DSP灵活性好,但是处理速度有所降低。
3.DSP采用取指、译码、执行三个阶段的流水线(Pipeline)技术,缩短了执行时间,提高了运行速率。
DSP具有8个Functional unit,如果并行处理的话,以600MHz的时钟计算,如果执行的指令是single cycle指令,则可以4800MIPS(指令每秒)。
4.DSP的8个functional Unit,具有独特的功能,对滤波、矩阵运算、FFT(傅里叶变换)具有哈弗结构把指令空间与数据空间隔离的存储方式。
这样实现是为了实现指令的连续读取,而实现pipeline流水线结构。
传统哈弗结构:两个独立的存储空间,还使用独立总线。
让取指与执行存储独立,加快执行速度。
改进型哈弗结构:指令与数据的存储空间还是独立的。
但是使用公共的总线(地址总线与数据总线)。
这样实现的原因是因为出现了CACHE,数据的存储动作大部分被内部的CACHE 总线承接了,所以总线冲突的情况会大大减少。
同时让总线的结构与控制变得简单,CACHE 存储的速度也明显快于外设存储器。
冯诺依曼结构:是指令空间与数据空间共享的存放方式。
它不能实现pipeline的执行过程。
Pipeline(流水线)技术是把指令的取指-译码和指令的执行独立开来的技术。
虽然每条指令的过程还是要经过取指-译码-执行三个阶段最少3个CPU Cycle。
但是多个指令同时并行先后进行,保证总体的指令吞吐速率理想情况下可以保证在每个指令只要一个CPU CYCLE。
Pipeline技术必须要有哈弗结构支持,即必须把指令空间与数据空间隔离存放。
流水线阻断流水线中阻断现象也十分普遍,下面就各种阻断情况下的流水线性能进行详细分析。
51单片机汇编指令及伪指令小结51单片机汇编指令及伪指令小结51单片机是一种广泛应用的基于汇编语言的微控制器。
它的汇编指令集非常丰富,包括了基本的数据处理、逻辑运算、分支跳转、数据存储和输入输出等指令。
汇编指令的灵活运用可以实现各种复杂的功能,因此掌握51单片机的汇编指令是开发嵌入式系统的重要基础。
1. 基本数据处理指令51单片机汇编指令集包括了一系列基本的数据处理指令,如加法(add)、减法(sub)、乘法(mul)、除法(div)等。
这些指令用于实现对数据的基本运算操作。
2. 逻辑运算指令逻辑运算指令用于实现各种逻辑运算,如与(and)、或(or)、非(not)、异或(xor)等。
这些指令通常用于处理数据的开关控制、状态判断等功能。
3. 分支跳转指令分支跳转指令用于实现程序的流程控制。
常用的分支跳转指令包括无条件跳转(jmp)、条件跳转(jz、jnz、jc、jnc等)、循环跳转(loop)等。
这些指令可以根据条件和需求设置程序的执行流程,实现各种循环、分支等功能。
4. 数据存储指令数据存储指令用于实现数据的存储和加载操作。
常用的存储指令包括将数据存储到寄存器或内存中(mov)、将数据从寄存器或内存中加载(ld)等。
这些指令通过对数据的存储和加载,实现对数据的读写操作。
5. 输入输出指令输入输出指令用于实现与外设的数据通信。
常用的输入输出指令包括从端口输入(instr)、输出到端口(outstr)等。
这些指令通过与外部设备的数据交互,实现嵌入式系统与外设的连接。
除了以上的基本指令外,51单片机还提供了一些伪指令,用于程序的组织和调试。
这些伪指令包括宏指令、条件编译指令、调试指令等。
1. 宏指令宏指令是一种通过宏展开的方式来扩展汇编代码的指令。
它通过提前定义一些宏,并在代码中使用这些宏来生成更复杂的汇编代码。
宏指令的好处是可以简化代码的书写,使得程序的逻辑更清晰。
2. 条件编译指令条件编译指令用于根据编译时的条件来选择性地编译代码。
second汇编指令用法-回复[second汇编指令用法]汇编语言是计算机硬件能够直接识别和执行的一种低级语言。
在汇编语言的指令集中,有许多常用的指令,其中包括了一些用于处理数据的指令,也就是我们所说的"数据处理指令"。
其中,"second"指令是一种常用的数据处理指令,用于将操作数中的秒部分提取出来。
本文将以"second"指令为主题,详细介绍其用法和实际应用。
第一部分:指令介绍"second"指令是一种简单易用的指令,它用于将参数中的时间值的"秒"部分提取出来。
该指令的语法如下所示:second operand1, operand2其中,"operand1"表示要提取秒数的时间值,"operand2"表示将提取的秒数存储的寄存器或内存地址。
第二部分:用法解析1. "second"指令的操作数类型"second"指令的操作数可以是寄存器、内存地址、立即数等。
2. 操作数的格式和数据类型在使用"second"指令时,操作数的格式应与运行环境和数据类型相匹配。
例如,如果操作数是寄存器,那么应该使用正确的寄存器名称。
3. "second"指令的执行过程当执行"second"指令时,计算机会去除时间值中的"分钟"和"小时"部分,然后将剩余部分存储到指定的寄存器或内存地址中。
第三部分:实际应用案例以下是一个实际应用案例,演示如何使用"second"指令来提取秒数,并将其存储到寄存器BX中。
section .datatime db '12:34:56' ; 定义一个包含时间值的字符串section .textglobal _start_start:mov esi, time ; 将时间值的内存地址存储到ESI寄存器中mov cl, [esi+6] ; 获取时间值中的秒部分并存储到CL寄存器中mov ah, 0 ; 将AH寄存器清零mov al, cl ; 将AL寄存器设置为秒数mov bx, ax ; 将AX寄存器的值存储到BX寄存器中mov eax, 1 ; 设置系统调用号为1(exit)xor ebx, ebx ; 设置返回值为0int 0x80 ; 调用系统中断在上述示例代码中,我们首先定义了一个包含时间值的字符串,接着通过将其内存地址存储到ESI寄存器中,从而将其作为"second"指令的操作数。
学习笔记-汇编-两个16位数字相加获得32位数字使⽤的是MASM编译在XP环境下 command内 debug 调试的啥也不说上代码!!assume cs:code,ds:datadata segmentdw 0fa12h,0fdffhdata endscode segmentstart:mov ax,datamov ds,ax ;设置数据段mov ax,0h ;清零mov bx,0h ;清零mov al,ds:[0] ;fa12低位mov bl,ds:[2] ;fdff低位add ax,bx ;两个8位数字相加 ah ⾼位存储进位的数mov ds:[0],al ;将低位结果存到ds[0]mov al,ah ;将进位数存⾄ax低位mov ah,0h ;⾼位清零xor bx,bx ;bx清零mov bl,ds:[1]add ax,bx ;数字1⾼位与进位数相加mov bl,ds:[3]add ax,bx ;数字2⾼位与进位数相加mov ds:[1],ax ;⾼位相加后的数据放⾄ds[1];⾼位相加可能是8位也可能是16位int 21hcode endsend start主要思路就是在16位寄存器⾥⾯计算两个⼋位数字的和将进位的数保存⾄⾼位可以依次扩展⾄ 32位 64位等等闲来⽆事最近看了⼀点汇编的知识课本上都是⼀些 mov add之类的操作但是都没有任何实际的⽤途第⼀次发帖来博客园也有好⼏年时间了⼀直都处于潜⽔阶段看各位⼤侠再次⾼谈阔论看的⼩弟也是蠢蠢欲动终于忍不住写下了⼀点微薄见解忘在此结实各路英雄豪杰。
32位汇编语言学习笔记3leal和算术运算指令32位汇编语言学习笔记在学习汇编语言的过程中,我们已经了解了一些基本指令和寄存器的用法。
本文将继续介绍两个重要的指令:leal指令和算术运算指令。
通过深入了解和学习这两个指令,我们将更好地理解和掌握汇编语言编程的技巧和方法。
一、leal指令leal指令用于将一个有效地址(Effective Address,EA)加载到目标操作数中。
它的一般格式为:leal Source, Destination。
在这个指令中,Source表示源操作数,可以是寄存器、内存或立即数。
Destination表示目标操作数,只能是寄存器。
leal指令在源操作数的基础上进行计算,将计算结果存储到目标操作数中。
下面是一些leal指令的示例:1. leal (%eax,%ebx,4), %edx这条指令将地址(%eax + %ebx * 4)的结果存储到%edx寄存器中。
其中,%eax是个基址寄存器,%ebx是个变址寄存器,4表示缩放因子。
2. leal -8(%ebp), %ecx这条指令将地址(%ebp - 8)的结果存储到%ecx寄存器中。
其中,%ebp是个基址寄存器,-8是个偏移量。
需要注意的是,leal指令只能进行地址计算,并将结果存储到目标操作数中,不能进行实际的加载操作。
二、算术运算指令在汇编语言中,算术运算指令主要用于进行数值的计算和操作。
常见的算术运算指令包括add、sub、mul、div等。
这些指令可以对数据寄存器和内存中的数据进行四则运算。
下面是一些常用的算术运算指令及其示例:1. add指令:用于将两个操作数相加,并存储结果到目标操作数中。
一般格式为:add Source, Destination。
示例:add %eax, %ebx这条指令将%eax和%ebx寄存器中的值相加,结果存储到%ebx中。
2. sub指令:用于将第一个操作数减去第二个操作数,并将结果存储到目标操作数中。
汇编语言学习笔记《汇编语言》--王爽前言学习汇编目的:充分获得底层编程体验;深刻理解机器运行程序的机理。
原则:没有通过监测点不要向下学习;没有完成当前实验不要向下学习。
第一章基础知识有三类指令组成汇编语言:汇编指令;伪指令;其他符号。
8bit = 1byte = 一个存储单元有n根地址线,则可以寻址2的n次方个内存单元。
1.1节--1.10节小结(1)汇编指令是机器指令的助记符,同机器指令一一对应。
(2)每一种cpu都有自己的汇编指令集。
(3)cpu可以直接使用的信息在存储器中存放。
(4)在存储器中指令和数据没有任何区别,都是二进制信息。
(5)存储单元从零开始顺序编号。
(6)一个存储单元可以存储8个bit,即八位二进制数。
(7)每一个cpu芯片都有许多管脚,这些管脚和总线相连。
也可以说,这些管脚引出总线。
一个cpu可以引出的三种总线的宽度标志了这个cpu不同方面的性能。
地址总线的宽度决定了cpu的寻址能力;数据总线的宽度决定了cpu与其他器件进行数据传送时的一次数据传送量;控制总线的宽度决定了cpu对系统中其他器件的控制能力。
监测点:1KB的存储器有1024个存储单元?存储单元的编号从0到1023.内存地址空间:最终运行程序的是cpu,我们用汇编编程时,必须要从cpu的角度思考问题。
对cpu来讲,系统中的所有存储器中的存储单元都处于一个统一的逻辑存储器中,它的容量受cpu寻址能力的限制。
这个逻辑存储器即是我们所说的内存地址空间。
第二章寄存器(cpu的工作原理)mov ax, 2add ax, axadd ax, axadd ax, ax(1)cpu中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;(2)段地址和偏移地址通过内部总线送人一个称为地址加法器的部件;(3)地址加法器将两个16位地址合成为一个20位的物理地址;(4)地址加法器通过内部总线将20位物理地址送人输入输出控制电路;(5)输入输出控制电路将20位物理地址送上地址总线;(6)20位物理地址被地址总线传送到存储器;段地址*16+偏移地址= 物理地址的本质含义内存并没有分段,段的划分来自cpu。
汇编学习笔记(13)-宏指令(MASM)结构说明: 是⼀堆数据的定义的集合基本格式: 结构名称 STRUC 字段的定义 结构名称 ENDS 举例: STUDENT STRUC ID DW ? SCORE DB 1 NAME DB 'STUDENTNAME' STUDENT ENDS定义变量: 变量名结构类型 < 参数表 > 举例: S1 STDUENT <1,50,'zhao'> S2 STDUENT <1,60,'zhang'> S3 STDUENT <1,70,'wang'>结构使⽤: 1. MOV AX, P1.ID 2. MOV BX, OFFSET P1 MOV AL, [BX].SCORE总结: 使⽤起来还是和C/C++ 的结构⽐较类似的,实际上 P1.ID 和 [BX].SCORE 的两种引⽤⽅式本质上是汇编器帮我们转换了地址。
记录说明: 结构是将将⼀堆定义结合起来,⽅便管理,那么记录就是讲⼀个字或者⼀个字节拆分成各种按照位的定义 实际上记录就是⼀个字或者字节的按位定义,所以长度最长不超过16位,右对齐。
基本格式: 记录名称 RECORD 字段1:位宽=初始值,字段2:位宽=初始值,…. 举例: ABCD RECORD AA:5=12, BB:3=6, CC:4=3 内存结构: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0 0 0 0 aa aa aa aa aa bb bb bb cc cc cc cc定义变量: 变量名结构类型 < 参数表 > 举例: S2 ABCD <1,2,3> S1 ABCD <1,2,3> S3 ABCD <3,2,1>记录使⽤: WIDTH 返回⼀个记录整体的位宽或者⼀个字段的位宽 MOV AX, WIDTH ABCD MOV AX, WIDTH AA MASK 返回对应字段的掩码 MOV BX, MASK AA; BX = 0001111100000000B总结: 和结构的功能有点类似,相当于在字节尺度尺度上的结构定义,相当于定义标志位,⽽MASK 就是提取标志位的掩码。
ARM汇编语言程序设计1.ARM汇编语言概述2.ARM寄存器3.ARM指令ARM指令包括数据处理指令、传输指令、分支指令和其他特殊指令。
(1)数据处理指令:包括算术运算、逻辑运算、移位和旋转、比较和测试等。
(2)传输指令:用于数据的加载和存储,包括复制、分配和堆栈操作等。
(3)分支指令:用于控制程序流,包括无条件跳转、条件跳转和中断处理等。
4.ARM程序设计(1)初始化:程序开始时需要进行系统和寄存器的初始化。
可以将堆栈指针初始化,设置另外的寄存器和内存变量等。
(2)输入输出:程序可能需要从外部设备读取数据或向外部设备写入数据。
可以使用传输指令实现数据的输入和输出。
(3)运算处理:根据程序的需求,进行各种运算处理。
可以使用数据处理指令实现数据的加减乘除、逻辑运算等。
(4)循环和条件控制:根据需要,使用分支指令控制程序的流程。
可以使用无条件跳转、条件跳转和循环指令实现程序的循环和条件控制。
(5)结束:在程序执行完毕后,可以进行清理工作,例如释放内存、关闭设备等。
5.ARM程序设计实例下面是一个简单的ARM汇编程序示例,实现从数组中找到最大值并输出:.global _start.section .dataarray: .word 1, 3, 5, 2, 4max: .word 0.section .text_start:loop:next:在上述示例中,程序首先将数组的地址和最大值的地址加载到寄存器中。
然后使用循环和条件控制指令依次比较数组元素,找到最大值并将其存储在max变量中。
最后将最大值输出,并结束程序。
mrc汇编指令MRC汇编指令详解引言:MRC(Microprocessor Resource Controller)汇编指令是一种用于ARM架构处理器的指令集,主要用于控制和管理处理器资源,实现高效的操作和运算。
本文将详细介绍MRC指令的相关内容,包括指令的分类、功能和使用方法。
一、指令分类MRC指令主要分为三类:数据处理指令、控制指令和系统指令。
1. 数据处理指令:数据处理指令用于对数据进行运算和处理,包括加法、减法、乘法、除法等操作。
例如,ADD指令用于实现两个寄存器的相加运算,SUB 指令用于实现两个寄存器的相减运算,MUL指令用于实现两个寄存器的相乘运算,DIV指令用于实现两个寄存器的相除运算。
2. 控制指令:控制指令用于控制程序的流程和跳转,包括条件分支、循环和跳转等操作。
例如,B指令用于实现无条件跳转,BEQ指令用于实现等于零时的跳转,BNE指令用于实现不等于零时的跳转,BL指令用于实现子程序的调用。
3. 系统指令:系统指令用于管理和控制处理器的各种资源和功能,包括中断、异常处理、协处理器控制等操作。
例如,SWI指令用于实现软中断,MCR指令用于实现协处理器的数据传送和控制。
二、指令功能MRC指令具有丰富的功能,可以实现多种操作和运算。
下面介绍几个常用的指令功能:1. 数据传送:MRC指令可以实现数据在寄存器之间的传送和复制。
例如,MOV指令用于将数据从一个寄存器复制到另一个寄存器,LDR指令用于将数据从存储器加载到寄存器中,STR指令用于将数据从寄存器存储到存储器中。
2. 逻辑运算:MRC指令可以实现逻辑运算,包括与、或、非、异或等操作。
例如,AND指令用于实现两个寄存器的与运算,OR指令用于实现两个寄存器的或运算,NOT指令用于实现一个寄存器的非运算,EOR指令用于实现两个寄存器的异或运算。
3. 算术运算:MRC指令可以实现算术运算,包括加法、减法、乘法、除法等操作。
例如,ADD指令用于实现两个寄存器的相加运算,SUB指令用于实现两个寄存器的相减运算,MUL指令用于实现两个寄存器的相乘运算,DIV指令用于实现两个寄存器的相除运算。
ARM汇编指令集一、跳转指令跳转指令用于实现程序流程的跳转,在ARM程序中有两种方法可以实现程序流程的跳转:Ⅰ.使用专门的跳转指令。
Ⅱ.直接向程序计数器PC写入跳转地址值。
通过向程序计数器PC写入跳转地址值,可以实现在4GB的地址空间中的任意跳转,在跳转之前结合使用MOV LR,PC等类似指令,可以保存将来的返回地址值,从而实现在4GB连续的线性地址空间的子程序调用。
ARM指令集中的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,包括以下4条指令:1、B指令B指令的格式为:B{条件} 目标地址B指令是最简单的跳转指令。
一旦遇到一个B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。
注意存储在跳转指令中的实际值是相对当前PC值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算(参考寻址方式中的相对寻址)。
它是24 位有符号数,左移两位后有符号扩展为32 位,表示的有效偏移为26 位(前后32MB的地址空间)。
以下指令:B Label ;程序无条件跳转到标号Label处执行CMP R1,#0 ;当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label 处执行BEQ Label2、BL指令BL指令的格式为:BL{条件} 目标地址BL 是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC的当前内容,因此,可以通过将R14 的内容重新加载到PC中,来返回到跳转指令之后的那个指令处执行。
该指令是实现子程序调用的一个基本但常用的手段。
以下指令:BL Label ;当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到R14中3、BLX指令BLX指令的格式为:BLX 目标地址BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM 状态切换到Thumb状态,该指令同时将PC的当前内容保存到寄存器R14中。
因此,当子程序使用Thumb指令集,而调用者使用ARM指令集时,可以通过BLX指令实现子程序的调用和处理器工作状态的切换。
汇编学习笔记(4)-伪指令(MASM)前⾔ 编写汇编代码的时候会使⽤到两种语句,⼀种就是前⾯介绍的汇编指令⼜CPU提供功能⽀持,另⼀种呢叫做伪指令,伪指令是由汇编的编译器提供⽀持。
所以伪指令的运⾏结果都必须实在编译的时候就能确定的,下⾯介绍的就是伪指令了。
注意接下来介绍的伪指令都是基于MASM汇编编译器,⽐较常⽤的还有NASM 它的语法以后有机会介绍数值表达式 数值表达式不是汇编指令,表达式的值是在汇编代码的汇编过程中就由汇编编译器计算出结果⽽写到⼆进制程序中了,并不是在程序运⾏的过程中才计算的 (1) 常数表达式 常数就是直接的数字,直接写数字默认表⽰10进制数,也可以⽤符号指定为其他进制 D = ⼗进制 ; MOV AL, 1234D B = ⼆进制 ; MOV AL, 0101B H = ⼗六进制 ; MOV AL, 0FFFFH , 注意常数必须是数字开头不能是字母开头,如果16进制数第⼀个数字是字母的话就要补⼀个0在前⾯ Q = ⼋进制 ; MOV AL, 123Q 因为在程序中字母也是数字,所以其实也可以直接将字母或者字符串当成数字,⽐如 MOV AL, 'a' MOV AX,"ab" ; 双引号和单引号都是可以使⽤的 (2) 算数运算符 就是简单的正(+) 负(-) 加(+) 减(-) 乘(*) 除(/) 模(mod) mov ax, 100+200 mov ax, 100/2 (3) 关系运算符 等于(EQ) 不等(NE) ⼤于(GT) ⼩于(LT) ⼤于等于(GE) ⼩于等于(LE) 如果等式成⽴则实际的值为0FFFF就是补码表⽰的-1, 如果关系不成⽴那么结果就是0 mov ax, 123 gt 234 mov ax, 1234+5 lt 1235 (4) 逻辑运算 与(and) 或(or) ⾮(not) 异或(xor) 左位移(shl) 右位移(shr) mov ax, 1 shl 3 mov al, 3 and 47 (5) 其他操作符 HIGH LOW WIDTH MASK HIGH 表⽰取数据的⾼⼋位 LOW 表⽰取数据的低⼋位地址表达式 地址表达式所表⽰的是存储器操作数的地址。
汇编语⾔中cmp指令⽤法笔记与总结本⽂实例讲述了汇编语⾔中cmp指令⽤法。
分享给⼤家供⼤家参考,具体如下:cmp是⽐较指令,cmp的功能是相当于减法指令,只是不保存结果.cmp指令执⾏后,将对标志寄存器产⽣影响.其他相关指令通过识别这些被影响的标志寄存器来得知⽐较结果.cmp指令格式: cmp 操作对象1,操作对象2功能: 计算操作对象1 - 操作对象2 但不保存结果,仅仅根据计算结果对标志寄存器进⾏设置.⽐如cmp ax,ax 是做ax - ax 的运算,结果为0,但并不在ax中保存,仅影响flag的相关各位.指令执⾏后: zf = 1,pf = 1,sf = 0,cf = 0,of = 0;下⾯的指令:mov ax,8mov bx,3mov ax,bx执⾏后: (ax)= 8,zf = 0,pf = 1,sf = 0, cf = 0, of = 0如果 ax = bx 则 ax - bx = 0 ,所以 : zf = 1如果 ax != bx 则ax - bx != 0,所以 : zf = 0如果ax < bx 则ax - bx 将产⽣错位,所以 : cf = 1如果 ax >= bx 则 ax - bx 将不必借位,所以 : cf = 0如果ax > bx 则 ax - bx 既不必借位,结果⼜不为0, 所以 : cf = 0 并且 zf = 0如果 ax <= bx 则ax - bx 既可能借位,结果可能为0,所以 : cf = 1 或 zf =1检测⽐较结果的条件转移指令je 等于则转移 zf=1jne 不等于则转移 zf=0jb 低于则转移 cf=1jnb 不低于则转移 cf=0ja ⾼于则转移 cf=0且zf=0jna 不⾼于则转移 cf=1或zf=1e : equalne : not equalb: belownb : not belowa : abovena : not above编程: 统计data段中数值⼩于8的字节的个数,⽤ax保存统计结果mov ax,datamov ds,axmov ax,0 ;初始化累加器mov bx,0 ;ds:bx指向第⼀个字节mov cx,8s : cmp byte ptr [bx] , 8 ;和8进⾏⽐较jnb next ;如果不⼩于8转到next,继续循环inc ax ;如果⼩于8就将计数值加1next:inc bxloop s程序执⾏后: ax = 2还有疑问的可以去查看⼀下指令⼿册,讲解的⽐较细致希望本⽂所述对⼤家汇编语⾔程序设计有所帮助。
汇编JCC指令表与笔记汇编-JCC之前可以修改EIP寄存器的指令JMP,CALL,RETN所有JCC指令的动作->根据标志寄存器修改EIP的值标志寄存器 EFLAGSCF(bit 0)[Carry flag] C位若算术产⽣的结果在最⾼有效位(most-significant bit)发⽣进位或者借位则将其置1 反之清零这个标志通常⽤来指⽰⽆符号证书运算的溢出状态宽度溢出位。
只要容器内放不下就会发⽣变化MOV AL,0xFEADD AL,2 C => 1MOV AL,0x7FSBU AL,0xFF C => 1PF (bit 2) [parity flag] P位奇偶校验位如果结果的最低有效字节最后⼀个字节(least-significant byte)包含偶数个1位则该位置1,否则清零利⽤PF可进⾏奇偶校验检查需要传输1100 1110,数据中含5个1,所以其奇校验位位0,同时吧1100 1110传输给接收⽅,接收⽅收到数据后再⼀次计算奇偶性,1100 1110中仍然含有5个1,所以接收⽅计算出的奇偶验位还是0,与发送⽅⼀致,表⽰在此次传输过程中未发⽣错误。
例⼦:MOV AL,0xCEAF (bit 4)[Auxiliary Carry Flag] 辅助进位标志器如果算术操作在结果的第三位发⽣进位或者借位则该标志置1,否则清零这个标志在BCD(binary-code decimal)算术运算中被使⽤ZF(bit 5)[Zero Flag] ⽤的最多划重点。
若结果为0则将其置1,反之清零。
经常与CMP或者TEST等指令⼀起使⽤例1: 判断2个值是否相等MOV EAX,100MOV ECX,100CMP EAX,ECX(CMP指令相当于SUB指令,但是相减的结果并不保存到第⼀个操作数中只影响标志寄存器)例2:判断某个值是否为0AND EAX,EAX 0 ZF=1TEST EAX,EAX(TEST相当于and,但是与运算的结果并不保存到第⼀个操作数中只影响标志寄存器)SF(bit 7) [Sign Flag]该标志被设置为有符号整型的最⾼有效位(0指⽰结果为正,反之则为负)意思其实就是,运算完之后看下符号位是0(正)还是1(负)当然如果是⽆符号数运算就不⽤看了只看容器内数字的最⾼位例⼦MOV AL,0x7F MOV AL,0xFEADD AL,2 ADD AL,2OF(bit 11)[OverFlow Flag]溢出标志OF⽤于反应有符号数加减运算所得结果是否溢出可以这样理解:* 如果是⽆符号数运算,是否溢出看CF位* 如果是有符号数运算,是否溢出看OF位两个数做运算,运算完毕的结果跟运算前的数的最⾼位相同 OF为0最⾼位不同为1例⼦:MOV AL,0x7FADD AL,2DF(bit 10)[Diretion Flag]这个⽅向标志控制字符串指令(`MOVS`,CMPS,SCAS,LODS以及`STOS`)。
ARM汇编:数据处理指令集:MOV、ADD、ADDS、ADC、SUB、SUBS、SBC、R。
ARM指令集——数据处理指令数据处理指令有:MOV、ADD、ADDS、ADC、SUB、SUBS、SBC、RSB、MUL、AND、ORR、EOR、BIC、CMP、TST、TEQ、LSL、LSR、ASR、RORV数据处理指令语法1.<操作{<cond>}{S}> <Rd>, <Rn>, <Operand2>2.<操作码> <⽬标寄存器Rd> <第⼀操作寄存器Rn> <第⼆操作数Operand2>3.;第⼀个位置必须是寄存器,第⼆操作数可以是寄存器,也可以是⽴即数数据传送指令 MOV1.mov r1, #0x1 ;r1 = 0x1 0x1 是⽴即数2.mov r2, r1 ;r2 = r13.mvn r3, r2 ;r3 = ~r24.mov r1, 0xffffff00 ;0xffffff00 不是⽴即数,只是编译器在编译阶段对其进⾏了替换5.mvn r1, 0x000000ff ;替换的指令6.7.;⼀条数据传送指令 mov reg, #n mov reg占⽤ bit[31:12],bit[11:0]留给⽴即数使⽤,因此⽴即数⾃包含2^12个8.;⼀个⽴即数由 bits[8:0]循环右移 2 * bits[11:9]得到。
(⼀个⼋位的数循环右移偶数次得到)9.;⽴即数的本质是包含于指令中的数,占⽤指令本⾝的空间加法指令 ADD1.;加法指令执⾏时,若没有进位 CPSR 'C' 位置 02.mov r0, #13.mov r1, #14.add r2, r1, r0 ;r2 = r1 + r05.add r2, r1, #2 ;r2 = r1 + 2数据操作对CPSR的影响;默认情况下,数据处理指令不影响条件码标志位,但可以选择通过添加“S”来影响标志位。
(转)ARM汇编学习笔记——MRS和MSR指令MRS,状态寄存器传送⾄通⽤寄存器类指令功能:将状态寄存器的内容传送⾄通⽤寄存器。
格式:MRS{<条件码>}Rd,CPSR}SPSR其中:Rd ⽬标寄存器,Rd不允许R15。
R=0 将CPSR中的内容传送⽬的寄存器。
R=1 将SPSR中的内容传送⾄⽬的寄存器。
注释:MRS与MSR配合使⽤,作为更新PSR的读-修改-写序列的⼀部分。
例如:改变处理器或清除标志Q。
注意:当处理器在⽤户模式或系统模式下,⼀定不能试图访问SPSR这条指令不影响条件码标志。
例:MRS R0,CRSR ;将CPSR中的内容传送⾄R0MRS R3,SPSR ;将SPSR中的内容传送⾄R3MSR,通⽤寄存器传送⾄状态寄存器传送指令功能:将通⽤寄存器的内容传送⾄状态寄存器。
格式:MSR{<条件码>CPSR_f|SPSR_f,<#immed_8r>MSR{<条件码>CPSR_<field>|SPSR_<field>,Rm其中:<field>字段可以是以下之⼀或多种:(位从右到左)C:控制域屏蔽字段(PSR中的第0位到第7位);X:扩展域屏蔽字段(PSR中的第8位到第15位);S:状态域屏蔽字段(PSR中的第16位到第32位);F:标志域屏蔽字段(PSR中的第24位到第31位)。
immed_8r 值数字常量的表达式。
常量必须对应8位位图。
该位图在32位字中循环移位偶数数位。
Rm 源寄存器。
注释:同前⼀条指令(MRS)。
例1:设置N、Z、C、V标志。
MSR CPSR_f,#&f0000000 ;仅⾼位有效,其他必须为0例2:仅置位C标志,保留N、Z、V标志。
MRS R0,CPSR ;将CPSR中的内容传送⾄R0ORR R0,R0,#&1f ;置位R0的第29位MSR CPSR_c,R0 ;再将R0中的内容传送⾄CPSR例⼦:设置cpu⼯作在超级保护模式(SVC32)@set the cpu to SVC32 modemrs r0,cpsr@把CPSR内容存⼊r0.使⽤了mrs指令:专⽤寄存器到通过寄存器的存取.@CPSR当前程序状态寄存器格式如下:@ 31 30 29 28 27 26 25 24 ~ ~ ~ 8 7 6 5 4 3 2 1 0@ ___ ___ ___ ___ ___ ___ ___ ___ _ _ _ _ ___ ___ ___ ____ ____ ____ ____ ____@| N | Z | C | V | * | * | * | * | * * * | I | F | T | M4 | M3 | M2 | M1 | M0 |@bic r0,r0,#0x1f@bic指令(bit clear): r0:= r0 and (not op2).上边的指令⽬的是把bit0~bit4清零.orr r0,r0,#0xd3@r0:= r0 or 0xd3 . 以上三条指令执⾏后r0值为:**** **** **** **** **** ***** 11*1 0011msr cpsr,r0@把r0存于cpsr.注意:msr指令是专⽤的通⽤寄存器到特殊功能寄存器的指令与mrs对应说明:通过上边的指令可以看到,实现了两个功能.1,disable 外部中断(IRQ)与快速中断(FIR).2,把系统设为SVC32状态(超级保护)即M4~M1=10011。
阅读反汇编后的汇编程序挺麻烦,尤其是在c语言程序的子函数参数中有数组参数,同时当子函数里有循环操作时,反汇编后的代码中频繁出现ptr指令操作。
该指令的用法十分灵活,有时候读入(或写入)的是某内存地址,有时候读入(写入)的是某内存地址中存储的值,初学时总感觉很迷惑,分不清什么时候读内存地址,什么时候读内存地址中值,参考相关文献和书籍后作如下总结。
例如一段简单的C语言程序:int mywork(int a[9], int b[9], int c[9]){int i;for ( i=0; i<9; i++)c[i] =a[i] +b[i];}这段代码debug版反汇编后代码很简单,但是里面有许多小细节值得推敲。
int mywork(int a[9], int b[9], int c[9]) ;原c代码… … ;这里为开始调用函数时当前寄存器数据保存for ( i = 0 ; i < 9 ; i ++)mov dword ptr [i], 0;这里为i初始化,值为0jmp mywork+xx1h ;进入循环体内部mov eax, dword ptr [i];add eax, 1mov dword ptr [i], eaxmywork+xx1h:cmp dword ptr [i], 9jge mywork+xx2h ;如果i等于或大于9,跳出循环c[i] =a[i] +b[i];mov eax, dowrd ptr [i] ;读入参数imov ecx, dword ptr [a] ;这里是读入参数数组a的首地址mov edx, dword ptr [b] ;这里是读入参数数组b的首地址mov eax, dword ptr [ecx + eax*4] ;读入aadd eax, dword ptr [edx +eax*4] ; eax = a[i]+b[i]mov edi, dword ptr [c] ;这里是读入参数数组c的首地址mov dword ptr [edi+ eax*4], eax ;这里保存计算结果,c[i]= a[i]+b[i]inc eaxjmp mywork+xx1hmywork+xx2h: … … ;一些数据恢复操作,主要是出栈等ret文中用红色标记处两处涉及ptr指令的地方。
汇编学习笔记——DOS及DEBUG介绍⼀、课程简介声明:该课程基于《汇编语⾔(第2版)》郑晓薇编著,机械⼯业出版社。
本节实验取⾃教材中第⼆章的《实例⼆进⼊计算机》。
实验环境:1.DOS 环境实验环境中安装有dosemu可以模拟DOS环境,并提供DEBUG、MASM、LINK等汇编语⾔开发程序。
2.进⼊DOS和DEBUG在桌⾯上双击dosemu图标,直接进⼊DOS。
再做如下操作:C:\〉D: ——回车后进⼊D盘D:\〉CD DOS ——进⼊DOS⼦⽬录D:\dos〉DIR ——列出⽬录中的⽂件D:\dos〉DEBUG ——进⼊DEBUG⼆、进⼊计算机微型计算机的字长与微处理器的寄存器位数有关。
以Intel 80X86系列微处理器为例:CPU是8086/8088、80286的字长是16位(⼆进制位bit),那么它们的寄存器的位数⼀定是16位的;32位字长的微机CPU是80386/80486或者Pentium系列,它们的寄存器的位数则是32位的。
在汇编语⾔中,数值后⾯分别⽤字母B、H、D代表⼆进制(Binary)、⼗六进制(Hexadecimal)、⼗进制数(Decimal)(⼗进制数可以省略D)。
在计算机中还规定采⽤字节、字、双字等单位来表⽰数据。
字节(Byte):8位⼆进制数。
如00000101B,或表⽰成05H;10000101B,或表⽰成85H。
字(Word):16位⼆进制数,等于2字节。
如1100010111010110B,或表⽰成C5D6H。
双字(Double Word):32位⼆进制数,⼜称为双精度数,等于4字节。
如23456789H。
2.1 8086寄存器组8086寄存器都是16位的寄存器,根据⽤途可分为4种类型。
分别是数据寄存器、地址寄存器、段寄存器和控制寄存器。
如图所⽰:img数据寄存器中每个寄存器⼜可以分为2个8位的寄存器:AH、AL,BH、BL,CH、CL,DH、DL。
H表⽰⾼字节(⾼8位)寄存器、L表⽰低字节(低8位)寄存器。
数据处理指令1.数据传送(MOV MVN)2.算术运算(ADD ADC SUB SBC RSB RSC)3.位运算(AND ORR EOR BIC)4.比较测试(CMP CMN TST TEQ)操作码{条件码}S 目标寄存器,第一源操作数,第二源操作数1.数据传送指令无第一源操作数2.比较测试指令无目标寄存器3.比较测试指令不加S,结果影响NZCV4.第一源操作数是寄存器5.第二源操作数有:8位图立即数,寄存器,寄存器移位(LSL,LSR,ASR,ROR,RRX)6.S:1.目标寄存器为PC,CPSR=SPSR2.目标寄存器不为PC,结果影响NZCV7.加法,C进位,有进位,C=1,无进位,C=08.减法,C借位,有借位,C=0,无借位,C=11-10累加和arm-linux-as -g -o sum.o sum.s arm-linux-ld -e _start -o sum sum.oqemu-arm -g 1234 sumarm-linux-gdb sum最大公约数的求解20=5X412=3X4= 2X4R0=20R1=12R0==R1?20!=12R0=R0-R1=20-12=8R1=R1-R0=12-8=4R0=R0-R1=8-4=4while(R0 != R1){if(R0 >= R1){R0 = R0 – R1;}else{R1 = R1 – R0;}}跳转指令数据处理指令(传送,加法,减法,位运算,比较测试)mov r1, #0x56从存储器中获得,怎么办?加载指令:将数据从存储器中读到寄存器存储指令:将处理完毕的数据(寄存器)存储回存储器实现了寄存器与存储器之间的数据交互单寄存器多寄存器单寄存器字和无符号字节的加载,存储指令单寄存器的字加载指令LDR{cond} Rd, <地址模式> 功能:将指定地址单元<地址模式>的字数据读入Rd中。
单寄存器的无符号字节加载指令LDR{cond}B Rd, <地址模式> 功能:将指定<地址模式>地址单元中的字节数据读入Rd中,字节数据放在Rd的低8位,高24bit用0填充<地址模式>:数据来源Rd:目标寄存器示例LDR R1, [R2]R2=0x20008000R1是0x20008000地址中的数据LDR PC, [R0, #8]LDRB R1, [R2], #1R2=0x20008000 0x56R1=0x56R2=R2+1=0x20008001LDR R1, [PC, R3]LDR R1,[R2, R3, LSL #2]LDREQB R1,[R2, R3]LDR R0, [R0, #8]! @×基址与目标寄存器不一样单寄存器字和无符号字节存储指令语法格式STR{cond} Rd, <地址模式>功能:将Rd寄存器的字数据存储到由<地址模式>指定的地址中STR{<cond>}B Rd, <地址模式>功能:将寄存器中一个字节数据保存到<地址模式>指定的地址中Rd:源寄存器<地址模式>:数据需要存储到的目标地址示例STR R1, [R2]STR R1, [R2], #1STR R1, [R2, R3]STRB R0, [R1, R2, ASR #2]STREQB R0, [R1, R2, LSL #2]STR PC, [R0, #8] [PC, #8] 单元内容STR R0, [R0, #8]! @×1 .零偏移LDR R0, [R1] //将R1指定的地址中的数据加载到R0R0=0xe92d48002. [<Rn>, #+/-<offset_12>] 偏移量为立即数(12bit)LDR R0, [R1,#0x8] ;R0<-[R1+0 x8]LDR R0, [R1, #-0x20] ; R0<- [R1 –0x20]R0=0xe59f30603. [<Rn>, +/-<Rm>] 偏移量为寄存器LDR R0,[R1, R2] ;R0<-[R1+R 2]LDRR0,[R1,-R2] ;R0 <-[R1-R2]4. [<Rn>, +/-<Rm>, <shift> #<shift_imm>] 偏移量为寄存器移位LDR R0,[R1 ,R2,LSL#2] ;R0<-[R1+R2*4]5. [<Rn>, #+/-<offset_12>]!LDR R0,[R1, #0x8]! ;R0<-[R1+0x8] R1=R1+81.先加载数据2.改变基址6. [<Rn>, +/-<Rm>]!LDRR0,[R1,R2] ! ;R0<-[R1+R2] R1=R1+R27. [<Rn>, +/-<Rm>, <shift> #<shift_imm>]!LDR R0,[R1,R2,LSL #2] !;R0<-[R 1+R2*4] R1=R1+R2*48. [<Rn>], #+/-<offset_12>LDR R0, [R1], #0x20 ;R0=<-[R1] R1=R1+0x201.现将基址指定的数据加载到R02.改变基址9. [<Rn>], +/-<Rm>LDR R0, [R1], R2 ;R0=<-[R1] R1=R1+R210. [<Rn>], +/-<Rm>, <shift> #<shift_imm>LDR R0, [R1], R2, LSL #2;R0=<-[R1] R1=R1+R2*4地址模式:10:1.无偏移量,将指定基址的数据加载到寄存器,基址不变2.将基址+偏移量指定地址的数据加载到寄存器,基址不变1.立即数2.寄存器3.寄存器移位3.将基址+偏移量指定地址的数据加载到寄存器,基址=基址+偏移量1.立即数2.寄存器3.寄存器移位4.将基址表示的加载到寄存器,基址=基址+偏移量1.立即数2.寄存器3.寄存器移位单寄存器字和无符号字节的加载,存储指令单寄存器半字和有符号字节的加载,存储指令加载指令语法格式LDR{cond}H Rd, <地址模式> 功能:Rd<- <地址模式>,高16bit 用0填充LDR{cond}SH Rd, <地址模式> 功能:Rd<- <地址模式>,高16bit 用符号位填充LDR{cond}SB Rd, <地址模式> 功能:Rd<- <地址模式>,高24bit 用符号位填充使用示例LDRH R1, [R0]R0=0x20008000R1=0x4800LDRSH R8, [R3, #2] LDREQH R12, [R13, #-6] LDRSB R7, [R6, #-1]!LDRH R3, [R9], #2LDRSB R1, [R2], R3LDRH PC, [R0] @×LDRH R0, [R0], #4 @×LDRSB PC, [R0]@×LDRSB R0, [R0], #4 @×不要以PC作为目标寄存器用在加载半字和字节的加载指令中在基址要发生变化的指令中,基址寄存器和目标寄存器不要相同的语法格式STR{cond}H Rd,<地址模式>使用示例STRH R1, [R0]STRH R8, [R3, #2] STREQH R12, [R13, #-6] STRH R7, [R6, #-2]!STRH R3, [R9], #2STRH R1, [R2], R3STRH PC, [R0] @×STRH R0, [R0], #4 @×STRH R7, [R6, #-1] @ ?半字读写时,指定的地址必须半字对齐,地址整除2基址+偏移量偏移量:立即数(由8bit来表示),寄存器1 .零偏移LDRSH R0, [R1]R0<-[R1]的低16bit R0的高16bit用符号位填充2. [<Rn>, #+/-<offset_8>] LDRH R0, [R1, #0x04]3. [<Rn>, +/-<Rm>]LDRSB R0, [R1, R2]4. [<Rn>, #+/-<offset_8>]! LDRH R0, [R1, #0x08]!5. [<Rn>, +/-<Rm>]!LDRSB R0, [R1, R2]!6. [<Rn>], #+/-<offset_8> LDRSH R0, [R1], #0x47. [<Rn>], +/-<Rm> LDRSH R0, [R1], R2单寄存器字和无符号字节存储加载指令地址模式:基址+偏移量立即数(12bit)寄存器寄存器移位单寄存器半字和有符号字节存储加载指令地址模式:基址+偏移量立即数(8bit)寄存器多寄存器存储加载指令多寄存器加载指令LDMLDM{cond}{addressing_mode} Rb{!}, < Reglist >{^}功能:将Rb基址中数据加载到Reglist表示的寄存器列表中LDMIA / STMIA 后增加LDMIB / STMIB 先增加LDMDA / STMDA 后减小LDMDB / STMDB 先减小多寄存器存储指令STMSTM{cond} {addressing_mode} Rb{!}, < Reglist >{^}cond : 条件域addressing_modeLDMIA / STMIA Increment After(先操作,后增加)LDMIB / STMIB Increment Before(先增加,后操作)LDMDA / STMDA Decrement After (先操作,后递减)LDMDB / STMDB Decrement Before (先递减,后操作)Rb : 基址寄存器! : 更新基址寄存器Reglist: 源/目标寄存器列表(可以是16个寄存器的任何子集)^ : 1.寄存器列表中没有PC寄存器:特权模式下使用用户模式下的寄存器2.寄存器列表中有PC寄存器,CPSR=SPSR,异常返回R10:基址寄存器{R0,R1,R4}:源操作的寄存器STMDA R10!,{R0,R1,R4}LDMIA R10,{R0,R1,R4}R0=0x20008000 IB地址先增加,然后再加载数据[0x20008000]=1[0x20008004]=2[0x20008008]=3[0x2000800C]=4[0x20008010]=5LDMIB R0! , {R1,R2,R3,R4}R1=2R2=3R3=4R4=5R0=0x20008010R0=0x20008000 IA地址后增加,先加载数据[0x20008000]=1[0x20008004]=2[0x20008008]=3[0x2000800C]=4[0x20008010]=5LDMIA R0!, {R1, R2, R3,R4}R1=1R2=2R3=3R4=4R0=0x20008010LDMIA R0!, {R1-R3} LDMIB R0, {R1-R3, R7}^ @ x usr/sysLDMDB SP!, {R1-R3, PC}^ @ x usr/sysLDMDB R0, {R0-R2} LDMDA R15, {R1} @xLDMDB R0!, {R0-R2} @x Rn值LDM{cond}{addressing_mode} Rb{!}, < Reglist >{^}功能:将Rb基址中数据加载到Reglist表示的寄存器列表中多寄存器存储指令STMSTM{cond} {addressing_mode}Rb{!}, < Reglist >{^}IA 先存储或加载数据,地址后增加IB 地址先增加,后存储或加载数据DA 先存储或加载数据,地址后减小DB 地址先减小,后存储或加载数据多寄存器存储加载,只操作字数据大编号寄存器存放在高地址,小编号寄存器存放在低地址!:基址要更新^:1.寄存器列表中包括PC,CPSR=SPSR(异常模式下使用)2.寄存器列表中不包括PC,特权模式下使用用户模式寄存器PC不做为基址寄存器若要更新基址,基址和目标寄存器不使用相同的寄存器STMIA R0!, {R1-R3} STMIA SP!, {R1-R3, LR} STMIB R0, {R1-R3, R9}^ @x usr/sys STMDB R0, {R0-R2} STMDB R0!, {R0-R2}STMDA R15, {R1} @ x栈的种类:Descending stacks (减栈)栈向内存地址减小的方向变化Ascending stacks (加栈)栈向内存地址增加的方向变化Full stacks (满栈)栈指针指向的栈顶保存有效元素Empty stacks (空栈)栈指针指向的栈顶未保存有效元素综合以上两种特点,有以下4种栈FD(Full Descending)满减栈ED(Empty Descending)空间栈FA(Full Ascending)满加栈EA(Empty Ascending)空加栈STMFD (Push) [多寄存器存储- STMDB]LDMFD (Pop) [多寄存器加载- LDMIA]STMDB 入栈LDMIA 出栈…….MOV R0, #0MOV R1,#1BL loop CPU自动将ADD指令地址存放LRADD R3,R4loop:STMFD sp!, {r4-r7, lr}SUB R4, #1…..LDMFD sp!, {r4-r7, pc}STMFD(STMDB\Push):入栈根据满减栈原则,先减地址,后入栈,高地址存大编号寄存器的原则,依次入栈,栈顶指针永远指向有效元素。