汇编看if else

前言:

我们先来思考几个问题
如:
1、 我们经常使用到的if else 流程语句代码 是怎么被机器读懂的
2、它背后的本质是什么
3、 从汇编的角度去看 if else 又是什么呢
4、 不同的汇编对if else 的解释 是相同的吗


本文分别从ARM和AT&T汇编去分析一段oc代码

源码

- (void)cycle {
    
    
    int a = 6;
    int b = 10;
    if (a == b) {
    
    
        NSLog(@"相等");
    }else {
    
    
        NSLog(@"不相等");
    }
    int c = 9;
}

ARM汇编

YangASM`-[ViewController asm_ifCycle]:
    0x104b8df7c <+0>:  sub    sp, sp, #0x30             ; =0x30 
    0x104b8df80 <+4>:  stp    x29, x30, [sp, #0x20]
    0x104b8df84 <+8>:  add    x29, sp, #0x20            ; =0x20 
    0x104b8df88 <+12>: stur   x0, [x29, #-0x8]
    0x104b8df8c <+16>: str    x1, [sp, #0x10]
    0x104b8df90 <+20>: mov    w8, #0x6
    0x104b8df94 <+24>: str    w8, [sp, #0xc]
    0x104b8df98 <+28>: mov    w8, #0xa
    0x104b8df9c <+32>: str    w8, [sp, #0x8]
    0x104b8dfa0 <+36>: ldr    w8, [sp, #0xc]
    0x104b8dfa4 <+40>: ldr    w9, [sp, #0x8]
    0x104b8dfa8 <+44>: subs   w8, w8, w9
    0x104b8dfac <+48>: b.ne   0x104b8dfc0               ; <+68> at ViewController.m
0x104b8dfb0 <+52>: adrp   x0, 3
0x104b8dfb4 <+56>: add    x0, x0, #0x8              ; =0x8 
0x104b8dfb8 <+60>: bl     0x104b8e520               ; symbol stub for: NSLog
    0x104b8dfbc <+64>: b      0x104b8dfcc               ; <+80> at ViewController.m
    0x104b8dfc0 <+68>: adrp   x0, 3
    0x104b8dfc4 <+72>: add    x0, x0, #0x28             ; =0x28 
    0x104b8dfc8 <+76>: bl     0x104b8e520               ; symbol stub for: NSLog
    0x104b8dfcc <+80>: mov    w8, #0x9
->  0x104b8dfd0 <+84>: str    w8, [sp, #0x4]
    0x104b8dfd4 <+88>: ldp    x29, x30, [sp, #0x20]
    0x104b8dfd8 <+92>: add    sp, sp, #0x30             ; =0x30 
    0x104b8dfdc <+96>: ret  

ARM汇编解析

我们重点看 if 语句 的汇编代码

	// ne是 not equal缩写 代表条件 不相等
	// b跳转指令 
	// b.ne  就是条件跳转指令  如果不相等跳转到0x104b8dfc0指令 
    // 0x104b8dfc0指令 就是  NSLog(@"不相等")对应的汇编地址  下面可以看到
	0x104b8dfac <+48>: b.ne   0x104b8dfc0  
	
	//  NSLog(@"相等")
	0x104b8dfb0 <+52>: adrp   x0, 3
    0x104b8dfb4 <+56>: add    x0, x0, #0x8              ; =0x8 
    0x104b8dfb8 <+60>: bl     0x104b8e520               ; symbol stub for: NSLog
    
    // 无条件跳转到  0x104b8dfcc   
    // 跳过的3条指令 刚好是  NSLog(@"不相等"); 对应的汇编指令
    0x104b8dfbc <+64>: b      0x104b8dfcc               ; <+80> at ViewController.m
    
    // NSLog(@"不相等");
    0x104b8dfc0 <+68>: adrp   x0, 3
    0x104b8dfc4 <+72>: add    x0, x0, #0x28             ; =0x28 
    0x104b8dfc8 <+76>: bl     0x104b8e520               ; symbol stub for: NSLog
    
    // int c = 9
    0x104b8dfcc <+80>: mov    w8, #0x9
->  0x104b8dfd0 <+84>: str    w8, [sp, #0x4]
    

介绍3条跳转指令

bl 跳转指令 跳转会附带把下一条指令的地址 保存到寄存器lr(x30)中 之后 再去跳转
b 最单纯的跳转指令
b.ne 条件跳转指令 不相等就跳转

AT&T汇编

同样的代码 我们看下在AT&T 汇编下的生成

YangASM`-[ViewController asm_ifCycle]:
    0x101c21eb0 <+0>:  pushq  %rbp
    0x101c21eb1 <+1>:  movq   %rsp, %rbp
    0x101c21eb4 <+4>:  subq   $0x20, %rsp
    0x101c21eb8 <+8>:  movq   %rdi, -0x8(%rbp)
    0x101c21ebc <+12>: movq   %rsi, -0x10(%rbp)
    0x101c21ec0 <+16>: movl   $0x6, -0x14(%rbp)
    0x101c21ec7 <+23>: movl   $0xa, -0x18(%rbp)
    0x101c21ece <+30>: movl   -0x14(%rbp), %eax
    0x101c21ed1 <+33>: cmpl   -0x18(%rbp), %eax
    0x101c21ed4 <+36>: jne    0x101c21ef0               ; <+64> at ViewController.m
    0x101c21eda <+42>: leaq   0x2137(%rip), %rax        ; @
    0x101c21ee1 <+49>: movq   %rax, %rdi
    0x101c21ee4 <+52>: movb   $0x0, %al
    0x101c21ee6 <+54>: callq  0x101c22434               ; symbol stub for: NSLog
    0x101c21eeb <+59>: jmp    0x101c21f01               ; <+81> at ViewController.m:29:9
    0x101c21ef0 <+64>: leaq   0x2141(%rip), %rax        ; @
    0x101c21ef7 <+71>: movq   %rax, %rdi
    0x101c21efa <+74>: movb   $0x0, %al
    0x101c21efc <+76>: callq  0x101c22434               ; symbol stub for: NSLog
->  0x101c21f01 <+81>: movl   $0x9, -0x1c(%rbp)
    0x101c21f08 <+88>: addq   $0x20, %rsp
    0x101c21f0c <+92>: popq   %rbp
    0x101c21f0d <+93>: retq   

AT&T汇编解析

我们重点看其中的条件语句

	// int a = 6  6存放到  -0x14(%rbp)  内存地址
	0x101c21ec0 <+16>: movl   $0x6, -0x14(%rbp)
	
	// int b = 10  10 存放到 -0x18(%rbp) 内存地址 
	0x101c21ec7 <+23>: movl   $0xa, -0x18(%rbp)
	
	// 把-0x14(%rbp) 内存地址的值也就是6 赋给 eax 寄存器
    0x101c21ece <+30>: movl   -0x14(%rbp), %eax
	
	// cmp 比较指令  加l变成 cmpl 就是比较的4个字节  
	// 我们的 a b 都是int类型 在内存占据4个字节
	// 从-0x18(%rbp)地址 往下4个字节  里面存储的数据 也就是10  和 eax 里面的值 进行对比
	// 也就是  6 和 10  对比 是否想等
     0x101c21ed1 <+33>: cmpl   -0x18(%rbp), %eax

    // jne jump not equal  条件跳转指令  不相等就跳转
    // 如果 a != b 那么就进行跳转  跳转到 0x101c21ef0 指令  
    // 0x101c21ef0指令 在下面可以找到  其实就是 NSLog(@"不相等"); 对应的指令
    0x101c21ed4 <+36>: jne    0x101c21ef0               ; <+64> at ViewController.m
	
	// leaq 我们后面再详细说  其实就是  强制拿一个地址 给 rax   而不是拿地址上的值给 rax 
	// NSLog(@"相等");
    0x101c21eda <+42>: leaq   0x2137(%rip), %rax        ; @
    0x101c21ee1 <+49>: movq   %rax, %rdi
    0x101c21ee4 <+52>: movb   $0x0, %al
    0x101c21ee6 <+54>: callq  0x101c22434               ; symbol stub for: NSLog
    
    //  输出完 NSLog(@"相等"); 之后跳转到 0x101c21f01 指令
    0x101c21eeb <+59>: jmp    0x101c21f01               ; <+81> at ViewController.m:29:9	

	/// NSLog(@"不相等");
    0x101c21ef0 <+64>: leaq   0x2141(%rip), %rax        ; @
    0x101c21ef7 <+71>: movq   %rax, %rdi
    0x101c21efa <+74>: movb   $0x0, %al
    0x101c21efc <+76>: callq  0x101c22434               ; symbol stub for: NSLog
	
	///  int c = 9
->  0x101c21f01 <+81>: movl   $0x9, -0x1c(%rbp)

补充

1、ARM汇编和 AT&T汇编 条件跳转指令 分别是 b.ne jne
2、 jne 通常配合 cmd 使用

猜你喜欢

转载自blog.csdn.net/u014641631/article/details/121417915
今日推荐