我有这个课程作业,我似乎无法弄明白。 重点是将此程序集转换为C(使用GNU汇编程序AT& T语法汇编的代码):
.section .rdata,"dr"
LC0:
.ascii "%d\12\0"
.text
.globl _main
_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl 12(%ebp), %eax
addl $4, %eax
movl (%eax), %eax
movl %eax, (%esp)
call _atoi
movl %eax, 24(%esp)
cmpl $4, 24(%esp)
je L2
cmpl $6, 24(%esp)
jle L3
cmpl $9, 24(%esp)
jg L3
L2:
movl 24(%esp), %eax
addl $20, %eax
movl %eax, 28(%esp)
jmp L4
L3:
cmpl $0, 24(%esp)
jne L5
movl $44, 28(%esp)
jmp L4
L5:
cmpl $-1, 24(%esp)
jne L6
movl $-44, 28(%esp)
jmp L4
L6:
movl $99, 28(%esp)
L4:
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
movl $0, %eax
leave
ret
然而,我总是迷失在L2上。似乎无论我们是否进入第一个if语句,我们总是会执行标签L2,这没有任何意义。我试图理解这一切,我得到的最接近的是这个C代码:
#include <stdio.h>
int main(int argc, char *argv[]){
int y = 0;
int x = atoi(*++argv);
if (x != 4){
if (x > 6 && x <= 9){
y = 20 + x;
}
else if (x == 0){
y = 44;
}
else if (x == -1){
y = -44;
}
else {
y = 99;
}
}
else{
y = 20 + x;
}
printf("%d %d", y, x);
}
有人可以帮忙解决我遇到的这个令人困惑的问题, 感谢
答案 0 :(得分:4)
在解码编译器输出时,它通常有助于以更密集但仍然非常低级的形式(伪代码)重写汇编代码,仅使用基本的低级转换。关键是以一种难以出错的方式对少量指令进行分组/组合,但这更好地暴露了代码片段的内部逻辑。下一步是消除冗余存储和临时存储(如用于存储x + 20到y的EAX)。我正在跳过这里的第一步,但在更复杂的代码中执行此操作会很危险。
条件序列变为:
x equ [esp + 24]
y equ [esp + 28]
if (x == 4) goto L2;
if (x <= 6) goto L3;
if (x > 9) goto L3;
L2: y = x + 20; goto L4;
L3: if (x != 0) goto L5;
y = 44; goto L4;
L5: if (x != -1) goto L6;
y = -44; goto L4;
L6: y = 99;
L4: printf("%d\f", y);
前三个条件形成了编制者用来评估复杂条件的显着模式。编译器将该条件的第二项和第三项反转为使用其“跳转”解决方案片段;再次反转允许你编码原始条件(跳转到L2 /'然后'是OR,跳转到L3 /'其他'是AND NOTs):
if (x == 4 || !(x <= 6) && !(x > 9))
- &GT;
if (x == 4 || (x > 6) && (x <= 9))
鲍勃是你的叔叔。其他条件可能是链接if或switch语句的结果,很难说。但这几乎不重要。因此你的反编译已经几乎完美,你只是错过了一个小小的节拍。在中间步骤中,C-ified条件看起来像这样:
if (x == 4 || x > 6 && x <= 9)
{
y = x + 20;
}
else // L3
{
if (x == 0)
{
y = 44;
}
else // L5
{
if (x == -1)
{
y = -44;
}
else // L6
{
y = 99;
}
}
}
然后可以收紧:
if (x == 4 || x > 6 && x <= 9)
{
y = x + 20;
}
else if (x == 0)
{
y = 44;
}
else if (x == -1)
{
y = -44;
}
else
{
y = 99;
}
P.S。:(argv + 1)
的值不会存储回argv
,只是取消引用。因此它是atoi(*(argv + 1))
或atoi(argv[1])
。