专业建站制作,网站备案ip查询系统,网页设计制作网站用什么软件,官网建设银行8种机械键盘轴体对比本人程序员#xff0c;要买一个写代码的键盘#xff0c;请问红轴和茶轴怎么选#xff1f;Android Native 进程启动流程ARM传参#xff0c;R0-R3传递前四个参数1. Thumb 指令集特点Thumb 指令集指令长度#xff1a;16或32#xff0c;16为为主Thumb-16 …8种机械键盘轴体对比本人程序员要买一个写代码的键盘请问红轴和茶轴怎么选Android Native 进程启动流程ARM传参R0-R3传递前四个参数1. Thumb 指令集特点Thumb 指令集指令长度16或3216为为主Thumb-16 大部分只能访问前8个寄存器 R0-R7(少数可以访问R8-R15)Thumb-32 可以访问所有的ARM core 寄存器 R0-R15更小、更加灵活2. ARM指令集特点指令长度32位4字节对齐功能更加完善对比ThumbARM2字节对齐4字节对齐占用空间少、密度高占用空间较多功能不齐全功能齐全ARM和Thumb指令集各有自己的优点取长补短往往会得到最好的性能3. Opcod 中判断指令集Opcode[15:13] 111 Opcode[12:11]! 00 满足则为32bit 的ARMbl #0x80000fbc0xed 0xff 0xff 0xeb4. IDA 中识别与切换指令集Edit-segments-change segment register value(快捷键ALTG)请看操作。这有一段指令判断出目前是thumb指令集的按下ALTG,把0x1改成0x0就是指定为ARM指令集然后按下P键定义函数函数参数就都分析出来了(5. ARM切换指令集原理处理器无论在ARM还是Thumb状态下都可以通过BX/BLX/LDR/LDM切换不同的指令集。状态切换是由寄存器Rn的最低位来指定的如果操作数寄存器的状态位Bit00则进入ARM状态如果Bit01则进入Thumb状态。ARM 中对于字节、字、双字的定义注意和intel汇编的区别一个word(字)这里是4个字节但是注意一下在IDA中依然延续着老的传统一个DCW(word)代表两个字节DCB 定义1字节数据DCW 定义2字节数据DCD 定义4字节数据在IDA中在上面这些数据定义上按下D键可以切换定义的类型Array 定义数组右键或*号键数组最常见的就在数组IDA中的自定义数据类型Structures 窗口中可以创建一个自定义结构体。按下I或者Ins键即可创建。创建了一个名为test的结构体因为没有定义字段所以现在都还是空的结构体长度为0(相当于空结构体没有任何内容)所以去定义字段。为自定义数据类型添加字段创建完结构体后长这样在ends处按下D键就可以定义一个字段了在字段上按D可以改变长度1/2/4其他按键这样就可以给一个变量转成自己的结构体类型应用自定义数据类型在起始数据处右键-Structure-自定义的数据类型ARM汇编中的标志寄存器与条件代码跳转指令b指令跳转bl指令跳转且保存返回地址blx/bx指令带x可以切换指令集分支指令例子beqbeq(equal)b指令条件助记符(参考下面的cond)ben条件执行ARM中大部分的指令都支持带条件执行。cond:前四位保存条件码比较指令的大用处Compare 指令cmp r0,#1完成操作:减法运算(不保存结果)根据结果更新标志位标志寄存器APSR 寄存器标志寄存器是条件执行的基础。N、Z、C、V用于条件标志位N - 负数标志位Z - 零标志位C - 进位标志位V - 溢出标志位比如若减法运算之后为负数则N为1为0则Z1一些会修改标志位的指令1. 指令后缀带S的指令例如(MOVS)2. TST(and)、TEQ(or)、CMN(add)、CMP(sub)例如MOVS之后的到的值为0那么Z就被置位(为1)完整一点的例子这里if有两种可能一种是a10一种是a10在汇编中先cmp a,#10然后选择if括号内相反的选项 bgt next1 (大于则跳转出去)然后在这中间填入if代码块中的内容实例分析打开程序导出表libcinit的第三个参数(R2)是main函数的地址跳入main函数之后发现IDA未能把ARM指令集识别正确。需要手动(ALTG)随便输入一个不等于0x0的数全部改好之后就识别出来了程序源码123456789101112131415161718192021222324252627282930int (){int a 0,b 0;printf(This is condition statements re test!nPlease input two number:);scanf(%d%d,a,b);if(a b 10){printf([if]ab10b);}if(a b){printf([if-else-1]a bn);}else if(a b){printf([if-else-if] abn);}else{printf([if-else] a}if(a 10){if(a 20){printf([nest if]n);}printf(a 10n);}return 0;}自己调试一下生成thumb代码BL的下一条指令的地址被保存在LR寄存器中调用gcc的内建函数R0作为参数 R1LR57C(待调试) R1R1257E(待调试) 地址做移位是为了对齐(如这里的R1)而数移位是为了做乘除法(如这里的R0)LSRS: R1R1右移两位LSLSR0R0左移两位R0*4LSLSR1R1左移两位 //先右移再左移清除R1原来的最低位用于对齐得到0x580(待调试)LDRR0[R1R0] [580原来的R04] //假设原来的R01则R0[580原来R04][5804][0x584]loc_59C-0x580ADDS: R0R0R1loc_59CMOV: LRloc_59CPOP: 恢复寄存器R0R1MOV: PCloc_59C;函数结束跳转到case选中的代码块这些不是代码是长为4字节的数据项每一项都是偏移值这个偏移值0x580就能找到真正的代码生成ARM代码ADDLSPCPC(R3*4)PC的PC寄存器指向的不是下条指令是下下条指令(也就是当前指令地址8)CEMU测试bl funl //把LR设置为BL指令的下一条地址fun1:mov r0,pcmov r1,lr差了8个字节关于ARM中的寄存器PC从图中可以看出一条汇编指令的运行有三个步骤取指、译码、执行当第一条汇编指令取指完成后紧接着就是第二条指令的取指然后第三条…如此嵌套其实很容易看出第一条指令add r0, r1,$5取指完成后PC就指向了第二条指令此时PCPC4当第一条指令译码完成以后此时PCPC8所以第一条指令开始执行时PC值已经加了8所以必须记住这个前提在arm中每次该指令执行时其实这时的PC值是PCPC8而且这个前提也同样适合多级流水线原因就不解释了