描述
验证if、循环、switch在汇编当中是怎么表示的
if 的汇编
新建的工程 源代码
int g = 12;
void func(int a,int b){
if(a >b){
g = a;
}else{
g = b;
}
}
int main(int argc, char * argv[]) {
func(1, 2);
return 0;
}
汇编的代码
ext:00000001000068B0 _func ; CODE XREF: _main+28↓p
__text:00000001000068B0
__text:00000001000068B0 var_8 = -8
__text:00000001000068B0 var_4 = -4
__text:00000001000068B0
__text:00000001000068B0 SUB SP, SP, #0x10
__text:00000001000068B4 STR W0, [SP,#0x10+var_4]
__text:00000001000068B8 STR W1, [SP,#0x10+var_8]
__text:00000001000068BC LDR W0, [SP,#0x10+var_4]
__text:00000001000068C0 LDR W1, [SP,#0x10+var_8]
__text:00000001000068C4 CMP W0, W1
__text:00000001000068C8 B.LE loc_1000068E0
__text:00000001000068CC ADRP X8, #_g@PAGE
__text:00000001000068D0 ADD X8, X8, #_g@PAGEOFF
__text:00000001000068D4 LDR W9, [SP,#0x10+var_4]
__text:00000001000068D8 STR W9, [X8]
__text:00000001000068DC B loc_1000068F0
__text:00000001000068E0 ; ---------------------------------------------------------------------------
__text:00000001000068E0
__text:00000001000068E0 loc_1000068E0 ; CODE XREF: _func+18↑j
__text:00000001000068E0 ADRP X8, #_g@PAGE
__text:00000001000068E4 ADD X8, X8, #_g@PAGEOFF
__text:00000001000068E8 LDR W9, [SP,#0x10+var_8]
__text:00000001000068EC STR W9, [X8]
__text:00000001000068F0
__text:00000001000068F0 loc_1000068F0 ; CODE XREF: _func+2C↑j
__text:00000001000068F0 ADD SP, SP, #0x10
__text:00000001000068F4 RET
__text:00000001000068F4 ; End of function _func
汇编代码分析
- SUB SP, SP, #0x10
- 拉伸栈空间
- STR W0, [SP,#0x10+var_4],STR W1, [SP,#0x10+var_8],LDR W0, [SP,#0x10+var_4],LDR W1, [SP,#0x10+var_8]
- 将w0,w1入栈,并从栈读到w0,w1
- CMP W0, W1
- 这个是相当于减法 w0 - w1,会修改标志寄存器,>,<,= ;
- B.LE loc_1000068E0
- LE 代表的含义是如果是w0小于等于w1那么会直接跳转到后面写的内存的方法中去_text:00000001000068E0 ADRP X8, #_g@PAGE
- ADRP X8, #_g@PAGE ,ADD X8, X8, #_g@PAGEOFF 读取一个全局变量_g 存入x8
- LDR W9, [SP,#0x10+var_8] 从栈读取一个数据存入w9
- STR W9, [X8] 将w9存入x8的地址中
- 如果w0大于w1 走这里__text:00000001000068CC ADRP X8, #_g@PAGE
- ADRP X8, #_g@PAGE ,ADD X8, X8, #_g@PAGEOFF 读取一个全局变量_g 存入x8
- LDR W9, [SP,#0x10+var_4] 从栈空间读取 [SP,#0x10+var_4] 数据放入w9
- STR W9, [X8] 将w9的值存入到x8的栈空间
- ADD SP, SP, #0x10 回复栈空间
- RET 返回
汇编还原源代码
因为w0、w1是两个参数,在main的汇编当中有
int g = 12; //动态分析可以知道
func(int a , int b){
STR W0, [SP,#0x10+var_4]
STR W1, [SP,#0x10+var_8]
LDR W0, [SP,#0x10+var_4]
LDR W1, [SP,#0x10+var_8]
- int var_4 = a
- int var_8 = b
- int w0 = var_4
- int w1 = var_8
- if(w0>w1){
ADRP X8, #_g@PAGE
ADD X8, X8, #_g@PAGEOFF
LDR W9, [SP,#0x10+var_4]
STR W9, [X8]
int* x8 = &g;
int w9 = var_4;
*x8 = w9;
}else{
ADRP X8, #_g@PAGE
ADD X8, X8, #_g@PAGEOFF
LDR W9, [SP,#0x10+var_8]
STR W9, [X8]
int *x8 = &g
int w9 = var_8;
*x8 = w9
}
}
最简化代码
int g = 12;
void func{
if(a>b){
g = a;
}else{
g = b;
}
}xw
循环的汇编
源代码 do while
int main(int argc, char * argv[]) {
int nSum = 0;
int i = 0;
do {
nSum = nSum + 1;
i++;
} while (i<100);
return 0;
}
汇编代码
代码分析
首先从SUB SP, SP, #0x20开始
- 拉伸栈空间
- 0x20+var_4 存入0
- 0x20+var_8 存入w0
- x1 入栈 SP,#0x20+var_10
- SP,#0x20+var_14存入0
- SP,#0x20+var_18存入0
loc_100006900 ; CODE XREF: _main+38↓j - w8 = 读取[SP,#0x20+var_14]
- W8 = W8 + #1
- w8 存入SP,#0x20+var_14
- 从SP,#0x20+var_18 读取给 w8
- W8 = W8+#1
- w8 存入 SP,#0x20+var_18
- SP,#0x20+var_18 读取给w8
- CMP W8, #0x64 减法运算判断
- B.LT loc_100006900 判断如果小于执行地址中的方法,如果大于等于直接走下面方法
- w8 = 0
- x0 = x8
- 恢复栈空间
- 返回
还原源代码
先做后判断 是do while
var_4 = 0
var_8 = w0
var_10 = x1
var_14 = 0
var_18 = 0
do{
w8 = var_14
w8 = w8 + 1
var_14 = w8
w8 = var_18
w8 = w8 + 1
var_18 = w8
w8 = var_18
}while(w8<0x64)
w8 = 0
x0 = x8
简化
func(id w0,id w1){
do{
int var_14 = 0;
var_14 = var_14 + 1;
int var_18 = 0;
var_18 = var_18 + 1;
}while(var_18<0x64);
return 0;
}
源代码while
int main(int argc, char * argv[]) {
int nSum = 0;
int i = 0;
while (i<100){
nSum = nSum + 1;
i++;
} ;
return 0;
}
汇编代码while
0x104a1a8e4 <+0>: sub sp, sp, #0x20 ; =0x20
0x104a1a8e8 <+4>: str wzr, [sp, #0x1c]
0x104a1a8ec <+8>: str w0, [sp, #0x18]
0x104a1a8f0 <+12>: str x1, [sp, #0x10]
-> 0x104a1a8f4 <+16>: str wzr, [sp, #0xc]
0x104a1a8f8 <+20>: str wzr, [sp, #0x8]
0x104a1a8fc <+24>: ldr w8, [sp, #0x8]
0x104a1a900 <+28>: cmp w8, #0x64 ; =0x64
0x104a1a904 <+32>: b.ge 0x104a1a924 ; <+64> at main.m
0x104a1a908 <+36>: ldr w8, [sp, #0xc]
0x104a1a90c <+40>: add w8, w8, #0x1 ; =0x1
0x104a1a910 <+44>: str w8, [sp, #0xc]
0x104a1a914 <+48>: ldr w8, [sp, #0x8]
0x104a1a918 <+52>: add w8, w8, #0x1 ; =0x1
0x104a1a91c <+56>: str w8, [sp, #0x8]
0x104a1a920 <+60>: b 0x104a1a8fc ; <+24> at main.m:19
0x104a1a924 <+64>: mov w8, #0x0
0x104a1a928 <+68>: mov x0, x8
0x104a1a92c <+72>: add sp, sp, #0x20 ; =0x20
0x104a1a930 <+76>: ret
代码分析
- sub sp, sp, #0x20 ; =0x20 拉伸栈空间
- 0x1c = 0
- 0x18 = w0
- 0x10 = x1
- 0xc = 0
- 0x8 = 0
- w8 = 0x8
- w8 和0x64比较大小 w8 - 0x64
- 如果上面的结果 大于等于执行地址中的方法,否则向下执行
- 小于等于
- w8 = 0xc
- w8 = w8 + 1
- 0xc = w8
- w8 = 0x8
- w8 = w8 + 1
- 0x8 = w8
- 小于等于
- w8 = 0
- x0 = x8
- 回复栈空间
简化代码
int func(id a, id b){
int 0xc = 0
int 0x8 = 0
while(0x8<0x64){
0xc = 0xc + 1
0x8 = ox8 + 1
}
return 0;
}
源代码循环for
int main(int argc, char * argv[]) {
for (int i = 0; i<100; i++) {
printf("woqu");
}
return 0;
}
汇编代码
__text:00000001000068C8 _main
__text:00000001000068C8
__text:00000001000068C8 var_18 = -0x18
__text:00000001000068C8 var_14 = -0x14
__text:00000001000068C8 var_10 = -0x10
__text:00000001000068C8 var_8 = -8
__text:00000001000068C8 var_4 = -4
__text:00000001000068C8 var_s0 = 0
__text:00000001000068C8
__text:00000001000068C8 SUB SP, SP, #0x30
__text:00000001000068CC STP X29, X30, [SP,#0x20+var_s0]
__text:00000001000068D0 ADD X29, SP, #0x20
__text:00000001000068D4 STUR WZR, [X29,#var_4]
__text:00000001000068D8 STUR W0, [X29,#var_8]
__text:00000001000068DC STR X1, [SP,#0x20+var_10]
__text:00000001000068E0 STR WZR, [SP,#0x20+var_14]
__text:00000001000068E4
__text:00000001000068E4 loc_1000068E4 ; CODE XREF: _main+44↓j
__text:00000001000068E4 LDR W8, [SP,#0x20+var_14]
__text:00000001000068E8 CMP W8, #0x64
__text:00000001000068EC B.GE loc_100006910
__text:00000001000068F0 ADRP X0, #aWoqu@PAGE ; "woqu"
__text:00000001000068F4 ADD X0, X0, #aWoqu@PAGEOFF ; "woqu"
__text:00000001000068F8 BL _printf
__text:00000001000068FC STR W0, [SP,#0x20+var_18]
__text:0000000100006900 LDR W8, [SP,#0x20+var_14]
__text:0000000100006904 ADD W8, W8, #1
__text:0000000100006908 STR W8, [SP,#0x20+var_14]
__text:000000010000690C B loc_1000068E4
__text:0000000100006910 ; ---------------------------------------------------------------------------
__text:0000000100006910
__text:0000000100006910 loc_100006910 ; CODE XREF: _main+24↑j
__text:0000000100006910 MOV W8, #0
__text:0000000100006914 MOV X0, X8
__text:0000000100006918 LDP X29, X30, [SP,#0x20+var_s0]
__text:000000010000691C ADD SP, SP, #0x30
__text:0000000100006920 RET
__text:0000000100006920 ; End of function _main
分析
- 从 STUR WZR, [X29,#var_4] var_4 = 0
- var_8 = w0
- var_10 = x1
- var_14 = 0
- w8 = var_14
- 因为_text:00000001000068E4 loc_1000068E4 ,__text:000000010000690C B loc_1000068E4 所以是一个循环
- cmp w8 0x64 比较
- B.GE 上面大于等于直接跳出循环。
- 小于
- ADRP、ADD获取一个常量或者全局变量 “我去” x0 是参数
- BL printf 打印
- var_18 = w0
- w8 = var_14
- w8 = w8 + 1
- var_14 = w8
- 跳转到 loc_1000068E4 B直接跳转没有 不用保存lr
- 下面的不用说了
简化代码
int func(id var_8, id var_10){
for(int var_14 = 0;var_14<0x64;i++){
printf("woqu");
}
return 0;
}