> 文章列表 > 3、循环选择判断

3、循环选择判断

3、循环选择判断

  • 获取全局变量和常量时,会出现adrp和add两条指令获取一个地址的情况
  • ADRP(Address Page)
    • adrp x0, 1
      • 将PC寄存器的低12位清零
      • 将1的值,左移12位,16进制就是0x1000
      • 以上两个结果相加放入x0寄存器
    • 通过ADD指令获取这页内存中的偏移值
  • 条件判断
    • cmp(Compare)比较指令
      • CMP把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,但不存储结果,只是正确的更改标志(CMP后面跟的是B.LE,即else的条件)
      • 一般CMP做完判断后会进行跳转,后面通常会跟上B指令
        • BL符号: 跳转到符号处执行
        • B.LT符号: 比较结果是小于(less than),执行标号,否则不跳转
        • B.LE符号: 比较结果是小于等于(less than or equal to),执行标号,否则不跳转
        • B.GT标号: 比较结果是大于(greater than),执行标号,否则不跳转
        • B.GE标号: 比较结果是大于等于(greater than or equal to),执行标号,否则不跳转
        • B.EQ标号: 比较结果是等于,执行标号,否则不跳转
        • B.NE标号: 比较结果是不等于(not equal),执行标号,否则不跳转
        • B.HI标号: 比较结果是‘无符号大于’,执行标号,否则不跳转
        • B.HS标号: 比较结果是‘无符号大于等于’,执行标号,否则不跳转
    • do-while循环: 判断条件在后面,满足条件往外跳
    • while循环: 判断条件在里面,不满足就往外跳
    • for循环: 判断条件在里面,不满足就往外跳
  • Switch
    • 1、假设switch语句的分支比较少时(比如3条,少于4的时候没有意义),没有必要使用次结构,相当于if-else
    • 2、各个分支常量的差值较大时,编译器会在效率还是内存进行取舍,这时编译器还是会编译成类似if-else的结构
    • 3、在分支比较多的时候,在编译的时候会生成一个表,不同的case通过跳转表的不同地址,每个地址占四个字节.
  • Switch使用总结
    • 1、先将参数减去最小case
    • 2、先判断是否是default,如果不是,则在范围之内,可以通过表直接拿到地址,反之则default
    • 表中为什么不直接存地址,而是存差值?
      • 地址太长了
      • 地址在运行时期才会知道虚拟地址(即ASLR),如果存的是偏移地址,使用时需要加上ASLR
    • 如果case很大呢?
      • 只要是连续的就行,因为汇编会减去最小case
      • 如果case之间相差太大了,编译器会进行优化,变成if-else