开发者
资源
【专业实习Day2】openEuler 系统环境实验
【专业实习Day2】openEuler 系统环境实验
发表于2025/07/08
1230

openEuler 系统环境实验报告

一、 实验目的

  1. 学习在鲲鹏平台上查看 openEuler 操作系统及硬件系统信息的方法
  2. 通过对比实验,理解 C 语言基本数据类型(如 char)在不同 CPU 架构(aarch64 vs. x86_64)下的差异
  3. 通过反汇编 C 程序,初步体验 aarch64 精简指令集(RISC)的特点
  4. 掌握在 C 代码中嵌入内联汇编以及编写并执行纯汇编程序的基本方法
  5. 加深对操作系统、CPU 架构和上层应用软件之间关系的理解

二、 实验环境

环境/工具说明
硬件平台华为云服务器(ECS)
操作系统openEuler 22.03 LTS
编译器/工具GCC 编译器、as 汇编器、ld 链接器、objdump 反汇编工具
登录方式本地终端、SSH 远程登录

三、 实验内容与步骤

(1)查看系统信息

  1. 查看系统架构与内核版本

    # 查看CPU架构 (应显示 aarch64)
    uname -m
    
    # 查看内核版本
    uname -r
    
    # 查看所有系统信息
    uname -a
  2. 查看 CPU 详细信息

    lscpu

    获取 CPU 的详细规格,如型号(Kunpeng-920)、核心数、线程数、缓存大小、字节序(Little Endian)等

    屏幕截图 2025-07-08 093738.png

  3. 查看 openEuler 操作系统版本

    cat /etc/os-release

    屏幕截图 2025-07-08 135832.png

(2)观察 C 语言 char 数据类型

  1. 准备 C 源代码 (char.c):

    #include <stdio.h>
    
    int main() {
      // -1 的二进制补码为 0xff
      char ch = -1;
    
      printf("sizeof ch is %zu\n\n", sizeof(ch));
    
      // 在不同平台,默认的 char 类型可能是有符号或无符号的
      printf("default char ch = 0x%2x, %+4d\n", ch & 0xff, ch);
      printf("signed char ch = 0x%2x, %+4d\n", (signed char)ch & 0xff, (signed char)ch);
      printf("unsigned char ch = 0x%2x, %+4d\n", (unsigned char)ch & 0xff, (unsigned char)ch);
    
      return 0;
    }
  2. 编译并执行:

    gcc char.c -o ch
    ./ch

    default char 的输出值应为 +255,表现与 unsigned char 一致。在鲲鹏 aarch64 平台上,GCC 编译器默认将 char 类型处理为 unsigned char
    屏幕截图 2025-07-08 100133.png

  3. 在 x86_64 平台对比实验:
    在 x86_64 环境下执行相同操作。default char 的输出值应为 -1,表现与 signed char 一致。在 x86_64 平台上,GCC 默认将 char 处理为 signed char

  4. 引申实验:
    编译器选项可以覆盖平台的默认行为。在鲲鹏平台使用 -fsigned-char 编译选项,观察结果是否与 x86_64 平台一致

    gcc -fsigned-char char.c -o ch
    ./ch

    屏幕截图 2025-07-08 134704.png

(3)体验 aarch64 架构精简指令集

  1. 准备 C 源代码 (abc.c):

    int main() {
        int a = 1;
        int b = 2;
        int c = a + b;
        return a + b + c;
    }
  2. 编译并反汇编:

    # -g 参数是为了在反汇编代码中关联C源码
    gcc -g abc.c
    objdump -S ./a.out

    屏幕截图 2025-07-08 100324.png

  3. 分析: 观察 objdump 输出的汇编代码。aarch64 的指令通常是定长的,且采用“加载-存储”(Load-Store)架构,即内存操作和计算操作分离,这与 x86_64 复杂多变的指令格式形成对比。

(4)C 代码中的内联汇编

  1. 准备 C 源代码 (add.c):

    #include <stdio.h>
    #include <stdlib.h>
    
    int add(int i, int j) {
        int res = 0;
        // 使用内联汇编执行加法操作
        // %w[result] 表示32位寄存器
        asm (
            "ADD %w[result], %w[input_i], %w[input_j]"
            : [result] "=r" (res)
            : [input_i] "r" (i), [input_j] "r" (j)
        );
        return res;
    }
    
    int main(int argc, char *argv[]) {
        if (argc < 3) {
            printf("Usage: %s <int> <int>\n", argv[0]);
            return -1;
        }
        int i = atoi(argv[1]);
        int j = atoi(argv[2]);
        printf("%d + %d = %d\n", i, j, add(i, j));
        return 0;
    }
  2. 编译并执行:

    gcc -o add add.c
    ./add 10 20

    程序输出 10 + 20 = 30,成功地在 C 代码中调用了 aarch64 的 ADD 指令来完成计算
    屏幕截图 2025-07-08 134938.png

(5)纯汇编程序

  1. 准备汇编源代码 (hello.s):

    # hello.s for Kunpeng aarch64
    .text
    .global _start
    
    _start:
        # write(fd, buf, len) 系统调用
        # fd = 1 (stdout) -> x0
        mov x0, #1
        # buf = msg 地址 -> x1
        ldr x1, =msg
        # len = 消息长度 -> x2
        mov x2, len
        # 系统调用号 64 (write) -> x8
        mov x8, #64
        # 触发系统调用
        svc #0
    
        # exit(code) 系统调用
        # code = 0 -> x0
        mov x0, #0
        # 系统调用号 93 (exit) -> x8
        mov x8, #93
        # 触发系统调用
        svc #0
    
    .data
    msg:
        .ascii "Hello, openEuler on Kunpeng!\n"
    len = . - msg
  2. 汇编与链接:

    # 使用 as 将汇编代码编译成目标文件
    as -o hello.o hello.s
    # 使用 ld 将目标文件链接成可执行文件
    ld -o hello hello.o
  3. 执行:

    ./hello

    屏幕上打印出 Hello, openEuler on Kunpeng!
    屏幕截图 2025-07-08 135122.png

四、实验心得

通过本次系列实验,我从多个层面探索了鲲鹏平台上的 openEuler 系统环境。我不仅学会了如何查询基本的系统信息,还通过具体的代码示例,深入理解了不同硬件架构对上层软件(特别是 C 语言编译器)行为的影响。此外,通过反汇编和直接编写汇编代码,我对 aarch64 指令集有了更直观的认识,并掌握了底层系统调用的方法。这些实验为在鲲鹏平台上进行更复杂的系统编程和性能优化打下了坚实的基础。

收藏举报
Level 1
0
帖子
0
粉丝
0
获赞