Linux中汇编语言的学习(加法、乘法、除法、左移、右移、按位与等多种命令操作实例以及ARM的 N、Z、C、V 标志位的解释)
汇编概述
汇编需要学习的大致框架如下: @ 汇编中的符号 @ 1.指令;能够北嘁肷梢惶?2bit机器码,并且能够被cpui识别和执行 @ 2.伪指令:本身不是指令,编译器可以将其替换成若干条指令 @ 3.伪操作:不会生成指令,只在编译阶段告诉编译器怎么编译 @ ARM指令集 @ 1.数据处理指令:进行数学运算、逻辑运算 @ 2.跳转指令:实现程序的眺转,本质就是修改PC寄存器 @ 3.Load/Score指令:访问(读写)内存 @ 4.状态寄存器传送指令:用于访问(读写)CPSR寄存器 @ 5.软中断指令:触发软中断 @ 6.协处理器指令:协处理器可以处理的指令 .text @表示当前为代码段 .global _start @将_start定义成全局符号 _start: @汇编入口 MOV R1,#1 @汇编指令 stop: @死循环,防止程序跑飞 B stop .end @汇编的结束
汇编数据处理指令
MOV指令的实例操作 @ 1.指令:能够编译生成一条32位的机器码,且能被cpu识别和执行 @ 1.1 数据处理指令:数学运算、逻辑运算 @ 数据搬移指令 @ MOV R1,#1 @ R1 = 1 @ MOV R2,R1 @ R2 = R1 @MVN R0,#0xFF @ R0 = ~0xFF @MOV R0,#0 @MOV R1,#0 @MOV R1,#1 @MVN R0,#0 @ 立即数:编译通过的是立即数,否则不是 @ 立即数的本质就是包含在指令当中的数,属于指令的一部分,变量则是单独占一个空间 @ 立即数的优点 @ 取值的时候就是可以将其读取到CPU,不用单独去内存读取,速度快 @ 立即数的缺点 @ 不能是任意的32的数字,有局限性 @ MOV R0,#0x12345678 @ 因为12345678太大了,所以编译报错,指令本身还有其他数而12345678本身就占了32位 @MOV R0, #0x12 @ MOV R0, #0xFFFFFFFF @ 上述相当于伪指令,执行时替换成等价的CPU能认识的指令 数据运算指令格式操作实例(ADD、SUB等指令) @ 数据运算指令的格式 @ 《操作吗》《目标寄存器》《第一操作寄存器》《第二操作数》 @ 操作码:表示执行哪种操作 @ 目标寄存器:用于存储运算的结果 @ 第一操作寄存器:存储第一个参与运算的数据(只能写寄存器) @ 第二操作数:第二个参与运算的数据(可以是寄存器也可以是立即数) @ 加法指令 @MOV R2,#5 @MOV R3,#3 @ADD R1,R2,R3 @ R1 = R2 + R3 @ADD R1,R2,#5 @ ADD R1,#5 R1这个形式的不行 @ ADD 不能计算两个值,例如:ADD R1,#2,#5,也不能是以下格式:ADD R1 #2,R2 @ 减法指令 @SUB R1,R2,R3 @ R1 = R2 - R3 @SUB R1,R2,#3 @ R1 = R2 - 3 @ 逆向减法指令,针对例如这种格式:R1 = #2 - R2 @RSB R1,R2,#3 @ R1 = 3 - R2 @ 乘法指令 @MUL R1,R2,R3 @ R1 = R2 * R3 @ 乘法必须是两个寄存器相乘 @ 按位与指令 @AND R1,R2,R3 @ R1 = R2 & R3 @ 按位与指令 @ORR R1,R2,R3 @ R1 = R2 | R3 @ 按位异或指令,相同为0,相异则1 @EOR R1,R2,R3 @ R1 = R2 ^ R3 @ 左移指令 @LSL R1,R2,R3 @ R1 = (R2 << R3) @ 右移指令 @LSR R1,R2,R3 @ R1 = (R2 >> R3) @ 位清零指令 MOV R2,#0xFF BIC R1,R2,#0x0F @ 第二操作数中的哪一位为1,则将第一操作寄存器中的哪一位清0,然后将结果放入目标寄存器 @ 数据运算指令的格式扩展 @MOV R1,R2,LSL #1 @ R1 = (R2 << 1) @ 数据运算指令对条件位(N、Z、C、V)的影响 @ 默认情况下数据运算不会对条件位产生影响,当在指令后加后缀“s『罂梢杂跋毂 @ MOV R1,#3 @ SUBS R2,R1,#5 @ 两个64位的数据做加法运算 @ 第一个数的低32位放在R1 @ 第一个数的高32位放在R2 @ 第二个数的低32位放在R3 @ 第二个数的高32位放在R4 @ 第一个数 @ 0x00000001 FFFFFFFF @ 第二个数 @ 0x00000002 00000005 @ MOV R1,#0xFFFFFFFF @ MOV R2,#0x00000001 @ MOV R3,#0x00000005 @ MOV R4,#0x00000002 @ ADC带进位的加法,如果有进位的话C置为1,且ADC实际上为R2 + R4 + C(1) @ ADDS R5,R1,R3 @ ADC R6,R2,R4 @ 第一个数 @ 0x00000002 00000001 @ 第二个数 @ 0x00000001 00000005 MOV R1,#0x00000001 MOV R2,#0x00000002 MOV R3,#0x00000005 MOV R4,#0x00000001 @ SBC本质上是:R2 - R4 -‘!C’,为什么减去取反的C,由于CPSR寄存器减法时,28位上置1 SUBS R5,R1,R3 SBC R6,R2,R4 跳转指令 @ 1.2 跳转指令:实现程序的眺转,本质就是修改了PC寄存器 @ 方式一:直接去修改PC寄存器的值(不建议使用,需要我们自己去计算绝对地址) @ MAIN: @ MOV R1,#1 @ MOV R2,#2 @ MOV R3,#3 @ MOV PC,#0x18 @ MOV R4,#4 @ MOV R5,#5 @ FUNC: @ MOV R6,#6 @ MOV R7,#7 @ MOV R8,#8 @ 方式二:不带返回的跳转指令,本质就是将PC寄存器的值修改成跳转标号下第一条指令的地址,同时将跳转指令下一 条指令的地址存储到LR MAIN: MOV R1,#1 MOV R2,#2 MOV R3,#3 BL FUNC MOV R4,#4 MOV R5,#5 FUNC: @ 必须将LR地址给PC,然后程序就能返回了 MOV R6,#6 MOV R7,#7 MOV R8,#8 MOV PC,LR ARM指令的条件码 @ 比较指令 @ CMP的本质是一条减法指令(SUBS),只是没有将运算的结果存入寄存器 MAIN: MOV R1,#1 MOV R2,#2 CMP R1,R2 @ BEQ本质就是判断R1和R2是否相等,相等的话就跳转,否则就不跳转 @ BEQ FUNC BNE FUNC @ if(NQ)(B FUNC)本质:if(z==0)(B FUNC) MOV R3,#3 MOV R4,#4 MOV R5,#5 FUNC: MOV R6,#6 MOV R7,#7 @ ARM指令集大多数都可以带条件码后缀如下: @MOV R1,#1 @MOV R2,#2 @CMP R1,R2 @MOVGT R3,#3 条件码如下: 条件码的案例代码 @ 练习 @ int R1 = 9; @ int R2 = 15; @START: @ if(R1 == R2) @ STOP(); @ else(R1>R2) @ { @ R1 = R1-R2; @ goto START; @ } @ else @ { @ R2 = R2 - R1; @ goto START; @ } @ 汇编编写 MOV R1,#9 MOV R2,#15 START: CMP R1,R2 BEQ STOP SUBGT R1,R1,R2 SUBGT R2,R2,R1 B START STOP: B STOP 内存读写案例代码: @Load/Srore指令:访问(读写)内存 @ 写内存 @ MOV R1,#0xFF000000 @ MOV R2,#0x40000000 @ STR R1,[R2] @将R1寄存器中的数据存储到R2指向的内存空间 @ 读内存 @ LDR R3,[R2] @ 将内存中R2指向的内存空间的数据读取到R3寄存器 @ MOV R1,#0xFFFFFFFF @ MOV R2,#0x40000000 @ STRB R1,[R2] @ B代表一个字节,往内存存取低一个字节的数据 @ STRH R1,[R2] @ H代表两个字节 @ STR R1,[R2] @ 默认为四个字节 @ LDR指令同样支持以上后缀 ARM指令的寻址方式 @ 寻址方式就是CPU去寻找一个操作数的方式 @ 立即寻址 @ MOV R1,#1 @ ADD R1,R2,#1 @ 寄存器寻址 @ ADD R1,R2,R3 @ 寄存器移位寻址,寄存器先做移位然后再用寄存器 @ MOV R1,R2,LSL #1 @ 寄存器间接寻址,R2作为一个地址间接的去访问内存里面的内容 @ STR R1,[R2] @。。。。 @ 基址加变址寻址 @MOV R1,#0xFFFFFFFF @MOV R2,#0x40000000 @MOV R3,#4 @ STR R1,[R2,R3] @ 将R1寄存器中的数据写入到R2+R3指向的内存空间 @ 将R1寄存器中的数据写入到R2+(R1<<1)指向的内存空间 @ STR R1,[R2,R3,LSL #1] @ 基址加变址寻址的索引方式 @ 前索引 @ MOV R1,#0xFFFFFFFF @ MOV R2,#0x40000000 @ STR R1,[R2,#8] @ 将R1寄存器中的数据写入到R2+8指向的内存空间 @ 后索引 @ MOV R1,#0xFFFFFFFF @ MOV R2,#0x40000000 @ STR R1,[R2],#8 @ 将R1寄存器中的数据写入到R2指向的内存空间,然后R2自增8 @ 自动索引 MOV R1,#0xFFFFFFFF MOV R2,#0x40000000 STR R1,[R2,#8]! @ 将R1寄存器中的数据写入到R2+8指向的内存空间,然后R2自增8
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/269441.html
如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!