一、概念梳理
1. 字(word)与字节(Byte)
由于历史原因,intel从16位体系逐步扩展到32,64位体系,所以定16bit为1字。64为四字。
例如:long4字。
2. 汇编特殊算数操作
clto 转换为8字(oct word)------128位
2个64位相乘要用128位来盛放
3. 跳转指令
0 :48 89 f8 mov rdi rax
3 : eb 03 jmp 8//注意 这个是03 他都是相对地址,下一条的5再加上3 =8 就跳到8了
5 : 48 d1 f8 sar rax
8 : 48 85 c0 test rax rax
b : 7f f8 jg 5//这个跳转 f8 是个补码,源码是-8,0xb-8=5就跳到5了
d : f3 c3 repz, retq
4. 跳到中间 jump to middle
jump to middle直接翻译过来就是跳转到中间,它的原理其实就是把条件测试写在中间部分,在首次迭代开始之前先行跳转并执行条件测试语句。
long fact_jump_to_middle(long n) { long result = 1; goto test; loop: result *= n; n --; test: if (n > 1) goto loop; return result; }
对于cpu就知道从前往后执行,不看别的那些label
5. guarded-do门卫
另一种翻译方式被称为guarded-do,它的原理是在迭代之前设置一个“门卫”条件。如果不符合条件的话,则直接跳到循环逻辑之后,否则就进入循环逻辑中,此处的循环逻辑依旧用do-while循环来实现。按照这种翻译方式所翻译的goto版本如下
long fact_guarded_do(long n) { long result = 1; if (n <= 1) goto done; loop: result *= n; n --; if (n > 1) goto loop; done: return result;
可见最关键的地方是设置的“门卫”条件,该条件应该设置成循环条件的补集。只要满足这个“门卫”条件则跳过整个循环逻辑,否则就进入循环区域中。
6. switch汇编详解
如果没有break就不会跳到最后。
movl %eax, -4(%rbp) #eax中存放的是c代码中的 branchvare变量值 movl -4(%rbp), %eax cmpl $2, %eax je .L9 #等于2跳转到L9 cmpl $2, %eax jg .L10 #大于2跳转到L10,在L10代码处又进行了分支跳转 cmpl $1, %eax je .L11 #等于1跳转到L11 jmp .L8 #跳转default .L10: cmpl $3, %eax je .L12 cmpl $4, %eax je .L13 jmp .L8 .L11: call case1 jmp .L14 .L9: call case2 jmp .L14 .L12: call case3 jmp .L14 .L13: call case4 jmp .L14 .L8: call casedefault nop .L14: movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc