ARM学习之-----------确认参数个数示例版

2020-04-25

  • 学习如何通过arm汇编代码确认函数参数的个数(不足之处后期补充)

  • R0/R1/R2/R3 = 参数寄存器

  1. 用参数寄存器存放函数的参数(寄存器不够:栈)
  2. 参数从R0开始
  • 查看方法
  1. 看函数跳转的寄存器(B,BL,BLX),如果涉及到参数寄存器(Rn),如果n<=4,则参数为R0-Rn
    1. 比如 BLX R3 ,那么参数就是R0,R1,R2
  2. 如果BLX 后面的不是参数寄存器,则说明参数至少4个,
    1. 本人新手,至于如何判断函数的参数个数,,下面通过具体的汇编代码查看,,
    2.  
  • 示例
  1. java层代码
    public native int testOneParam(int a);
        public native int testTwoParam(int a, int b);
        public native int testThreeParam(int a, int b, int c);
        public native int testFourParam(int a, int b, int c,int d);
        public native int testFiveParam(int a, int b, int c,int d,int e);
        public native int testSixParam(int a, int b, int c,int d,int e,int f);
        public native int testSevenParam(int a, int b, int c,int d,int e,int f,int g);
  2. 汇编代码public native int testOneParam(int a);
    libparamtest.so:B4D8A100 Java_com_ldj_leanndk001_TestParamActivity_testOneParam
    libparamtest.so:B4D8A100 MOV             R0, R2    //1
    libparamtest.so:B4D8A104 BX              LR        //2
    libparamtest.so:B4D8A104 ; End of function Java_com_ldj_leanndk001_TestParamActivity_testOneParam
    
    //注释1处。
    首先这个是jni函数,而且是静态注册,所以有两个固定参数R0(JNIEnv*),R1(jobject),
    此处将R2赋值给R0,并且参与BX运算,可知函数有三个参数,,传递进来的java层有一个参数
    
  3.  public native int testTwoParam(int a, int b);
    libparamtest.so:B4D8A108 Java_com_ldj_leanndk001_TestParamActivity_testTwoParam
    libparamtest.so:B4D8A108 ADD             R0, R3, R2    //注释1
    libparamtest.so:B4D8A10C BX              LR            //注释2
    libparamtest.so:B4D8A10C ; End of function Java_com_ldj_leanndk001_TestParamActivity_testTwoParam
    
    //注释1
    将R2+R3的结果赋值给R0,不涉及别的寄存器,可知参数为2+2=4,java层有两个参数 
    

     

  4. public native int testThreeParam(int a, int b, int c);
    libparamtest.so:B4D8A110 Java_com_ldj_leanndk001_TestParamActivity_testThreeParam
    libparamtest.so:B4D8A110
    libparamtest.so:B4D8A110 arg_0=  0
    libparamtest.so:B4D8A110
    libparamtest.so:B4D8A110 LDR             R0, [SP,#arg_0]   //将栈顶数据赋值给R0
    libparamtest.so:B4D8A114 ADD             R1, R3, R2   //R1=R2+R3
    libparamtest.so:B4D8A118 ADD             R0, R1, R0   //R0=R1+R0
    libparamtest.so:B4D8A11C BX              LR
    libparamtest.so:B4D8A11C ; End of function Java_com_ldj_leanndk001_TestParamActivity_testThreeParam
    
    //分析:
    jni函数有两个固定参数,然后LDR指令获取了一个参数,加上原本的参数寄存器R0-R3,所以jni层一共有5个参数,java层有3个

    调试截图:

  5. public native int testFourParam(int a, int b, int c,int d);
    libparamtest.so:B4D8A120 Java_com_ldj_leanndk001_TestParamActivity_testFourParam
    libparamtest.so:B4D8A120
    libparamtest.so:B4D8A120 arg_0=  0
    libparamtest.so:B4D8A120 arg_4=  4
    libparamtest.so:B4D8A120
    libparamtest.so:B4D8A120 LDR             R1, [SP,#arg_0] //从栈顶获取数据赋值给R1,也就是第5个参数   
    libparamtest.so:B4D8A124 ADD             R2, R3, R2    //R2=R2+R3
    libparamtest.so:B4D8A128 LDR             R0, [SP,#arg_4] //从栈[SP+4]处获取第6个参数,赋值给R0
    libparamtest.so:B4D8A12C ADD             R1, R2, R1    //R1=R2+R1
    libparamtest.so:B4D8A130 ADD             R0, R1, R0    //R0=R1+R0
    libparamtest.so:B4D8A134 BX              LR
    libparamtest.so:B4D8A134 ; End of function Java_com_ldj_leanndk001_TestParamActivity_testFourParam
    
    
    //分析:
    jni函数有两个固定参数R0,R1,
    
    原本的参数寄存器R0-R3,LDR指令获取了两个参数,所以总共是6个参数,java层4个

    调试截图:

  6. public native int testFiveParam(int a, int b, int c,int d,int e);
    libparamtest.so:B4D8A138 testFiveParam
    libparamtest.so:B4D8A138
    libparamtest.so:B4D8A138 arg_8=  8
    libparamtest.so:B4D8A138
    libparamtest.so:B4D8A138 LDMFD           SP, {R0,R12}    //1.将栈前两个数据分别赋值给R0,R12
    libparamtest.so:B4D8A13C ADD             R2, R3, R2      //2.  
    libparamtest.so:B4D8A140 ADD             R0, R2, R0        
    libparamtest.so:B4D8A144 LDR             R1, [SP,#arg_8]  //3.从[SP+8]数据赋值给R1
    libparamtest.so:B4D8A148 ADD             R0, R0, R12
    libparamtest.so:B4D8A14C ADD             R0, R0, R1
    libparamtest.so:B4D8A150 BX              LR
    libparamtest.so:B4D8A150 ; End of function testFiveParam
    
    //分析:
    jni函数有两个固定参数R0,R1,
    
    第一个LDMFD指令,将SP+0,SP+4两个数据赋值给R0和R12,可以看出是两个参数
    然后LDR指令将SP+8数据赋值给R1。又是一个参数
    
    加上4个参数寄存器可知,一共是7个参数,,java层5个参数
    
        

    调试截图:

  7. public native int testSixParam(int a, int b, int c,int d,int e,int f);
    libparamtest.so:B4D8A154 testSixParam
    libparamtest.so:B4D8A154
    libparamtest.so:B4D8A154 arg_0=  0
    libparamtest.so:B4D8A154 arg_4=  4
    libparamtest.so:B4D8A154 arg_8=  8
    libparamtest.so:B4D8A154 arg_C=  0xC
    libparamtest.so:B4D8A154
    libparamtest.so:B4D8A154 STMFD           SP!, {R11,LR}  //压栈,SP=SP-0x8
    libparamtest.so:B4D8A158 LDR             R0, [SP,#8+arg_0]  //SP+0x8,第五个参数
    libparamtest.so:B4D8A15C ADD             R2, R3, R2    //参数寄存器
    libparamtest.so:B4D8A160 LDR             LR, [SP,#8+arg_4]  //SP+0xc,第6个参数
    libparamtest.so:B4D8A164 ADD             R0, R2, R0
    libparamtest.so:B4D8A168 LDR             R1, [SP,#8+arg_8]  //SP+0x10,第7个参数
    libparamtest.so:B4D8A16C ADD             R0, R0, LR
    libparamtest.so:B4D8A170 LDR             R12, [SP,#8+arg_C] //SP+0x14,第8个参数
    libparamtest.so:B4D8A174 ADD             R0, R0, R1
    libparamtest.so:B4D8A178 ADD             R0, R0, R12
    libparamtest.so:B4D8A17C LDMFD           SP!, {R11,PC}    //平栈,,SP=Sp+0x8
    libparamtest.so:B4D8A17C ; End of function testSixParam
    
    //分析:
    jni函数有两个固定参数R0,R1,
    
    从上面注释可以看出,一共使用LDR指令从栈中获取了4个参数
    
    加上4个参数寄存器可知,一共是8个参数,,java层6个参数

    调试截图

  8.  

  9. public native int testSevenParam(int a, int b, int c,int d,int e,int f,int g);
    libparamtest.so:B4D8A180 testSevenParam
    libparamtest.so:B4D8A180
    libparamtest.so:B4D8A180 arg_0=  0
    libparamtest.so:B4D8A180 arg_4=  4
    libparamtest.so:B4D8A180
    libparamtest.so:B4D8A180 STMFD           SP!, {R4,LR}            ; 压栈,SP=SP-0x08
    libparamtest.so:B4D8A184 ADD             LR, SP, #8+arg_4        ; 将PC+0x8+4 栈地址保存到LR            寄存器,此时LR寄存器中保存的是第6个参数地址
    libparamtest.so:B4D8A188 LDR             R4, [SP,#8+arg_0]       ; 将SP+0x8中保存的数给R4,就是第五个参数
    libparamtest.so:B4D8A18C ADD             R2, R3, R2              ; 加法运算
    libparamtest.so:B4D8A190 LDMIA           LR, {R0,R1,R12,LR}      ; 批量加载栈中保存的数据,并且赋值 给R0,R1,R12,LR,
    libparamtest.so:B4D8A190                                         ; 此时这四个寄存器中保存的都是传递进来的参数
    libparamtest.so:B4D8A194 ADD             R2, R2, R4
    libparamtest.so:B4D8A198 ADD             R0, R2, R0
    libparamtest.so:B4D8A19C ADD             R0, R0, R1
    libparamtest.so:B4D8A1A0 ADD             R0, R0, R12
    libparamtest.so:B4D8A1A4 ADD             R0, R0, LR
    libparamtest.so:B4D8A1A8 LDMFD           SP!, {R4,PC}            ; 平栈,,恢复栈顶指针
    libparamtest.so:B4D8A1A8 ; End of function testSevenParam
    
    
    
    //分析:
    jni函数有两个固定参数R0,R1,
    
    从上面注释可以看出,一共使用LDR指令从栈中获取了1个参数
    LDMIA指令获取了4个,
    
    加上4个参数寄存器可知,一共是9个参数,,java层7个参数

    调试截图:

 

 

  1.  

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值