1. Ada的变体记录 (Variant Record)
以下是IDA生成的一段伪代码:
v7 = *(_BYTE *)a1;
v8 = 4;
if ( *(_BYTE *)a1 != 88 )
{
if ( (unsigned __int8)v7 <= 2u
|| v7 == 5
|| v7 == 7
|| v7 == 8
|| v7 == 9
|| v7 == 12
|| v7 == 13
|| v7 == 14
|| v7 == 17
|| v7 == 18
|| v7 == 15
|| v7 == 16
|| v7 == 59
|| v7 == 60
|| v7 == 61
|| v7 == 62
|| v7 == 63
|| v7 == 64
|| v7 == 65
|| v7 == 71
|| v7 == 72
|| v7 == 73
|| v7 == 74
|| v7 == 75
|| v7 == 80
|| v7 == 6
|| v7 == 81
|| v7 == 10
|| v7 == 11
|| v7 == 82
|| v7 == 51
|| v7 == 52
|| v7 == 53
|| v7 == 55
|| v7 == 58
|| v7 == 56
|| v7 == 45
|| v7 == 46
|| v7 == 47
|| v7 == 48
|| v7 == 49
|| v7 == 50
|| v7 == 92
|| v7 == 91 )
{
v8 = 8;
}
else if ( (unsigned __int8)(v7 - 39) <= 1u
|| v7 == 44
|| v7 == 41
|| v7 == 42
|| v7 == 43
|| v7 == 38
|| v7 == 85
|| v7 == 86
|| v7 == 87
|| v7 == 89
|| v7 == 90 )
{
v8 = 8;
}
else if ( v7 == 3
|| v7 == 19
|| v7 == 20
|| v7 == 21
|| v7 == 22
|| v7 == 23
|| v7 == 24
|| v7 == 25
|| v7 == 26
|| v7 == 27
|| v7 == 28
|| v7 == 29
|| v7 == 30
|| v7 == 31
|| v7 == 32
|| v7 == 33
|| v7 == 34
|| v7 == 35
|| v7 == 36
|| v7 == 37
|| v7 == 67
|| v7 == 68
|| v7 == 66
|| v7 == 69
|| v7 == 70 )
{
v8 = 104;
}
else
{
v8 = 8 * (v7 == 4) + 8;
}
}
v9 = v17;
v10 = v8;
qmemcpy(v17, v15, 4 * (v8 >> 2));
v12 = &v15[4 * (v8 >> 2)];
v11 = &v9[4 * (v8 >> 2)];
v13 = v8 & 2;
if ( v13 )
{
LOWORD(v13) = *(_WORD *)v12;
*(_WORD *)v11 = *(_WORD *)v12;
v11 += 2;
v12 += 2;
}
if ( (v10 & 1) != 0 )
{
LOBYTE(v13) = *v12;
*v11 = *v12;
}
这段代码的核心功能是:qmemcpy(v17, v15, 4 * (v8 >> 2));
根据上下文,v17与v15是两个变体记录类型的变量。
Ada语言中的变体记录的特点是,它的一些成员存在与否取决于该记录的参数。例如:
type Gender is (Male, Female);
type Person (Sex : Gender)is
record
Birth : Date;
case Sex is
when Male =>
Bearded : Boolean;
when Female =>
Children : Integer;
end case;
end record;
上例中,case Sex ... end case 即是变体部份。
笔者用C语言的联合类型来替代变体记录。这样,在C代码中,v17与v15的所有成员都是静态定义的,不需要动态地计算v15的长度。
因此,上述伪代码可改写为一行C代码:17 = v15;
2. Ada语言的范围检查
以下是IDA生成的一段伪代码:

上述代码中的函数mmi_server_types__t_result_data_fm_commandD116是Ada编译器生成的,用于检查变体记录类型的变量中所用的参数是否合法。
同样的调用出现了5次。在有些地方,甚至连续出现几十次。
为了便于阅读,笔者写了一个小工具,根据作用域来删除这类重复的调用语句。
3. 结语
从以上两个例子,可以领略Ada语言的灵活和严谨。
由于笔者的目的是为了学习原始代码中的设计思想,所以在把伪代码转化为C代码时精简了Ada编译器增生的代码。

被折叠的 条评论
为什么被折叠?



