- 目标:将X86二进制可执行文件转回C源代码。
- 了解编译器如何将C变成装配代码。
- 低级操作系统结构和可执行文件格式。
算术指令
mov eax,2 ; eax = 2
mov ebx,3 ; ebx = 3
add eax,ebx ; eax = eax + ebx
sub ebx, 2 ; ebx = ebx - 2
访问内存
mox eax, [1234] ; eax = *(int*)1234
mov ebx, 1234 ; ebx = 1234
mov eax, [ebx] ; eax = *ebx
mov [ebx], eax ; *ebx = eax
有条件分支
cmp eax, 2 ; compare eax with 2
je label1 ; if(eax==2) goto label1
ja label2 ; if(eax>2) goto label2
jb label3 ; if(eax<2) goto label3
jbe label4 ; if(eax<=2) goto label4
jne label5 ; if(eax!=2) goto label5
jmp label6 ; unconditional goto label6
功能调用
首先调用函数:
致电Func;将返回地址存储在堆栈上并跳到Func
第一个操作是保存返回指针:
pop esi ; save esi
Right before leaving the function:
pop esi ; restore esi
ret ; read return address from the stack and jump to it
现代编译器架构
c代码 - >解析 - >中间表示 - >优化 - >
低级中间表示 - >注册分配 - > x86汇编
高级优化
内线 p>
例如,功能C:
int foo(int a, int b){
return a+b }
c = foo(a, b+1)
转化为
c = a+b+1
循环展开
循环:
for(i=0; i<2; i++){
a[i]=0;
}
becomes
a[0]=0;
a[1]=0;
循环不变的代码运动
The loop:
for (i = 0; i < 2; i++) {
a[i] = p + q;
}
becomes:
temp = p + q;
for (i = 0; i < 2; i++) {
a[i] = temp;
}
常见的亚基消除
变量属性:
- 目标:将X86二进制可执行文件转回C源代码。
- 了解编译器如何将C变成装配代码。
- 低级操作系统结构和可执行文件格式。
算术指令
mov eax,2 ; eax = 2
mov ebx,3 ; ebx = 3
add eax,ebx ; eax = eax + ebx
sub ebx, 2 ; ebx = ebx - 2
访问内存
mox eax, [1234] ; eax = *(int*)1234
mov ebx, 1234 ; ebx = 1234
mov eax, [ebx] ; eax = *ebx
mov [ebx], eax ; *ebx = eax
有条件分支
cmp eax, 2 ; compare eax with 2
je label1 ; if(eax==2) goto label1
ja label2 ; if(eax>2) goto label2
jb label3 ; if(eax<2) goto label3
jbe label4 ; if(eax<=2) goto label4
jne label5 ; if(eax!=2) goto label5
jmp label6 ; unconditional goto label6
功能调用
首先调用函数:
致电Func;将返回地址存储在堆栈上并跳到Func
第一个操作是保存返回指针:
pop esi ; save esi
Right before leaving the function:
pop esi ; restore esi
ret ; read return address from the stack and jump to it
现代编译器架构
c代码 - >解析 - >中间表示 - >优化 - >
低级中间表示 - >注册分配 - > x86汇编
高级优化
内线 p>
例如,功能C:
int foo(int a, int b){
return a+b }
c = foo(a, b+1)
转化为
c = a+b+1
循环展开
循环:
for(i=0; i<2; i++){
a[i]=0;
}
becomes
a[0]=0;
a[1]=0;
循环不变的代码运动
The loop:
for (i = 0; i < 2; i++) {
a[i] = p + q;
}
becomes:
temp = p + q;
for (i = 0; i < 2; i++) {
a[i] = temp;
}
常见的亚基消除
变量属性:
a = b + (z + 1)
p = q + (z + 1)
becomes
temp = z + 1
a = b + z
p = q + z
常数折叠和传播
作业:
a = 3 + 5
b = a + 1
func(b)
Becomes:
func(9)
消除代码
删除不必要的代码:
a = 1
if (a < 0) {
printf(“ERROR!”)
}
to
a = 1
低级优化
强度降低
代码,例如:
y = x * 2
y = x * 15
Becomes:
y = x + x
y = (x << 4) - x
代码块重新排序
代码,例如:
if (a < 10) goto l1
printf(“ERROR”)
goto label2
l1:
printf(“OK”)
l2:
return;
Becomes:
if (a > 10) goto l1
printf(“OK”)
l2:
return
l1:
printf(“ERROR”)
goto l2
注册分配
- 内存访问比寄存器慢。
- 尝试在寄存器中尽可能多地适合本地变量。
- 将本地变量映射到堆栈位置和寄存器不是恒定的。
指令计划
汇编代码如下:
mov eax, [esi]
add eax, 1
mov ebx, [edi]
add ebx, 1
Becomes:
mov eax, [esi]
mov ebx, [edi]
add eax, 1
add ebx, 1
a = b + (z + 1)
p = q + (z + 1)
becomes
temp = z + 1
a = b + z
p = q + z
常数折叠和传播
作业:
a = 3 + 5
b = a + 1
func(b)
Becomes:
func(9)
消除代码
删除不必要的代码:
a = 1
if (a < 0) {
printf(“ERROR!”)
}
to
a = 1
低级优化
强度降低
代码,例如:
y = x * 2
y = x * 15
Becomes:
y = x + x
y = (x << 4) - x
代码块重新排序
代码,例如:
if (a < 10) goto l1
printf(“ERROR”)
goto label2
l1:
printf(“OK”)
l2:
return;
Becomes:
if (a > 10) goto l1
printf(“OK”)
l2:
return
l1:
printf(“ERROR”)
goto l2
注册分配
- 内存访问比寄存器慢。
- 尝试在寄存器中尽可能多地适合本地变量。
-
将局部变量映射到堆栈位置和寄存器不是恒定的。
-
目的:将X86二进制可执行文件转回C源代码。
-
了解编译器如何将C变成装配代码。
-
低级操作系统结构和可执行文件格式。
算术指令
mov eax,2 ; eax = 2
mov ebx,3 ; ebx = 3
add eax,ebx ; eax = eax + ebx
sub ebx, 2 ; ebx = ebx - 2
访问内存
mox eax, [1234] ; eax = *(int*)1234
mov ebx, 1234 ; ebx = 1234
mov eax, [ebx] ; eax = *ebx
mov [ebx], eax ; *ebx = eax
有条件分支
cmp eax, 2 ; compare eax with 2
je label1 ; if(eax==2) goto label1
ja label2 ; if(eax>2) goto label2
jb label3 ; if(eax<2) goto label3
jbe label4 ; if(eax<=2) goto label4
jne label5 ; if(eax!=2) goto label5
jmp label6 ; unconditional goto label6
功能调用
首先调用函数:
致电Func;将返回地址存储在堆栈上并跳到Func
第一个操作是保存返回指针:
pop esi ; save esi
Right before leaving the function:
pop esi ; restore esi
ret ; read return address from the stack and jump to it
现代编译器架构
c代码 - >解析 - >中间表示 - >优化 - >
低级中间表示 - >注册分配 - > x86汇编
高级优化
内线 p>
例如,功能C:
int foo(int a, int b){
return a+b }
c = foo(a, b+1)
转化为
c = a+b+1
循环展开
循环:
for(i=0; i<2; i++){
a[i]=0;
}
becomes
a[0]=0;
a[1]=0;
循环不变的代码运动
The loop:
for (i = 0; i < 2; i++) {
a[i] = p + q;
}
becomes:
temp = p + q;
for (i = 0; i < 2; i++) {
a[i] = temp;
}
常见的亚基消除
变量属性:
- 目标:将X86二进制可执行文件转回C源代码。
- 了解编译器如何将C变成装配代码。
- 低级操作系统结构和可执行文件格式。
算术指令
mov eax,2 ; eax = 2
mov ebx,3 ; ebx = 3
add eax,ebx ; eax = eax + ebx
sub ebx, 2 ; ebx = ebx - 2
访问内存
mox eax, [1234] ; eax = *(int*)1234
mov ebx, 1234 ; ebx = 1234
mov eax, [ebx] ; eax = *ebx
mov [ebx], eax ; *ebx = eax
有条件分支
cmp eax, 2 ; compare eax with 2
je label1 ; if(eax==2) goto label1
ja label2 ; if(eax>2) goto label2
jb label3 ; if(eax<2) goto label3
jbe label4 ; if(eax<=2) goto label4
jne label5 ; if(eax!=2) goto label5
jmp label6 ; unconditional goto label6
功能调用
首先调用函数:
致电Func;将返回地址存储在堆栈上并跳到Func
第一个操作是保存返回指针:
pop esi ; save esi
Right before leaving the function:
pop esi ; restore esi
ret ; read return address from the stack and jump to it
现代编译器架构
c代码 - >解析 - >中间表示 - >优化 - >
低级中间表示 - >注册分配 - > x86汇编
高级优化
内线 p>
例如,功能C:
int foo(int a, int b){
return a+b }
c = foo(a, b+1)
转化为
c = a+b+1
循环展开
循环:
for(i=0; i<2; i++){
a[i]=0;
}
becomes
a[0]=0;
a[1]=0;
循环不变的代码运动
The loop:
for (i = 0; i < 2; i++) {
a[i] = p + q;
}
becomes:
temp = p + q;
for (i = 0; i < 2; i++) {
a[i] = temp;
}
常见的亚表达消除
The variable attributions:
a = b + (z + 1)
p = q + (z + 1)
becomes
temp = z + 1
a = b + z
p = q + z
常数折叠和传播
作业:
a = 3 + 5
b = a + 1
func(b)
Becomes:
func(9)
消除代码
删除不必要的代码:
a = 1
if (a < 0) {
printf(“ERROR!”)
}
to
a = 1
低级优化
强度降低
代码,例如:
y = x * 2
y = x * 15
Becomes:
y = x + x
y = (x << 4) - x
代码块重新排序
代码,例如:
if (a < 10) goto l1
printf(“ERROR”)
goto label2
l1:
printf(“OK”)
l2:
return;
Becomes:
if (a > 10) goto l1
printf(“OK”)
l2:
return
l1:
printf(“ERROR”)
goto l2
注册分配
- 内存访问比寄存器慢。
- 尝试在寄存器中尽可能多地适合本地变量。
- 将本地变量映射到堆栈位置和寄存器不是恒定的。
指令计划
汇编代码如下:
mov eax, [esi]
add eax, 1
mov ebx, [edi]
add ebx, 1
Becomes:
mov eax, [esi]
mov ebx, [edi]
add eax, 1
add ebx, 1
a = b + (z + 1)
p = q + (z + 1)
becomes
temp = z + 1
a = b + z
p = q + z
常数折叠和传播
作业:
a = 3 + 5
b = a + 1
func(b)
Becomes:
func(9)
消除代码
删除不必要的代码:
a = 1
if (a < 0) {
printf(“ERROR!”)
}
to
a = 1
低级优化
强度降低
代码,例如:
y = x * 2
y = x * 15
Becomes:
y = x + x
y = (x << 4) - x
代码块重新排序
代码,例如:
if (a < 10) goto l1
printf(“ERROR”)
goto label2
l1:
printf(“OK”)
l2:
return;
Becomes:
if (a > 10) goto l1
printf(“OK”)
l2:
return
l1:
printf(“ERROR”)
goto l2
注册分配
- 内存访问比寄存器慢。
- 尝试在寄存器中尽可能多地适合本地变量。
- 将本地变量映射到堆栈位置和寄存器不是恒定的。
指令计划
汇编代码如下:
mov eax, [esi]
add eax, 1
mov ebx, [edi]
add ebx, 1
Becomes:
mov eax, [esi]
mov ebx, [edi]
add eax, 1
add ebx, 1
指令计划
汇编代码如下:
mov eax, [esi]
add eax, 1
mov ebx, [edi]
add ebx, 1
Becomes:
mov eax, [esi]
mov ebx, [edi]
add eax, 1
add ebx, 1