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名片即可
相关推荐
AIGC大时代12 小时前
分享14分数据分析相关ChatGPT提示词
人工智能·chatgpt·数据分析
SelectDB12 小时前
Apache Doris 2.1.8 版本正式发布
大数据·数据库·数据分析
Dipeak数巅科技14 小时前
数巅科技连续中标大模型项目 持续助力央国企数智化升级
大数据·人工智能·数据分析
Ray.199814 小时前
Flink 的核心特点和概念
大数据·数据仓库·数据分析·flink
一只码代码的章鱼14 小时前
粒子群算法 笔记 数学建模
笔记·算法·数学建模·逻辑回归
云天徽上18 小时前
【数据可视化】全国星巴克门店可视化
人工智能·机器学习·信息可视化·数据挖掘·数据分析
大嘴吧Lucy18 小时前
大模型 | AI驱动的数据分析:利用自然语言实现数据查询到可视化呈现
人工智能·信息可视化·数据分析
艾思科蓝 AiScholar18 小时前
【连续多届EI稳定收录&出版级别高&高录用快检索】第五届机械设计与仿真国际学术会议(MDS 2025)
人工智能·数学建模·自然语言处理·系统架构·机器人·软件工程·拓扑学
胡萝卜不甜1 天前
数学建模论文通用模板(细节方法二)
数学建模
浏览器爱好者1 天前
如何在Python中进行数据分析?
开发语言·python·数据分析