# 5.3 gdb和汇编代码执行

接下来我们来看一些真实的汇编代码。

![](/files/-MM0O7F87I4yrfDs2tnM)

图中的代码，上半部分的注释是对应的C代码，这是个简单的函数，它累加了从1到n的所有数字，并返回结果。下半部分是可以编译出的最简单的汇编代码。如果你在你自己的计算机编写同样的C代码并编译，你得到的极有可能是差别较大的汇编代码。这里有很多原因，有一些原因我们之后会讲，有一些原因是因为编译器。当将C代码编译成汇编代码时，现代的编译器会执行各种各样的优化，所以你们自己编译得到的汇编代码可能看起来是不一样的。例如，当你在gdb中做debug的时候，有时候你会看到gdb提示你说某些变量被优化掉了，这意味着编译器决定了自己不再需要那个变量，变量以及相关的信息会在某个时间点删掉。

上图中的代码都很直观，首先将寄存器a0中的值保存在寄存器t0中。之后将寄存器a0设置为0，之后在每个循环中将t0中的数据加到a0中，直到t0变成0。这就是代码的所有内容。

> 学生提问：这里面.secion，.global，.text分别是什么意思？
>
> TA：global表示你可以在其他文件中调用这个函数。text表明这里的是代码，如果你还记得XV6中的图3.4，

![](/files/-MM0X_s13Uk2By7Qk_gJ)

> 每个进程的page table中有一个区域是text，汇编代码中的text表明这部分是代码，并且位于page table的text区域中。text中保存的就是代码。

如果你对内核比较感兴趣，在编译完之后，你可以查看kernel.asm文件，你可以看到XV6完整内核的汇编版本。文件中每一行左边的数字表明的是这条指令会在内存中的哪个位置，这个信息非常有用。在汇编代码中还可以看到函数对应的label，以及它们是在哪里定义的。这些信息在我们调试代码的时候可能会非常非常有用，我稍后会展示这部分。

> 学生提问：.asm文件和.s文件有什么区别？
>
> TA：我并不是百分百确定。这两类文件都是汇编代码，.asm文件中包含大量额外的标注，而.s文件中没有。所以通常来说当你编译你的C代码，你得到的是.s文件。如果你好奇我们是如何得到.asm文件，makefile里面包含了具体的步骤。

现在回到函数sum\_to，我们看一下如何在gdb中检查这个函数。首先是要启动QEMU，

![](/files/-MM0dRLzKlv9Pgjb7i3C)

在另一个窗口打开gdb，

![](/files/-MM0dhzmT1sIf7EgwRx9)

gdb中输入tui enable可以打开源代码展示窗口。

sum\_to的代码现在都位于内核中，我在sum\_to中设置一个断点。然后继续代码的执行，代码在断点处停住。

![](/files/-MM0iOV59oR1qy2YHyWQ)

gdb窗口的左上角是程序计数器，我们可以看到当前的值是0x800065e2。如果我们去kernel.asm中，查找这个地址，我们可以看到这个地址就是sum\_to函数的起始地址。

![](/files/-MM0ix3GIZvCLp3F64QT)

如果代码出现了问题，在gdb中看到的地址，你可以直接在kernel.asm找到具体的行，分析问题的原因，然后再向相应的地址设置断点。

在gdb中输入layout asm，可以在tui窗口看到所有的汇编指令。再输入layout reg可以看到所有的寄存器信息。

![](/files/-MM0kg6lrwTwvEvi3DGW)

在寄存器窗口，可以看到t0，a0寄存器的值。在执行完一条汇编指令之后，t0寄存器拥有了a0寄存器的内容，也就是5。在寄存器窗口，更新了的寄存器会被高亮出来。

![](/files/-MM0ljIcOgoZ2JsdB3Sp)

之后持续的单步执行代码，直到函数返回。

如果你关心你设置了哪些断点，或着你跟踪代码的时候迷糊了，你可以在gdb中输入info breakpoints，你可以看到所有设置了的断点。你甚至可以看到这个断点已经被命中了几次。

![](/files/-MM0oGlP-Go7kovjzc5e)

类似的，你也可以通过输入info reg查看寄存器的信息。

> 学生提问：你是怎么打开多个terminal窗口的？
>
> TA：我是通过tmux打开的。（30:27 - 31:45在介绍tmux，与课程无关故跳过）
>
> 学生提问：为什么这里展示的是汇编代码而不是C代码？
>
> TA：从最初的代码可以看出，这里的程序完全是汇编代码实现的，所以自然也没有关联的C程序。如果我将断点设置在C代码中，在命中断点之后输入layout split或者layout source，就可以看到相应的C代码了。
>
> layout split会同时展现C代码和汇编，而layout source只会展示C代码。
>
> 学生提问：在C代码中，断点设置在某一行，如果这一行有多个语句的话，断点会设置在哪个语句？
>
> TA：断点会设置在第一个语句。

gdb和tmux有上百个快捷指令，可以通过google去查找，对于gdb，也可以使用apropos指令查看帮助。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mit-public-courses-cn-translatio.gitbook.io/mit6-s081/lec05-calling-conventions-and-stack-frames-risc-v/5.3-gdb-he-hui-bian-dai-ma-zhi-hang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
