当前位置: 首页 > news >正文

扫描网站特征dede瑞安市规划建设局网站

扫描网站特征dede,瑞安市规划建设局网站,宁国网站建设,邢台同城交友ARM汇编指令 学习arm汇编的主要目的是为了编写arm启动代码#xff0c;启动代码启动以后#xff0c;引导程序到c语言环境下运行。换句话说启动代码的目的是为了在处理器复位以后搭建c语言最基本的需求。因此启动代码的主要任务有#xff1a; 初始化异常向量表#xff1b;初…ARM汇编指令 学习arm汇编的主要目的是为了编写arm启动代码启动代码启动以后引导程序到c语言环境下运行。换句话说启动代码的目的是为了在处理器复位以后搭建c语言最基本的需求。因此启动代码的主要任务有 初始化异常向量表初始化各工作模式的栈指针寄存器开启arm内核中断允许将工作模式设置为user模式完成上述工作后引导程序进入c语言主函数执行 因此汇编指令的学习主要是围绕这几个目的展开主要学习跟上述目的相关的指令。 mov指令加载12位立即数到寄存器或转移一个寄存器的值到另外一个寄存器 mov r0, #2 ;加载立即数2到寄存器r0MOV{S}c Rd, #const mov r1, r0 ;将r0寄存器的值加载到r1MOV{S}c Rd, Rm 大多数指令的格式为opcode rd, rn rm,其中rd是目标寄存器rn是第一操作数寄存器。同理add指令常用的两种方式 ADD{S}c Rd, Rn, #const ADDS}c Rd, Rn, Rm{, shift} 类似的还有 sub指令 SUB{S}c Rd, Rn, #const SUB{S}c Rd, Rn, Rm{, shift} 以上四条指令都有立即数作为第二操作数的情况那么是什么立即数呢准确的说这里所指的是12位立即数imm12。先说怎么判断某数是不是12位立即数12位立即数的条件是 如果某个数的数值范围是0~255之间那么这个数一定是立即数把某个数展开成2进制这个数的最高位1至最低位1之间的二进制数序列的位数不能超过8位这个数的二进制序列的右边必须为偶数个连续的 0 例如0x234 0000 0000 0000 0000 0000 0010 0011 0100 最高位1至最低位1之间的二进制数序列1000 1101没有超过8位 末尾1的右边有2个0所以0x234是立即数 0x3f4 0000 0000 0000 0000 0000 0011 1111 0100 最高位1至最低位1之间的二进制数序列1111 1101 从第一个1开始到最后一个1之间没有超过8位 末尾1的右边有2个0所以0x3f4是立即数 0x132 0000 0000 0000 0000 0000 0001 0011 0010 最高位1至最低位1之间的二进制数序列1001 1001 从第一个1开始到最后一个1之间没有超过8位 末尾1的右边有1个0不满足第二条所以0x132不是立即数 0x7f8 0000 0000 0000 0000 0000 0111 1111 1000 最高位1至最低位1之间的二进制数序列1111 1111从第一个1开始到最后一个1之间没有超过8位 末尾1的右边有3个0不满足第二条所以0x7f8不是立即数 0xfab4 0000 0000 0000 0000 1111 1010 1011 0100 最高位1至最低位1之间的二进制数序列0011 1110 1010 1101 从第一个1开始到最后一个1之间超过8位不满足条件1所以这个数不是立即数 这是因为ARM中将这 12bits 分为 8bit 常数0~255和 4bit 循环右移位值0~15 8bit 常数范围0255位移的步进值是以2为单位即实际位移 2 * rotate 位可以表示循环有以030偶数位 0、2、4、6、8、10、12、14、16、18、20、22、24、26、28、30。在实际存储这个数值的时候要想办法把这个数压缩到这12位中去。压缩的方法就是找一个数这个数必须是一个8bit数之后循环右移2 * rotate位。如果能找打这个数那么待保存的数就是立即数否则就不是。 那么如果我们就是希望把一个非立即数存进rn,又该怎么做呢 ldr寄存器加载指令 LDR{c}{q} Rt, label ;如ldr r0, 0x2FAB4 ldr指令多用于从ram中将一个32位的字数据传送到目的寄存器中 LDRc Rt, [Rn{, #/-imm12}] 如 LDR   R0[R18]             将内存地址为R18的字数据读入寄存器R0这里的#8作为12位立即数是可以省略的 LDRc Rt, [Rn], #/-imm12 如 ldr r0, [r1], #8 ;将内存地址R1的字数据读入r0,之后r18 LDRc Rt, [Rn, #/-imm12]! 如 LDR   R0[R18]           将存储器地址为R18的字数据读入寄存器R0并将新地址R18写入R1。 bic指定位清零指令 BIC{S}c Rd, Rn, #const将rn中的字数据const为1的比特清零把结果放入rd orr指定位置位置1指令 ORR{S}c Rd, Rn, #const 汇编指令的s后缀几乎所有的汇编指令都可以在指令后面加上s后缀s后缀的含义是在指令执行过程中会更新cpsr寄存器的N,V,C,Z位 N在结果是有符号的二进制补码情况下如果结果为负数则N1如果结果为非负数则N0 Z如果结果为0则Z1;如果结果为非零否则Z0 C无符号溢出是针对无符号数最高有效位向更高位进位时C1减法中运算结果的最高有效位从更高位借位时C0 V有符号溢出该位是针对有符号数的操作会在下面两种情形变为1两个最高有效位均为0的数相加得到的结果最高有效位为1两个最高有效位均为1的数相加得到的结果最高有效位为0除了这两种情况以外V位为0 例如 mov r0, #0xFFFFFFFF adds r1, r0, #1 上面的操作会导致ZC置位这是因为结果为0并且从无符号数角度来看已经从最高位向更高位进位了 而 mov r0. #0x7FFFFFFF adds r1, r0, #1 会造成N位和C位置位这是因为计算结果0x80000000最为位为1代表负数并且 从有符号角度来看把一个整数加成了负数。 更新N,V,C,Z位有什么用呢几乎所有的arm指令都可以在指令之后可选地增加执行条件 例如movcs r0, #100;表示只有在C位置位的情况下才能把100加载入r0这样的话就可以非常方便地实现指令的有条件执行。 例如实现两个unsigned long long类型变量的求和 unsigned long long l1 0x00000000FFFFFFFF; unsigned long long l2 0x000000000000003; 很明显结果为0x0000000100000002 我们用r0装l1的高4字节r1装l1的低四字节 用r2装l2的高4字节r3装l2的低四字节 用r4装结果的高4字节r5装结果的低四字节 第6~7行装入被加数 第8~9行装入加数 第10~11行清空装结果的变量 第12行先加低四字节这里因为考虑到进位问题所以要更新N,V,C,Z位 第13行之前的进位导致更高位数据的丢失必须把这一位补回来要不要补就看之前时候进位进位标志是cs 练习从r0, r1代表的两个有符号数中找到较大值放入r2寄存器 CMP比较指令用于比较两个寄存器的值或者比较一个寄存器和立即数的值其原理是对待比较的两个数求差看结果是否为0这个指令会无条件修改N,V,C,Z位。 如 mov r0, #100 cmp r0, #100 会导致Z置位从条件码表可知只要Z置位就是两数相等。 跳转指令b b指令类似c语言的goto语句能够实现无条件跳转。跳转时需要一个lable表示要跳转到什么地方去 配合之前的条件码就可以实现一些较为复杂的操作例如实现从0加到100的和 这就是循环实现的机制 事实上程序跳转工作更多的是为了实现类似函数的功能此时lable就是函数的函数名其实lable本身代表的就是待跳转那一行指令的地址b指令本质上就是把待跳转那行的地址装入pc寄存器但是函数在调用完毕之后要回到调用处的下一行指令处执行为了能够回到调用的下一行需要使用bl指令。bl和b之间的区别就在于bl会在lr寄存器中保存回来的地址。如 以上代码虽然实现了函数调用的程序流程但是还存在两个问题一是调用完毕以后r0, r1寄存器的值被max_of_two_numbers函数修改了二是如果出现了函数的嵌套调用那么lr寄存器的值就会被修改而无法回到最开始的地方。要解决这个问题就必须在每次函数调用前保护现场在函数调用完毕以后恢复现场。而实现这个功能就需要使用栈这个数据结构。 栈的实现类型 2440实现保护和恢复现场使用的栈是数组栈即用一段连续的内存空间为栈提供空间。从数组栈的具体实现来看入栈的方式有四种做法 空增先写入数据再让栈指针自增空减先写入数据再让栈指针自减满增先让栈指针自增再写入数据满减先让栈指针自减再写入数据。 arm体系采用的方案是满减但是在进行操作之前我们必须告诉2440栈底的位置这里我们把栈底设置为0x40001000从地址0x40000000开始的0x1000这段内存空间对应的是2440内部的一段ram总共4k。实际能够使用的内存空间为[0x40000000~0x40000FFF]设置栈底指针寄存器: ldr sp 0x40001000 入栈保护指令stmfd(STMDB) STMFDc Rn{!}, registers 其中Rn表示栈底指针寄存器 registers 表示需要入栈保护的寄存器!表示入栈之后sp自动自减。如 stmfd sp!, {r0, r1, r2, r3-r12, lr} 出栈恢复指令ldmfd(LDM/LDMIA/) LDMFDc Rn{!}, registers 中Rn表示栈底指针寄存器 registers 表示需要入栈保护的寄存器!表示出栈之后sp自动自增。如 ldmfd sp!, {r0, r1, r2, r3-r12, lr} 在汇编中调用c语言编写的函数 设有c语言定义的函数void func_c(void);在汇编代码中调用该函数只需用import声明函数名即可之后就可以使用bl指令调用该函数注意既然是调函数就一定要保护现场 向c函数传参 向c函数传参的方法很简单如果参数个数小于等于4个就直接用r0~r3传参c函数返回值通过r0寄存器返回 设有c函数 int add_c(int a, int b, int c, int d) { return a b c d; } 如果参数个数大于4个从第五个参数开始就需要通过栈来传参 在c语言中调用汇编编写的函数类似不过在汇编中用export声明函数同时需要在c语言中用extern声明函数按照标准调用者负责保护现场和恢复现场 传参方法于此类似 切换arm内核的工作模式 切换工作方式的思路很简单由于内核的工作模式是由cpsr寄存器的低5位来设置的那么就可以先把cpsr读出来更改低5位之后再设置进去。这里读取cpsr使用mrs指令写cpsr寄存器用msr指令需要注意的是在keil环境下写cpsr需要写成   msr cpsr_c r0将r0的值写入到cpsr寄存器 学习了这些指令最终就可以编写我们自己的启动代码了 preserve8 area reset, code, readonly code32 entry b start nop nop nop nop nop b do_interrput nop start ldr sp, 0x40001000 mrs r0, cpsr bic r0, r0, #0x1F orr r0, r0, #0x12 bic r0, r0, #(0x01 7) msr cpsr_c, r0 ldr sp, 0x40001000 sub sp, sp, #1024 mrs r0, cpsr bic r0, r0, #0x1F orr r0, r0, #0x10 msr cpsr_c, r0 ldr sp, 0x40001000 sub sp, sp, #2048 import main b main do_interrput sub lr, lr, #4 stmfd sp!, {r0-r12, lr} import interrupt_handle bl interrupt_handle ldmfd sp!, {r0-r12, pc}^ end 代码 1. start.s preserve8area reset, code, readonlycode32entry;ldr r0, 0x40000fff;装立即数; mov r0, #0xffffffff ; bic r0, r0, #1;将最后一位清零 ; bic r0, r0, #(1 5);将第5位清零 ; bic r0, r0, #(1 7);将第7位清零; mov r0, #0x0 ; orr r0, r0, #1;将最后一位置1 ; orr r0, r0, #(1 5);将第5位置1 ; orr r0, r0, #(1 7);将第7位置1; mov r0, #10 ;两个数比较大小 ; mov r1, #20 ; cmp r0, r1 ; movge r2, r0 ;大的给r2 ; movle r2, r1 ;小的给r2; mov r0, #10 ;三个数比较大小 ; mov r1, #20 ; mov r2, #30 ; cmp r0, r1 ; movge r3, r0 ; movle r3, r1; cmp r3, r2 ; movle r3, r2 ; mov r0, #1;对无符号longlong进行相加操作判断溢出 ; mov r1, #0 ; mov r2, #0xffffffff ; mov r3, #0 ; ; adds r4, r0, r2 ; mov r5, #0 ; addcs r5, #1;cs为判断低四字节是否溢出; mov r0, #1;实现b ; mov r1, #0 ; b foo ; mov r2, #0xffffffff ; mov r3, #0 ;foo ; adds r4, r0, r2 add后加s影响CPSR寄存器中的NZCV位之后指令可加不同的条件分支 ; mov r5, #0 ; addcs r5, #1;cs为判断低四字节是否溢出 ; mov r0, #0x10;两个数字比大小 ; mov r1, #0x20 ; cmp r0, r1 ; bge great ; ble less; ;great ; mov r2, r0 ; b finished ;less ; mov r2, r1; mov r0, #0x10 ;判断三个数的最大值 ; mov r1, #0x20 ; mov r2, #0x30; ; cmp r0, r1 ; bge tmpgreat ; ble tmpless ;tmpgreat ; mov r3, r0 ; b continue ;tmpless ; mov r3, r1;continue ; cmp r3, r2 ; bge finished ; mov r3, r2; mov r0, #0 ;1到100求和 ; mov r1, #0; ;loop ; cmp r1, #100 ; bgt finished ; add r0, r0, r1 ; add r1, #1 ; b loop; ldr sp, 0x40001000;初始化满减栈 ; mov r0, #0 ; mov r1, #0 ; stmfd sp!, {r0-r12};保存现场入栈保护防止数据被修改 ; bl foo ;bl会在b指令跳转时将下一行要执行指令的地址放入lr ; ldmfd sp!, {r0-r12}; 恢复现场出栈; ;loop ; cmp r1, #100 ; bgt finished ; add r0, r0, r1 ; add r1, #1 ; b loop ; ;foo ; mov r0, #1 ; mov r1, #2 ; add r2, r0, r1 ; bx lr ;(跳转回原函数)mov pc, lr; ldr sp, 0x40001000 ;入栈保护嵌套调用汇编函数 ; mov r0, #1 ; mov r1, #2 ; stmfd sp!, {r0-r12, lr} ; bl max_of_two_numbers ; ldmfd sp!, {r0-r12, lr}; ;foo ; mov r0, #1 ; mov r1, #2 ; add r2, r0, r1 ; bx lr ;(跳转回原函数)mov pc, lr; ;max_of_two_numbers; mov r0, #3 ; mov r1, #4 ; stmfd sp!, {r0-r12, lr};不加lr第二次lr会将第一次lr的值覆盖 ; bl foo ; ldmfd sp!, {r0-r12, lr} ; cmp r0, r1 ; movge r2, r0 ; movle r2, r1 ; bx lr; mov r0, #1 ; mov r1, #2 ; mov r2, #3 ; stmfd sp!, {r0-r12, lr} ;汇编start.s调用main.c中的c语言函数,传参利用r0、r1、r2、r3传参 ; import add_c 汇编调c中函数用import声明c中的函数c中调汇编函数在汇编中用export声明汇编的函数 ; bl add_c ; ldmfd sp!, {r0-r12, lr} ; mov r0, #1 ;编写函数实现求三个数中的最大值 ; mov r1, #2 汇编给c中函数传参用r0-r3其他的通过入栈出栈传参返回值r0 ; mov r2, #3 ; stmfd sp!, {r0-r12, lr} ;汇编start.s调用main.c中的c语言函数,传参利用r0、r1、r2、r3传参 ; import max_of_three_numbers 调用函数时要入栈保护保护现场恢复现场 ; bl max_of_three_numbers ; ldmfd sp!, {r0-r12, lr} ; mov r0, #1 ;编写函数实现传参五个数进入main.c ; mov r1, #2 ; mov r2, #3 ; mov r3, #4 ; mov r4, #5; ; stmfd sp!, {r0-r12, lr} ;汇编start.s调用main.c中的c语言函数,传参利用r0、r1、r2、r3传参 ; import access_five_numbers ;汇编调c语言函数用import ; stmfd sp!, {r4} ; bl access_five_numbers ; ldmfd sp!, {r4} ; ldmfd sp!, {r0-r12, lr} ; ldr sp, 0x40001000;初始化满减栈 ; import main ; export foo ; b main; ;foo ; add r0, r0, r1 ; bx lr ;(跳转回原函数)mov pc, lr; ldr sp, 0x40001000 ; import main ; export sum_c ; b main; ;sum_c ; mov r2, r0 ;1到100求和 ; mov r1, #0 ; mov r0, #0; ;loop ; cmp r1, r2 ; bxgt lr ; add r0, r0, r1 ; add r1, #1 ; b loopldr pc, startldr pc, undifine_handlerldr pc, swi_handlerldr pc, prefetch_handlerldr pc, abort_handlernopldr pc, IRQ_handler ldr pc, FIQ_handlerundifine_handlerb undifine_handlerswi_handlerimport swi_functionstmfd sp!, {r0-r12, lr}ldr r0, [lr, #-4] ;取到swi中的值当执行到swi这一行时 pc指向swi的下一行lr放着swi下一行高四个字节的地址bic r0, r0, #0xff000000 ;取swi中的0x80给到swi——function函数进行传参bl swi_functionldmfd sp!, {r0-r12, pc}^ ;^将spsr恢复到cpsr;ldmfd sp!, {r0-r12, lr};bx lrprefetch_handlerb prefetch_handlerabort_handlerb abort_handlerIRQ_handlerb IRQ_handlerFIQ_handlerb FIQ_handlerstartldr sp, 0x40001000;初始化满减栈mrs r0, cpsr ;模式切换msr读取cpsrbic r0, r0, #0x1f;所有低五位清零orr r0, r0, #0x12;置位成IRQ模式10010msr cpsr_c, r0;转换模式为usr 写cpsr设置cpsr写入m域ldr r0, 0x40001000;初始化满减栈sub r0, r0, #1024mov sp, r0mrs r0, cpsrbic r0, r0, #0x1f;所有低五位清零orr r0, r0, #0x10;置位成usr模式10000msr cpsr_c, r0;转换模式为usrldr r0, 0x40001000sub r0, r0, #2048mov sp, r0swi #0x80import mainb mainfinishedb finished;类似于while1end 2. main.c //extern int add_c(int a, int b, int c); //extern int max_of_three_numbers(int a, int b, int c); //extern int access_five_numbers(int a, int b, int c, int d, int e); //extern int foo(int a, int b); //extern int sum_c(int a); //int add_c(int a, int b, int c) //{ // return a b c; //} // //int max_of_three_numbers(int a, int b, int c) //{ // int max a; // max a b ? a : b; // max max c ? max : c; // // return max; //} // //int access_five_numbers(int a, int b, int c, int d, int e) //{ // return a b c d e; //} extern void swi_function(int n);void swi_function(int n) {while (n--){}}int main(void) { // int ret foo(10, 20); // int sum sum_c(100);while (1){}} 1. add(s)c s : 影响CPSR寄存器中的NZCV位之后指令可加不同的条件分支 c :  movge   movgt b bl : 保存下一条指令的地址 bx arm满减栈 函数调用者实现出栈入栈 传参两种方法一样
http://www.zqtcl.cn/news/776568/

相关文章:

  • 网站seo优化步骤动态ip可以做网站
  • 用自己电脑怎么做网站广州公司建站
  • 购物网站前端浮动特效怎么做常用开发工具
  • 网页设计与制作精品课程网站wordpress文章页禁止右键
  • 英迈思做网站做的怎样中国建设银行官方网站纪念币
  • 最专业的手机网站建设厦门建设厅网站
  • 贵州省建设工程质量检测协会网站c 网站开发类似优酷
  • 关于网站建设申请卢沟桥做网站的公司
  • 网站源码对应的数据库怎么做单页成品网站
  • 网站分为哪几类上海人才网官网招
  • 网站建设的常见技术有哪些方面网站联系我们模块怎么做
  • 外贸网站建设专业上海四大设计院是哪四个
  • 太原网站设计排名维启网站建设
  • 电子商务网站建设基本流程图网站建设推广策划
  • 合肥集团网站建设哪个好果洛电子商务网站建设哪家好
  • 顺德高端网站企业建设网站没有服务器
  • .net网站开发模板天津手网站开发
  • 网页设计大赛网站开发重庆最近的新闻大事10条
  • 网站ftp用户名和密码是什么建设单位网站设计
  • 公司请人做的网站打不开网页游戏大厅都有哪些
  • 网投网站制作中国建设教育协会报名网站
  • 做外贸需要做网站吗上海中建建筑设计院有限公司
  • 网站源代码免费下载苏州seo网络优化公司
  • 建网站跟建网店的区别pico笔克品牌介绍
  • 网站设计小技巧西安网站建设网站
  • 做听书网站怎么做网站留言板带后台模板
  • 石家庄网站建设王道下拉棒厦门橄榄网站建设
  • 赤峰网站建设培训建筑资格证书查询官网
  • 共和县公司网站建设seo网络推广招聘
  • 网站怎样做外链百度网站地图提交