汇编Switch(十一)

1.先看个最简单的switch(小于4)

分析:

解释:这个主要是拿到一个静态变量调用printf打印

打印完执行:

对于上面也就是拉伸栈空间(这个前面说过,不多说),w0-1判断是否相等,-2是否相等,-3是否相等,如果相等就直接执行printf,然后取出值结束。其实这个小于3个分支,也就是和if else一样


2.多分支switch执行default(大于或等于4)

分析:

tip:判断是否b.hi大于,是根于subs改变了标记寄存器(状态寄存器)cpsr来判断是否大于 (link:标记寄存器 )

问题:mark_b处看printf是什么?

  1. 0x1029068b0低12位清0     >0x102906000
  2. 0x102906000低12位值+1    >0x102907000
  3. 0x102907000 +0xf2c           >0x102907f2c

然后在lldb执行:

问题:mark_a处为什么减4?

先判断是不是default


3.多分支switch(大于或等于4)

分析:

问题:

#mark-1.1 取值多少?

根据adrp运行得知x8=0x104c438c0,然后通过lldb取出内存分布

lldb: memory read 0x104c438c0

0x104c438c0: 79 22 32 34 00 42 33 32 40 30 3a 38 40 22 55 49 ……..

(从右到左没4个字节(2bit位=1字节)如0x34322279)

#mark-2 ldrsw x10, [x8, x9, lsl #2] 什么意思?

x8+ (以x8作为基地址,x9左移2位),由上面分析可知x9=1,

  1. x9(1)左移2位是 4
  2. x8+4也就是上面的79 22 32 34 00 42 33 32 40 30 3a 38 40 22 55 49….向右偏移4个字节,也就是从00…开始
  3. x10=00 42 33 32,也就是0x32334200
  4. register read x10 可以验证第3步地址对不对

 register read x10  读取 x10 = 0xffffffffffffffa8 也就是个负数 (0xff-0xa8+1) =0x58 (十进制-88) (全是ffffff是-1)

 #mark-3 0x104c42838 <+60>: add x8, x10, x8  ?

通过上面2步知道:

x8= x10是个负数, x8地址-x10地址

如果case 202: ?  

解:w0直接减200来判断 (一样来查表)

如果case是乱序的呢?switch分支有空缺 比如 case 1:    case 5: case 9: case 11:   

它一样是制作一张表,拿空间换时间 把中间跳过的数补充default地址 可看#mark-1.1来查看x8地址 如下图


如果是乱序呢?

解析:

这个完全就失去switch的优势,就是if else


Switch

1、假设switch语句的分支比较少的时候 小于4个相当于if
2、各个分支常量的差值较大的时候,编译器会在效率还是内存进行取舍(这个时候编译器还是会编译成类似于if,else的结构)
3、在分支比较多的时候:在编译的时候会生成一个表(跳转表每个地址四个字节)通过地址直接跳转  (最好是连续的case)

发表回复

电子邮件地址不会被公开。 必填项已用*标注

Protected with IP Blacklist CloudIP Blacklist Cloud