视频加载失败

课程

1906 字
约 6 分钟

GPT

计算机系统基础exercises/Homework/RainClass/chapter03·更新于 2026-09-15

CSAPP P.163

int sw(int x){

    int v = 0;

    switch (x) {

        /* ... ... */

    }

    return v;

}
1   movl        8(%ebp), %eax

2   addl        $3, %eax

3   cmpl        $7, %eax

4   ja          .L7

5   jmp         *.L8(,%eax,4)

6 .L7 :

7   ...

8   ...

1 .L8 :

2   .long       .L7

3   .long       .L2

4   .long       .L2

5   .long       .L3

6   .long       .L4

7   .long       .L5

8   .long       .L7

9   .long       .L6

(1)取值0和6对应.L7 ​取值为1和2对应.L2 ​取值3对应.L3 ​取值4对应.L4 ​取值为5对应.L5 ​取值为7对应.L6

(2).L7是default分支,根据符号表,取值为0和6时会执行default

(3).L2,当取值为1和2时会执行相同的分支.L2

GPT

1. 函数 sw 中的 switch 语句处理部分标号的取值情况:

汇编代码分析:

1   movl        8(%ebp), %eax        // 将函数参数 x(从栈中偏移8的位置)加载到 %eax 寄存器中
2   addl        $3, %eax             // 将 %eax 寄存器中的值加 3
3   cmpl        $7, %eax             // 比较 %eax 与 7
4   ja          .L7                  // 如果 %eax > 7(即x + 3 > 7),跳转到 .L7 标签(default 分支)
5   jmp         *.L8(,%eax,4)        // 根据 %eax 的值跳转到一个跳表地址,L8 是一个跳表的起始地址
6 .L7 :
7   ... // default 分支代码
8   ... // 其他代码

第1到第5行switch 语句的核心逻辑:

  • 第 1 行:将 x 传递的参数加载到 eax 寄存器。
  • 第 2 行:x 加 3。注意到这一点,意味着 x 可能会被偏移。
  • 第 3 行:比较 eax 的值与 7。
  • 第 4 行:如果 eax > 7(即 x + 3 > 7),则跳转到标签 .L7,即进入 default 分支。
  • 第 5 行:如果 eax <= 7,则根据 eax 的值选择一个跳转地址,这个地址由 .L8 标签后面的跳表来决定。

跳表地址(从 .L8 开始):

6 .L8 :
2   .long       .L7
3   .long       .L2
4   .long       .L2
5   .long       .L3
6   .long       .L4
7   .long       .L5
8   .long       .L7
9   .long       .L6

.L8 开始的指令是一个跳表,其中每个 .long 指令指定一个跳转地址。具体来说:

  • eax的值从 0 到 7,跳表的值依次对应着这些情况:

    • eax == 0 跳转到 .L7(这应该是 default 分支)
    • eax == 1 跳转到 .L2
    • eax == 2 跳转到 .L2
    • eax == 3 跳转到 .L3
    • eax == 4 跳转到 .L4
    • eax == 5 跳转到 .L5
    • eax == 6 跳转到 .L7(这也会跳到 default 分支)
    • eax == 7 跳转到 .L6

2. 标号的取值在什么情况下执行 default 分支?

  • 标号执行 default 分支的条件:

    • 如果 x + 3 > 7(即 x > 4),则跳转到 .L7,执行 default 分支。
    • 另外,eax == 0eax == 6 时,也会跳转到 .L7,因此这些情况下也会执行 default 分支。

3. 哪些标号的取值会执行同一个 case 分支?

  • 执行同一个 case 分支的标号:

    • eax == 1eax == 2 都会跳转到 .L2,所以它们会执行相同的 case 逻辑。

    其他的标号(eax == 0eax == 3 eax == 4eax == 5eax == 6eax == 7)分别跳转到不同的标签(.L7.L3.L4.L5.L7.L6)。

总结:

  • default 分支 会在 eax 等于 0 或 6,或者 x 大于 4 时执行。
  • 相同 case 分支eax == 1eax == 2 会跳转到 .L2,即它们会执行相同的代码块。

Copilot

在函数 sw 中,switch 语句处理部分的标号取值情况如下:

  1. 标号的取值情况

    • 汇编代码中,movl 8(%ebp), %eax 将参数 x 的值加载到寄存器 eax 中。
    • addl $3, %eaxeax 的值加3。
    • cmpl $7, %eax 比较 eax 的值与7。
    • ja .L7 如果 eax 的值大于7,则跳转到 .L7,执行 default 分支。
    • jmp *.L8(,%eax,4) 根据 eax 的值跳转到对应的标签。
  2. 标号的取值在什么情况下执行 default 分支

    • eax 的值大于7时,跳转到 .L7,执行 default 分支。
    • 由于 eax 的值是 x + 3,所以当 x + 3 > 7 时,即 x > 4 时,执行 default 分支。
  3. 哪些标号的取值会执行同一个 case 分支

    • .L8表中的值决定了跳转的目标标签:

      • .long .L7 对应 eax 为0或7,即 x 为-3或4,执行 default 分支。
      • .long .L2 对应 eax 为1或2,即 x 为-2或-1,执行相同的 case 分支。
      • .long .L3 对应 eax 为3,即 x 为0,执行 case 分支 .L3
      • .long .L4 对应 eax 为4,即 x 为1,执行 case 分支 .L4
      • .long .L5 对应 eax 为5,即 x 为2,执行 case 分支 .L5
      • .long .L6 对应 eax 为6,即 x 为3,执行 case 分支 .L6

总结:

  • default 分支在 x > 4x == -3 时执行。
  • case 分支 .L2x == -2x == -1 时执行。
Profile Image of the Author
Sonder
好想要技术
这是公告标题
这只是一个公告
分类
标签
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.16.7
文章许可
CC BY-NC-SA 4.0
文章目录