2024年深圳杯数学建模C题编译器版本的识别问题解题全过程文档及程序

2024年深圳杯数学建模

C题 编译器版本的识别问题

原题再现:

作为一种重要的工具,电子计算机自诞生以来,经历了极为快速的发展。区区百年的时间内,无论从体积、能耗、计算速度,还是应用能力等方面,电子计算机都出现了极为显著的变化。但要充分利用这一工具,必须使用能够被电子计算机解释执行的指令序列,即程序。
  最早可用于在电子计算机上执行的程序通常使用机器语言(machine language)编制。由于该类语言并不直观,故它极大地限制了电子计算机的普及。为克服这一困难,1957年诞生了第一个自动编译器,FORTRAN。此后,大量性能更高并支持近乎自然语言的编译器被设计了出来,例如,著名的C/C++编译器,Python编译器等。编译器的出现极大地推动了电子计算机在当代的广泛应用。
  为方便使用电子计算机,人们需首先按照一定的规则(即程序设计语言)将需要电子计算机完成的指令以特定的顺序集成在一起,形成脚本(即程序),然后使用编译器自动将脚本翻译为一系列机器语言的组合(即编译),编译器的编译结果最后会提交电子计算机执行。
  随着程序设计语言的不断变化,编译器也会不断更新。例如,GCC(the GNU Compiler Collection)就已经更新到了13.2.0版本[1]。不同版本的编译器在编译同一程序脚本时,编译结果会存在一定的差异;相同版本的编译器在使用不同编译选项时,编译结果也会出现差异。能否利用编译结果差异区分编译器的版本?你们的任务是
  问题1 使用GCC中不同版本的C++编译器编译附件1中的程序源代码[2],并对比使用默认编译选项时的编译结果。找出区分这些编译结果的主要特征。
  问题2 根据问题一中得到的特征,构造一个判别函数,使得能从各版本C++编译器使用默认编译选项时的编译结果,判别区分编译器版本。
  问题3 用GCC中不同版本的C++编译器编译附件2中的源程序代码[3],给出直接使用问题2中得到的判别函数区分编译器区版本的结果。研究使用附件1、2原代码编译结果之一都能区分GCC中不同版本的C++编译器的判别函数。
  问题4 给出几条提高由编译结果区分编译器版本的判别函数性能的建议,包括区分度和对原代码的泛化性。

整体求解过程概述(摘要)

编译器作为将高级语言转换为机器语言的工具,在软件开发过程中扮演着至关重要的角色。然而,不同版本的编译器可能会引入不同的优化策略、错误修复和安全补丁,这可能导致生成的汇编代码在性能、安全性和兼容性方面存在差异。因此,准确识别编译器版本对于确保软件的质量和安全性具有重要意义。
  为了构建有效的机器学习模型,我们首先需要从汇编代码中提取能够反映编译器版本差异的特征。经过深入分析,我们选择了以下关键特征:
  操作码频率:不同版本的编译器可能会选择不同的指令序列来实现相同的功能,因此操作码的频率可以作为一个有效的特征。
  寄存器使用率:编译器在优化代码时,可能会根据寄存器的可用性和使用效率来分配寄存器。因此,寄存器使用率也可以反映编译器版本的差异。
  Bigram数量:Bigram是指相邻的两个操作码或寄存器的组合。通过分析Bigram的数量和分布,我们可以捕捉到编译器在生成代码时的某些模式或偏好。
  基于提取的特征,我们构建了Gini决策树模型进行编译器版本的判别。Gini指数是一种衡量数据不纯度的指标,通过递归地选择最优分裂特征和分裂点,我们可以构建一个能够准确识别编译器版本的决策树模型。
  虽然Gini决策树模型在一定程度上能够识别编译器版本,但其性能仍存在局限性。为了进一步提升性能,我们引入了XGBoost模型。XGBoost是一种高效的梯度提升算法,通过集成多个弱分类器来构建一个强分类器,具有出色的性能和稳定性。
  此外,我们还讨论了以下优化模型的方法:
  增加数据集多样性:通过收集更多不同版本编译器的汇编代码样本,我们可以提高模型的泛化能力和准确性。
  引入自动特征提取:利用深度学习等技术自动提取汇编代码中的特征,可以减少人工特征工程的复杂性,并可能发现更多潜在的有用特征。
  结合静态和动态特征:除了分析汇编代码的静态特征外,我们还可以考虑结合程序的动态执行信息(如执行时间、内存使用情况等)来构建更全面的模型。
  编译器版本识别在现实中具有广泛的应用价值。例如,它可以帮助检测和预防编译器相关的安全漏洞,确保软件的安全性;同时,它还可以用于评估和优化编译器的性能,提高软件的运行效率。此外,编译器版本识别还可以为软件逆向工程、恶意软件分析等领域提供有力支持。
  本文提出了一种基于机器学习的编译器版本识别解决方案,通过提取汇编代码中的关键特征并构建Gini决策树和XGBoost模型进行判别。我们还讨论了多种优化模型的方法,并指出了编译器版本识别在现实应用中的重要价值。未来,我们将继续深入研究这一问题,探索更多有效的特征提取方法和模型优化策略,以提高编译器版本识别的准确性和效率。

模型假设:

1. 假设不同版本编译器对于实现同一功能,偏向于使用某些特定的操作码与寄存器。因为随着硬件的进步,指令更新,编译器将采用新的指令以实现更快的功能。
  2. 假设采用Windows 下的 mingw64 进行编译源代码。因为附件 1 中的源代码含有easyx 图形库,导致gcc 无法在Linux 系统下编译代码。所以我们考虑到既要能够编译,也要使用与gcc相关的编译器,故使用mingw64。
  3. 假设不提取汇编文件".ident"的相关特征。无论是gcc还是mingw64采用默认编译出来的汇编文件,都含有".ident"这一项,该项会直接注明汇编文件是由哪个版本的编译器生成的。我们考虑到实际应用中需要判别的是二进制文件,通过二进制文件反编译成汇编文件会失去'.ident' 这个特征。

问题分析:

问题一分析
  问题一要求我们提取出不同版本GCC编译附件1结果中的主要特征,以用于构建判别函数。为此,我们首先利用VsCode的文本比较工具,了解各个汇编文件的差异,之后编写程序实现对多个版本编译的汇编文件进行特征提取。我们将考虑提取操作码和寄存器的频率、Bigram(连续两个指令组合)的数量、代码块数量等特征,这些特征能更全面地反映不同版本编译器的行为差异。通过对这些特征的分析,我们为后续的问题二提供了坚实的数据基础。
  问题二分析
  在问题一的基础上,我们需要利用提取的特征数据构建判别函数。这是一个典型的多分类问题,特征数据将作为输入变量,不同的GCC版本作为标签类别。我们将使用机器学习算法,如Gini决策树、随机森林等,来构建判别模型。通过这些算法,我们能够实现不同版本GCC编译结果的有效分类和识别,并为后续的问题三提供强大的模型支持。
  问题三分析
  问题三要求利用构建的判别器对不同版本GCC编译附件2的结果进行版本预测。在这个阶段,我们将模型应用于未见过的源代码2生成的汇编文件数据上,以验证其普适性和准确性。考虑到题目要求根据源代码1或2都能构建GCC版本判别函数,我们认为数据规模过小,难以构建具有泛化性的判别函数,所以选择增加数据集规模,以求构建具有高泛化性的判别函数。
  问题四分析
  为了进一步提升判别函数的性能,我们提出了以下改进建议:首先,可以尝试引入深度学习模型,进行自动特征提取,再基于如Transformer的注意力机制模型,以捕捉更复杂的特征关系;其次,增加数据集的多样性,涵盖不同类型、不同规模的源代码,并通过不同的编译优化级别生成更多样的训练数据;最后,通过结合静态和动态特征,使模型能够从多个维度进行学习和预测,从而提高模型的泛化能力和预测准确率。

模型的建立与求解整体论文缩略图

全部论文请见下方" 只会建模 QQ名片" 点击QQ名片即可

程序代码:

python 复制代码
import os
import re

def process_assembly_file(input_file, output_file):
    # 读取原始汇编文件
    with open(input_file, 'r', encoding='utf-8') as file:
        lines = file.readlines()

    # 创建一个新的列表来存储修改后的内容
    processed_lines = []

    # 遍历原文件的每一行
    for line in lines:
        # 将逗号替换为空格
        line = line.replace(',', ' ')

        # 去除每行的前后空格
        stripped_line = line.strip()

        # 跳过以 . 开头或以 : 结尾的行
        if stripped_line.startswith('.') or stripped_line.endswith(':'):
            continue

        # 按空格分割行内的内容,得到每个单词
        words = re.split(r'\s+', stripped_line)

        # 处理每个单词
        processed_words = []
        for word in words:
            # 查找是否有括号,并替换为括号内的内容
            match = re.search(r'\((%[a-zA-Z0-9]+)\)', word)
            if match:
                word = match.group(1)

            # 处理以 $ 开头的单词
            if word.startswith('$'):
                if re.match(r'\$\d+', word):  # 如果 $ 后跟数字
                    word = '$0'
                elif re.match(r'\$-', word):  # 如果 $ 后跟负号
                    word = '$0'
                elif word.startswith('$.'):  # 如果 $ 后跟 .
                    word = '$.'
                elif word.startswith('$g'):  # 如果 $ 后跟 g
                    word = '$g'

            processed_words.append(word)

        # 将处理后的单词重新组合成一行
        processed_line = ' '.join(processed_words)
        processed_lines.append(processed_line + '\n')  # 保持行的格式

    # 写入新的汇编文件
    with open(output_file, 'w', encoding='utf-8') as file:
        file.writelines(processed_lines)


def process_all_files(input_folder, output_folder):
    # 如果输出文件夹不存在,则创建
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    # 遍历输入文件夹中的所有文件
    for filename in os.listdir(input_folder):
        # 构造完整的文件路径
        input_file = os.path.join(input_folder, filename)
        output_file = os.path.join(output_folder, filename)

        # 处理每个文件
        process_assembly_file(input_file, output_file)


input_folders = ['8.4.0', '10.2.0', '11.3.0', '12.2.0', '13.2.0']
output_folders = [f"{folder}_processed" for folder in input_folders]

print(output_folders)

# 处理所有文件
for input_folder, output_folder in zip(input_folders, output_folders):
    process_all_files(input_folder, output_folder)

print("所有文件处理完毕。")
python 复制代码
import csv
import os
from collections import Counter

file_count = 0  # 初始化文件计数器


def process_folder(folder_name):
    data = []
    global file_count
    file_count += 1  # 每处理一个文件夹,计数器加一
    for filename in os.listdir(folder_name):
        print(f"Processing {filename}...")
        if 'test' not in filename:
            print(f"Skipping {filename}...")
            continue
        file_path = os.path.join(folder_name, filename)
        with open(file_path, 'r') as file:
            word_counter = Counter()
            bigram_counter = Counter()
            first_word_list = []

            for line in file:
                words = line.strip().split()
                if not words:
                    continue
                first_word_list.append(words[0])
                word_counter.update(words)
                bigram_counter.update(zip(words[:-1], words[1:]))

            # 计算四元组(四个连续单词)的频率
            quadgram_counter = Counter(
                zip(first_word_list[:-3], first_word_list[1:-2],
                    first_word_list[2:-1], first_word_list[3:]))

            # 筛选频率大于10的特征
            word_features = {
                word: count
                for word, count in word_counter.items() if count > 10
            }
            bigram_features = {
                " ".join(bigram): count
                for bigram, count in bigram_counter.items() if count > 10
            }
            quadgram_features = {
                " ".join(quadgram): count
                for quadgram, count in quadgram_counter.items() if count > 10
            }

            # 构建一行数据
            features = {
                **word_features,
                **bigram_features,
                **quadgram_features
            }
            features['label'] = file_count  # 标签为当前文件的编号

            data.append(features)

    return data


def save_to_csv(data, output_file):
    keys = set()
    for row in data:
        keys.update(row.keys())

    keys = sorted(keys)  # 按字母排序,确保一致性
    with open(output_file, 'w', newline='') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=keys)
        writer.writeheader()
        for row in data:
            writer.writerow(row)


# 定义已处理的文件夹列表
processed_folders = [
    '8.4.0_processed', '10.2.0_processed', '11.3.0_processed',
    '12.2.0_processed', '13.2.0_processed'
]

# 初始化用于保存所有文件夹数据的列表
all_data = []

# 遍历每个文件夹并处理数据
for folder in processed_folders:
    folder_data = process_folder(folder)
    all_data.extend(folder_data)

# 保存合并后的数据到CSV文件
save_to_csv(all_data, 'no_our_data.csv')
全部论文请见下方" 只会建模 QQ名片" 点击QQ名片即可
相关推荐
JEECG低代码平台2 小时前
【开源大屏】玩转开源积木BI,从0到1设计一个大屏
数据分析·数据可视化
大数据编程之光3 小时前
Hive 窗口函数与分析函数深度解析:开启大数据分析的新维度
hive·hadoop·数据分析
零光速5 小时前
数据处理与统计分析——10-Pandas可视化-Matplotlib的常用API
数据结构·python·数据分析·pandas·matplotlib
数据龙傲天11 小时前
大数据时代下的电商API接口创新应用
爬虫·python·数据分析·api
Yaooooo811 小时前
【数学建模】利用Matlab绘制线图(1)
开发语言·数学建模·matlab
Python当打之年12 小时前
【55 Pandas+Pyecharts | 实习僧网Python岗位招聘数据分析可视化】
python·信息可视化·数据分析·pandas
康谋自动驾驶14 小时前
康谋方案 | 多源相机数据采集与算法集成测试方案
人工智能·科技·数据分析·自动驾驶·汽车
Genevieve_xiao14 小时前
【数模学习笔记】灰色关联分析
笔记·学习·数学建模
Genevieve_xiao14 小时前
【数模学习笔记】模糊综合评价
笔记·学习·数学建模
千瓜16 小时前
2024年特别报告,「十大生活方式」研究数据报告
大数据·数据挖掘·数据分析·业界资讯·新媒体