0

我正在学习linux内核源代码。

而且我已经对汇编语言有了一些基本的了解,比如通用指令的使用(例如mov, add, jmp, call...),AT&T 类型和 Intel 类型的区别。

因此,就目前而言,了解这些 asm 代码在做什么的粗略概念对我来说不是什么大问题。但是这些指令,比如.text .data显示在下面代码的头部和尾部,让我很困惑。

.text所以,我的直接问题是pair, pair的含义是什么.data?我的根本问题是什么是 asm 版本或键入这些语法?我认为这是对英特尔的颠覆,因为常量前没有“$”。但是为什么有'#'和'_start'而不是'main'呢?我在哪里可以找到所有这些相关 asm 语法的完整介绍?

请帮帮我!</p>

非常感谢!

.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

BOOTSEG  = 0x07c0           ! original address of boot-sector
INITSEG  = 0x9000           ! we move boot here - out of the way
SETUPSEG = 0x9020           ! setup starts here

entry _start
_start:
    mov ah,#0x03        
    xor bh,bh
    int 0x10
... ...

.text
endtext:
.data
enddata:
.bss
endbss:
4

2 回答 2

0

您正在寻找不同的东西:启动代码。

引导代码必须是 16 位的,并且是特殊的。它还需要不同的汇编器(16 位,实模式)。

所以,我们处于 16 位实模式,所以我们有段。这.text是针对 CS 段的(因此 .text 上的偏移量是相对于 CS 的)。.data段是预期的DS,但这可以改变(你可以告诉汇编程序,这样它就会知道计算偏移量是热的)。

注意:启动代码也比较特殊,因为 BIOS 在 07C0h:0000h 加载启动代码并运行它,但是我们移动它,运行第二部分,所以相同的代码会有不同的 CS 段(你可能会发现一些 LONG JUMP可能看起来没有必要)。然后加载其余的引导代码。然后设置东西(在 BIOS 级别和硬件级别,例如恢复 A20 行),然后准备内存表(我们仍然只有第一 MB 可用内存(BIOS 使用一些内存)用于受保护和 32 位模式,所以我们可以切换、刷新缓存并在 32 位中执行。然后是其余的设置。

编辑:添加更多解释。

我们处于 16 位实模式,因此内存地址由两个部分计算:段和偏移量(都是 16 位长,段移位 4 位)。所以当前代码在 CS:IP 中,通常我们在 DS 段中读取数据(很少有例外,或者我们可以明确给出段)。

当您组装代码时,您会在不同的段中获得不同的部分。

.text
begtext:

第一行声明:我们现在在.text段中(text通常用于代码)。下一行我们声明一个 label: begtext,我假设它是 for beginning of our text segment

您对其他段 (.data.bss) 执行相同操作。原因是我们想知道初始偏移量,所以我们可以移动数据(我们不知道汇编器或加载器是否会将 as 放在不同的偏移量,所以在开始时定义标签是安全的,所以我们可以使用它,如果我们需要移动代码)。您会在文件末尾看到相同的内容(例如endtext),以了解最后一点,以及所用段的大小(endtext - begtext)。

注意:我们不能移动整个段,因为段可能重叠,或者 CS 可能是 DS,只是偏移量不同,所以我们有覆盖错误部分的风险(如果我们以不同的顺序移动代码和数据)。

entry:定义入口点:您希望加载器从_start. 但这取决于结果文件的格式(因此汇编程序指令)。有时你有org明确地告诉当前位置的地方(例如,在.com我们拥有的 DOS 文件中org 100h,IIRC,这是 DOS 调用的入口点)。

您还定义了一些常量(07c0 是由 PC 上的 BIOS 加载和执行引导扇区的位置)。

.glovl只是将这些值声明为“全局”,以便导出并在其他模块上可用,如果您想“链接”多个文件。

于 2021-06-18T09:58:52.760 回答
0

您可以在汇编器的文档中找到所有这些相关的 asm 语法的完整介绍。与机器指令不同,例如mov, add, jmp, call,,,有许多指令和伪指令未规范化,它们取决于语言作者的个性和经验。

声明.globl begtext, begdata, begbss, endtext, enddata, endbss声明某些标签(稍后在源文本中的某处定义)将是 GLOBAL 别名 PUBLIC,即它们可以从与内核链接的其他程序模块访问。

标签.text, .data, .bss指示汇编器将其输出(发出的代码和数据)重定向到特定段的指令。可执行程序文件包含一个带有机器指令的段(.text别名.code)和数据段(.data, .rodata, .bss),但源文本不必按此顺序编写。想象一下,Linus(或任何编写源代码的人)是老板,他将源代码口授给他的秘书(汇编程序)。他告诉它发出三个指令,使用 BIOS 服务INT 0x10将控制台切换到 80*25 文本模式:

.text
 mov ah,#0x03        
 xor bh,bh
 int 0x10

秘书将在一张标有 的纸上写下(发出)这些指示.text。然后 Linus 决定定义一些消息,所以他告诉秘书指令.data,然后是消息定义:

.data    
 Message DB "Kernel is starting, please wait."

秘书将抓起另一张纸,贴上标签.data并在上面写下消息定义。当 Linus 决定口述其他机器代码时,秘书收回工作表.text并在中断的地方(原点)继续写 - 在指令下方INT 0x10通过这种方式,他们可以随意交替输出段并将数据保持在使用它操作的代码附近(这有利于程序的可读性)。最后,所有纸张将被装订(链接)在一起,因此所有机器指令在段中彼此靠近.text,并且在段中相似的数据.data

于 2021-06-18T07:33:01.007 回答