第11章-数学协处理器_第1页
第11章-数学协处理器_第2页
第11章-数学协处理器_第3页
第11章-数学协处理器_第4页
第11章-数学协处理器_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第 11 章 数学协处理器 内核目录 kernel math 目录中包含数学协处理器仿真处理代码文件 共包含 9 个 C 语言程 序 见表 11 1 本章内容与具体硬件结构关系非常密切 因此需要读者具备较深的有关 Intel CPU 和协处理器指令代码结构的知识 但好在这些内容与内核实现关系不大 因此跳过本章 内容并不会妨碍读者对内核实现方法的完整理解 不过若能理解本章内容 那么对于实现系统 级应用程序 例如汇编和反汇编等程序 和编制协处理器浮点处理程序将有很大帮助 表 11 1 linux kernel math 目录 名称大小 B最后修改时间名称大小 B最后修改时间 Makefile 33771991 12 31 12 26 48 ea c 1807 1991 12 31 11 57 05 add c 1999 1992 01 01 16 42 02 error c 234 1991 12 28 12 42 09 compare c 904 1992 01 01 17 15 34 get put c 5145 1992 01 01 01 38 13 convert c 4348 1992 01 01 19 07 43 math emulate c 11540 1992 01 07 21 12 05 div c 2099 1992 01 01 01 41 43 mul c 1517 1992 01 01 01 42 33 11 1 总体功能描述 在计算机上执行计算量较大的运算通常可以使用三种方法来完成 一种是直接使用 CPU 普通指令执行计算 由于 CPU 指令是一类通用指令 因此使用这些指令进行复杂和大量的运 算工作需要编制复杂的计算子程序 并且一般只有通晓数学和计算机的专业人员才能编制出这 些子程序 另一种方法是为 CPU 配置一个数学协处理器芯片 使用协处理器芯片可以极大地 简化数学处理编程难度 并且运算速度和效率也会成倍提高 但需要另外增加硬件投入 还有 一种方法是在系统内核级使用仿真程序来模拟协处理器的运算功能 这种方法可能是运算速度 和效率最低的一种 但与使用了协处理器一样可以方便程序员编制计算程序 并且能够在对程 序不加任何改动的情况下把所编程序运行在具有协处理器的机器上 在 Linux 0 1x 甚至 Linux 0 9x 内核开发初期 数学协处理器芯片 80387 或其兼容芯片 价格不菲 并且一直是普通 PC 中的奢侈品 因此除非在科学计算量很大的场合或特别需要之 处 一般 PC 中不会安装 80387 芯片 虽然现在的 Intel 处理器中都内置了数学协处理器功能 部件 从而现在的操作系统中已经无须包含协处理器仿真程序代码 但是因为 80387 仿真程序 完全建立在模拟 80387 芯片处理结构和分析指令代码结构基础上 因此学习本章内容后读者不 仅能够了解 80387 协处理器编程方法 而且对编写汇编和反汇编处理程序也有很大帮助 如果 80386 PC 中没有包括 80387 数学协处理器芯片 那么当 CPU 执行到一条协处理器指 令时就会引发 设备不存在 异常中断 7 该异常过程的处理代码在 sys call s 第 158 行开始 处 如果操作系统在初始化时已经设置了 CPU 控制寄存器 CR0 的 EM 位 那么此时就会调用 Linux 内核完全剖析 基于 0 12 内核 546 math emulate c 程序中的 math emulate 函数来用软件 解释 执行每一条协处理器指令 Linux 0 12 内核中的数学协处理器仿真程序 math emulate c 完全模拟了 80387 芯片执行协 处理器指令的方式 在处理一条协处理器指令之前 该程序会首先使用数据结构等类型在内存 中建立起一个 软 80387 环境 包括模仿所有 80387 内部栈式累加器组 ST 控制字寄存器 CWD 状态字寄存器 SWD 和特征字 TWD TAG word 寄存器 然后分析引起异常的当前协 处理器指令操作码 并根据具体操作码执行相应的数学模拟运算 因此在描述 math emulate c 程序的处理过程之前 有必要先介绍一下 80387 的内部结构和基本工作原理 11 1 1 浮点数据类型 本节主要介绍协处理器使用的浮点数据类型 首先简单回顾一下整型数的几种表示方式 然后说明浮点数的几种标准表示方式以及在 80387 中运算时使用的临时实数表示方法 1 整型数据类型 对于 Intel 32 位 CPU 来讲 有三种基本无符号数据类型 字节 byte 字 word 和双 字 double word 分别有 8 16 和 32 位 无符号数的表示方式很简单 字节中的每个位都代 表一个二进制数 并且根据其所处位置具有不同的权值 例如一个无符号二进制数 0b10001011 可表示为 U 0b10001011 1 27 0 26 0 25 0 24 1 23 0 22 1 21 1 20 139 它对应十进制数 139 其中权值最小的一位 20 通常被称为最低有效位 LSB Least Significant Bit 而权值最大的位 27 被称为最高有效位 MSB Most Significant Bit 而计算机中具有负数值的整型数据表示方法通常也有三种 2 的补码 Two s complement 符号数 Sign magnitude 和偏置数 biased number 表示方式 表 11 2 给出了这三种形式表 示的一些数值 表 11 2 整型数的几种表示形式 十进制数2 的补码表示法偏置表示法 127 符号数表示法 128无法表示0b11111111无法表示 1270b011111110b111111100b01111111 1260b011111100b111111010b01111110 20b000000100b100000010b00000010 10b000000010b100000000b00000001 00b000000000b011111110b00000000 0无法表示无法表示0b10000000 10b111111110b011111100b10000001 20b111111100b011111010b10000010 1260b100000100b000000010b11111110 1270b100000010b000000000b11111111 1280b10000000无法表示无法表示 2 的补码 二进制补码 表示法是目前大多数计算机 CPU 使用的整数表示方法 因为 CPU 的无符号数的简单加法也适用于这种格式的数据运算 使用这种表示法 一个数的负数 就是该数每位取反后再加 1 MSB 位就是该数的符号位 MSB 0 表示一个正数 MSB 1 表 第 11 章 数学协处理器 547 示负数 80386 CPU 具有 8 位 1 字节 16 位 1 字 和 32 位 双字 2 的补码数据类型 分别可以表示的数据范围是 128 127 32768 32767 2147483648 2146473647 另外 在 80387 仿真程序中使用了一种称为临时整数类型的格式 如图 11 1 所示 它的长度为 10 字 节 可表示 64 位整型数据类型 其中低 8 字节最大可表示 63 位无符号数 而最高 2 字节仅使 用了最高有效位来表示数值的正负 对于 32 位整型值则使用低 4 字节来表示 16 位整型值则 使用低 2 字节表示 数的偏置表示法通常用于表示浮点数格式中的指数字段值 把一个数加上指定的偏置值就 是该数的偏置数表示的值 从表 11 1 可以看出 这种表示方法的数值具有无符号数的大小顺 序 因此这种表示方法易于比较数值大小 即大数值的偏置表示值总是无符号值的一个大数 而其他两种表示方式却并非如此 符号数表示法有一个位专门用于表示符号 0 表示正数 1 表示负数 而其他位则与无符 号整数表示的数值相同 浮点数的有效数 尾数 部分使用的就是这种表示方法 而符号位代 表整个浮点数的正负符号 图 11 1 仿真程序支持的临时整数格式 2 BCD 码数据类型 BCD Binary Coded Decimal 码数值是二进制编码的十进制数值 对于压缩的 BCD 编码 每个字节可表示两位十进制数 其中每 4 位表示一位 0 9 的数 例如 十进制数 59 的压缩 BCD 码表示是 0 x01011001 对于非压缩的 BCD 码 每个字节只使用低 4 位表示 1 位十进制 数 80387 协处理器支持 10 字节压缩 BCD 码的表示和运算 可表示 18 位十进制数 如图 11 2 所示 与临时整数格式类似 其中最高字节仅使用了符号位 最高有效位 来表示数值 的正负 其余位均不用 若 BCD 码数据是负数 则会使用最高地址处 1 字节的最高有效位置 1 来表示负值 否则最高字节所有位均是 0 图 11 2 80387 支持的 BCD 码数据类型 3 浮点数据类型 具有整数部分和小数 尾数 部分的数称为实数或浮点数 实际上整型数是小数部分为 0 的实数 是实数集的一个子集 由于计算机使用固定长度位来表示一个数 因此并不能精确地 表示所有实数 由于计算机表示实数时为了在固定长度位内能表示尽量精确的实数值 分配给 表示小数部分的位个数并不是固定的 即小数点是可以 浮动 的 因此计算机表示的实数数 据类型也称为浮点数 为了便于程序移植 目前计算机中都使用 IEEE 标准 754 指定的浮点数 表示方式来表示实数 Linux 内核完全剖析 基于 0 12 内核 548 这种实数表示方式的一般格式如图 11 3 所示 它由有效数 Significant 部分 指数 Exponent 部分和符号位 Sign 组成 80387 协处理器支持三种实数类型 它们每个部分 使用的位数如图 11 4 所示 图 11 3 浮点数一般格式 图 11 4 80387 协处理器使用的实数格式 其中 S 是一个位的符号位 S 1 表示是负实数 S 0 表示是正实数 有效数 Significant 给 出了实数数值的有效位数或尾数 当使用指数时 一个实数可以表示成多种形式 例如十进制 数字 10 34 可以表示成 1034 0 10 2 10 34 100 1 034 101或 0 1034 102等 为了使计算 能够得到最大精度值 我们总是对实数进行规格化 Normalize 处理 即调整实数的指数值 使得二进制最高有效数值总是 1 并且小数点就位于其右侧 因此 上述例子正确的规格化处 理结果就是 1 034 101 对于二进制数来说就是 1 XXXXX 2N 其中 X 是 1 或 0 如果我们 总是使用这种形式来表示一个实数 那么小数点左边肯定是 1 所以在 80387 的短实数 单精 度 和长实数 双精度 格式中 这个 1 就没有必要明确地表示出来 因此在短实数或长 实数的二进制有效数中 0 x0111 010 实际上就是 0 x1 0111 010 格式中的指数字段含有把一个数表示成规格化形式时所需要的 2 的幂次值 正如前面提到 的 为了便于数字大小的比较 80387 使用偏置数形式来存储指数值 短实数 长实数和临时 实数的偏置基量分别是 127 1023 和 16383 因此一个短实数指数值 0b10000000 实际表示 21 0b01111111 0b00000001 另外 临时实数是 80387 内部运算时表示数的格式 它的最高有效数 1 被明确地放置在位 63 处 并且无论你给出的数是什么数据类型的 例如 整型数 短实数或 BCD 码数等 80387 都会把它转换成临时实数格式 80387 这样做的目的是为了使得精度最大化并且尽量减 少运算过程中的溢出异常 显式地把 1 表示出来是因为 80387 在运算过程中确实需要该位 用 于表示极小的数值 当输入到 80387 中的短型或长型实数被转换成临时实数格式时 就会明 确地在位 63 处放置一个 1 4 特殊实数 与上面表中格式某些值无法表示的情况类似 使用实数格式表示的某些值也有其特殊含义 第 11 章 数学协处理器 549 对于 80 位长度格式的临时实数 80387 并没有使用其可表示的所有范围数值 表 11 3 是 80387 使用中的临时实数所能表示的所有可能的数值 其中有效数一栏虚线左侧 1 位表示临时 实数位 63 即明确表示数值 1 的位 短实数和长实数没有此位 因此也没有表中的伪非规格 化类别 下面说明其中的一些特殊值 零值 无穷值 非规格化值 伪非规格化值以及信号 NaN Not a Number 和安静 NaN 表 11 3 80387 临时实数所能表示的数值类型和范围 负号偏置型指数有效数类别 0 111 11111 11 0 111 111 安静 NaNs QNaNs Quiet NaNs 0 111 11110 00不确定值 Indefinite 0 111 11101 11 0 111 111 0 111 11100 01 信号 NaNs SNaNs Signalling NaNs 0 111 11100 00无穷数 Infinite 0 111 10111 11 0 1 1 0 100 01100 00 规格化数 正常数 Normals 0 100 00111 11 0 100 001 0 100 00100 00 伪非规格化数 Pseudo Denormals 0 100 00011 11 0 100 000 0 100 00000 01 非规格化数 Denormals 0 100 00000 00零 Zero 零是指数和有效数均为 0 的值 其余指数为 0 的值作保留 即指数是 0 的值不能表示一个 正常实数值 无穷值是指数值为全 1 有效数值为全零的值 而且指数值为 0 x11 11 的所有其 余值也作保留使用 非规格化数 Denormals 是一种用于表示非常小数值的特殊类值 它可以表示渐进下溢 或渐进精度丢失情况 通常要求数值表示成规格化数 左移直到有效数的最高有效位是位 1 然而非规格化数的有效数最高有效位不是 1 此时偏置型指数 0 x00 00 分别是值为 2 126 2 1022 2 16382的短实数 长实数和临时实数指数值的特殊表示方式 这种表示比较特殊 因为偏置型指数 0 x00 01 对三种实数类型也分别表示相同的指数值 2 126 2 1022 2 16382 伪非规格化类数值 Pseudo denormals 是有效数最高有效位为 1 的值 而非规格化类数 值的该位是 0 伪非规格化数很少见 它们可以用规格化类数来表示却没有这么做 因为上面 已经说明特殊的偏置指数 0 x00 00 与规格化数的指数 0 x00 01 具有相同的值 因此伪非规格 化类数可以表示成规格化类数值 另一种特殊情况是 NaN NaN 是指 不是一个数 Not a Number NaN 有两种形式 会产生信号 Signaling 的和不会产生信号的或称为安静的 Quiet 当一个产生信号的 NaN SNaN 被用于操作时就会引发一个无效操作异常 而一个安静的 NaN QNaN 则不 会 SnaN 是一类会引发无效操作异常的数值 使用的方法就是程序先把变量都初始化为 Linux 内核完全剖析 基于 0 12 内核 550 SNaN 值 在实际使用这个变量时还需要对其进行真正的赋值 这样若操作过程中使用了一个 未被初始化的值就会引发异常 当然 NaN 类数值也可以用来存储其他信息 80387 自身不会产生 SNaN 类的值 但会产生 QNaN 类的值 当发生无效操作异常时 80387 就会产生一个 QNaN 类值 并且操作的结果将是不确定值 Indefinite 不确定值是一 种特殊的 QNaN 类值 每种数据类型都有一个表示不确定值的数 对于整型数则是用其最大 负数来表示其不确定值 另外还有一些 80387 不支持的临时实数值 即那些没有在上表中列出的数值范围 若 80387 遇到这些数值 就会引发无效操作异常 11 1 2 数学协处理器功能和结构 80386 虽然是一个通用微处理器 但其指令并不是非常适用于数学计算 因此若使用 80386 来执行数学计算 那么就需要编制非常复杂的程序 而且执行效率也相对较低 80387 作为 80386 的辅助处理芯片 极大地扩展了程序员的编程范围 以前程序员不太可能做到的事 使用协处理器后就可以很容易地 并且快速而精确地完成 80387 具有一组特别的寄存器 这组寄存器可以让 80387 直接操作比 80386 所能处理的大 或小几个数量级的数值 80386 使用 2 进制补数方式表示一个数 这种方法不适合用来表示小 数 而 80387 并不使用 2 的补数方法来表示数值 它使用了 IEEE 标准 754 规定的 80 位 10 个字节 格式 这种格式不仅具有广泛的兼容性 而且能够使用二进制表示极大 或极小 的 数值 例如 它能表示大到 1 21 104932数值 也能处理小到 3 3 10 4932的数 80387 并不保 持固定小数点的位置 如果数值小的话就多使用一些小数位 如果数值大的话就少用几位小数 位 因此小数点的位置是可以 浮动 的 这也是术语 浮点 数的由来 为支持浮点运算 80387 中包含三组寄存器 如图 11 5 所示 8 个 80 位长的数据寄存 器 累加器 可用于临时存放 8 个浮点操作数 并且这些累加器可以执行栈式操作 3 个 16 位状态和控制寄存器 一个状态字寄存器 SWD 一个控制字寄存器 CWD 和一个特征 TAG 寄存器 4 个 32 位出错指针寄存器 FIP FCS FOO 和 FOS 用于确定导致 80387 内部异常的指令和内存操作数 第 11 章 数学协处理器 551 图 11 5 80387 的寄存器 1 栈式浮点累加器 在浮点指令执行过程中 8 个 80 位长度的物理寄存器组被作为栈式累加器使用 虽然每 个 80 位寄存器有固定的物理顺序位置 即左边的 0 7 但当前栈顶则由 ST 即 ST 0 来 指明 ST 之下的其余累加器使用名称 ST i 来指明 i 1 7 至于哪个 80 位物理寄存器是 当前栈顶 ST 则由具体操作过程指定 在状态字寄存器中名称为 TOP 的 3 位字段含有当前栈 顶 ST 对应的 80 位物理寄存器的绝对位置 一个入栈 Push 操作将会把 TOP 字段值递减 1 并把新值存储于新的 ST 中 在入栈操作之后 原来的 ST 变成了 ST 1 而原来的 ST 7 变 成了现在的 ST 即所有累加器的名称都从原来的 ST i 变成了 ST i 1 math emulate 调用者 int7 返回地址 13 long orig eip 临时保存原 EIP 的地方 14 long edi 异常中断 int7 处理过程入栈的寄存器 15 long esi 16 long ebp 17 long sys call ret 中断 7 返回时将去执行系统调用的返回处理代码 18 long eax 以下部分 18 30 行 与系统调用时栈中结构相同 19 long ebx 20 long ecx 21 long edx 22 long orig eax 如不是系统调用而是其他中断时 该值为 1 23 long fs 24 long es 25 long ds 26 long eip 26 30 行 由 CPU 自动入栈 27 long cs 28 long eflags 29 long esp 30 long ss 31 do emu 函数 第 52 行 首先根据状态字来判断有没有发生仿真的协处理器内部异常 若有则设置状态字的忙位 B 位 15 否则就复位忙位 B 然后从上述 info 结构中 EIP 字段处 取得产生协处理器异常的二字节浮点指令代码 code 并在屏蔽掉每条浮点指令码中都相同的 ESC 码 二进制 11011 位部分后 根据此时的 code 值对具体的浮点指令进行软件仿真运算 处理 为便于处理 该函数按 5 种类型浮点指令码分别使用了五个 switch 语句进行处理 例 如 第一个 switch 语句 第 75 行 用于处理那些不涉及寻址内存操作数的浮点指令 而最后 第 11 章 数学协处理器 555 两个 switch 语句 第 419 432 行 则专门用来处理操作数与内存相关的指令 对于后一种类 型的指令 其处理过程的基本流程是首先根据指令代码中的寻址模式字节取得内存操作数的有 效地址 然后从该有效地址处读取相应的数据 整型数 实数或 BCD 码数值 接着把读取 的值转换成 80387 内部处理使用的临时实数格式 在计算完毕后 再把临时实数格式的数值转 换为原数据类型 最后保存到用户数据区中 另外 在具体仿真一条浮点指令时 若发现浮点指令无效 则程序会立刻调用放弃执行函 数 math abort 该函数会向当前执行进程发送指定的信号 同时修改栈指针 esp 指向中断 过程中调用 math emulate 函数的返回地址 math ret 并立刻返回到中断处理过程中去 11 2 2 代码注释 程序 11 1 linux kernel math math emulate c 1 2 linux kernel math math emulate c 3 4 C 1991 Linus Torvalds 5 6 7 8 Limited emulation 27 12 91 mostly loads stores which gcc wants 9 even for soft float unless you use bruce evans patches The patches 10 are great but they have to be re applied for every version and the 11 library is different for soft float and 80387 So emulation is more 12 practical even though it s slower 13 14 28 12 91 loads stores work even BCD I ll have to start thinking 15 about add sub mul div Urgel I should find some good source but I ll 16 just fake up something 17 18 30 12 91 add sub mul div com seem to work mostly I should really 19 test every possible combination 20 仿真范围有限的程序 91 12 27 绝大多数是一些加载 存储指令 除非你使用了 Bruce Evans 的 补丁程序 否则即使使用软件执行浮点运算 gcc 也需要这些指令 Bruce 的补丁程序非常好 但 每 次更换 gcc 版本你都得用这个补丁程序 而且对于软件浮点实现和 80387 所使用的库是不同的 因 此使用仿真是更为实际的方法 尽管仿真方法更慢 91 12 28 加载 存储协处理器指令可以用了 即使是 BCD 码的也能使用 我将开始考虑实现 add sub mul div 指令 唉 我应该找一些好的资料 不过现在我会先仿造一些操作 91 12 30 add sub mul div com 这些指令好像大多数都可以使用了 我真应该测试每种指 令 可能的组合操作 21 22 Linux 内核完全剖析 基于 0 12 内核 556 23 This file is full of ugly macros etc one problem was that gcc simply 24 didn t want to make the structures as they should be it has to try to 25 align them Sickening code but at least I ve hidden the ugly things 26 in this one file the other files don t need to know about these things 27 28 The other files also don t care about ST x etc they just get addresses 29 to 80 bit temporary reals and do with them as they please I wanted to 30 hide most of the 387 specific things here 31 这个程序中到处都是些别扭的宏 问题之一是 gcc 就是不想把结构建立成其应该成为的样子 gcc 企 图对结构进行对齐处理 真是讨厌 不过我起码已经把所有蹩脚的代码都隐藏在这么一个文件中了 其他程序文件不需要了解这些信息 其他的程序也不需要知道 ST x 等 80387 内部结构 它们只需要得到 80 位临时实数的地址就可以 随意操作 我想尽可能在这里隐藏所有 387 专有信息 32 33 include 信号头文件 定义信号符号 信号结构及信号操作函数原型 34 35 define ALIGNED TEMP REAL 1 36 include 协处理器头文件 定义临时实数结构和 387 寄存器操作宏等 37 include 内核头文件 含有一些内核常用函数的原形定义 38 include 段操作头文件 定义了有关段寄存器操作的嵌入式汇编函数 39 40 define bswapw x asm xchgb al ah a x short x 交换 2 字节位置 41 define ST x st x 取仿真的 ST x 累加器值 42 define PST x const temp real st x 取仿真的 ST x 累加器的指针 43 44 45 We don t want these inlined it gets too messy in the machine code 46 我们不想让这些成为嵌入的语句 因为这会使得到的机器码太混乱 以下这些是相同名称浮点指令的仿真函数 47 static void fpop void 48 static void fpush void 49 static void fxchg temp real unaligned a temp real unaligned b 50 static temp real unaligned st int i 51 执行浮点指令仿真 该函数首先检测仿真的 I387 结构状态字寄存器中是否有未屏蔽的异常标志置位 若有则对状态字中 忙标志B 进行设置 然后把指令指针保存起来 并取出代码指针EIP 处的 2 字节浮点指令代码code 接着分析代码 code 并根据其含义进行处理 针对不同代码类型值 Linus 使用了几个不同的 switch 程序块进行仿真处理 参数是 info 结构的指针 52 static void do emu struct info info 53 54 unsigned short code 55 temp real tmp 56 char address 57 第 11 章 数学协处理器 557 该函数首先检测仿真的 I387 结构状态字寄存器中是否有未屏蔽的异常标志置位 若有就设置状态字 中的忙标志 B 位 15 否则复位 B 标志 然后我们把指令指针保存起来 再看看执行本函数的代 码是不是用户代码 如果不是 即调用者的代码段选择符不等于 0 x0f 则说明内核中有代码使用了 浮点指令 于是在显示出浮点指令出的 CS EIP 值和信息 内核中需要数学仿真 后停机 58 if I387 cwd 设置忙标志 B 60 else 61 I387 swd 清忙标志 B 62 ORIG EIP EIP 保存浮点指令指针 63 0 x0007 means user code space 64 if CS 0 x000F 不是用户代码则停机 65 printk math emulate 04x 08x n r CS EIP 66 panic Math emulation needed in kernel 67 然后我们取出代码指针 EIP 处的 2 字节浮点指令代码 code 由于 Intel CPU 存储数据时是 小头 Little endian 在前的 此时取出的代码正好与指令的第 1 第 2 字节顺序颠倒 因此我们需 要交换一下 code 中两个字节的顺序 然后再屏蔽掉第1 个代码字节中的ESC 位 二进制11011 接 着 把浮点指令指针 EIP 保存到 TSS 段 i387 结构中的 fip 字段中 而 CS 保存到 fcs 字段中 同时把 略微处理过的浮点指令代码 code 放到 fcs 字段的高 16 位中 保存这些值是为了在出现仿真的处理 器异常时程序可以像使用真实的协处理器一样进行处理 最后让 EIP 指向随后的浮点指令或操作数 68 code get fs word unsigned short EIP 取 2 字节的浮点指令代码 69 bswapw code 交换高低字节 70 code 屏蔽代码中的 ESC 码 71 I387 fip EIP 保存指令指针 72 unsigned short 保存代码段选择符 73 1 unsigned short 保存代码 74 EIP 2 指令指针指向下一个字节 然后分析代码值 code 并根据其含义进行处理 针对不同代码类型值 Linus 使用了几个不同的 switch 程序块进行处理 首先 若指令操作码是具有固定代码值 与寄存器等无关 则在下面处理 75 switch code 76 case 0 x1d0 fnop 空操作指令 FNOP 77 return 78 case 0 x1d1 case 0 x1d2 case 0 x1d3 无效指令代码 发信号 退出 79 case 0 x1d4 case 0 x1d5 case 0 x1d6 case 0 x1d7 80 math abort info 1 SIGILL 1 81 case 0 x1e0 FCHS 改变 ST 符号位 即 ST ST 82 ST 0 exponent 0 x8000 83 return 84 case 0 x1e1 FABS 取绝对值 即 ST ST 85 ST 0 exponent 86 return 87 case 0 x1e2 case 0 x1e3 无效指令代码 发信号 退出 88 math abort info 1 SIGILL 1 89 case 0 x1e4 FTST 测试 TS 同时设置状态字中 Cn 90 ftst PST 0 91 return 92 case 0 x1e5 FXAM 检查 TS 值 同时修改状态字中 Cn 93 printk fxam not implemented n r 未实现 发信号退出 94 math abort info 1 SIGILL 1 Linux 内核完全剖析 基于 0 12 内核 558 95 case 0 x1e6 case 0 x1e7 无效指令代码 发信号 退出 96 math abort info 1 SIGILL 1 97 case 0 x1e8 FLD1 加载常数 1 0 到累加器 ST 98 fpush 99 ST 0 CONST1 100 return 101 case 0 x1e9 FLDL2T 加载常数 Log2 10 到累加器 ST 102 fpush 103 ST 0 CONSTL2T 104 return 105 case 0 x1ea FLDL2E 加载常数 Log2 e 到累加器 ST 106 fpush 107 ST 0 CONSTL2E 108 return 109 case 0 x1eb FLDPI 加载常数 Pi 到累加器 ST 110 fpush 111 ST 0 CONSTPI 112 return 113 case 0 x1ec FLDLG2 加载常数 Log10 2 到累加器 ST 114 fpush 115 ST 0 CONSTLG2 116 return 117 case 0 x1ed FLDLN2 加载常数 Loge 2 到累加器 ST 118 fpush 119 ST 0 CONSTLN2 120 return 121 case 0 x1ee FLDZ 加载常数 0 0 到累加器 ST 122 fpush 123 ST 0 CONSTZ 124 return 125 case 0 x1ef 无效和未实现仿真指令代码 发信号 退出 126 math abort info 1 SIGILL 1 127 case 0 x1f0 case 0 x1f1 case 0 x1f2 case 0 x1f3 128 case 0 x1f4 case 0 x1f5 case 0 x1f6 case 0 x1f7 129 case 0 x1f8 case 0 x1f9 case 0 x1fa case 0 x1fb 130 case 0 x1fc case 0 x1fd case 0 x1fe case 0 x1ff 131 printk 04x fxxx not implemented n r code 0 xc800 132 math abort info 1 3 158 case 0 x18 FADD ST ST i 159 fadd PST 0 PST code 160 real to real 161 return 162 case 0 x19 FMUL ST ST i 163 fmul PST 0 PST code 164 real to real 165 return 166 case 0 x1a FCOM ST i 167 fcom PST code 168 real to real 169 return 170 case 0 x1b FCOMP ST i 171 fcom PST code 172 real to real 173 fpop 174 return 175 case 0 x1c FSUB ST ST i 176 real to real 177 tmp exponent 0 x8000 178 fadd PST 0 179 real to real 180 return 181 case 0 x1d FSUBR ST ST i 182 ST 0 exponent 0 x8000 183 fadd PST 0 PST code 184 real to real 185 return 186 case 0 x1e FDIV ST ST i 187 fdiv PST 0 PST code 188 real to real 189 return 190 case 0 x1f FDIVR ST ST i 191 fdiv PST code 192 real to real 193 return 194 case 0 x38 FLD ST i 195 fpush 196 ST 0 ST code 197 return 198 case 0 x39 FXCH ST i 199 fxchg Linux 内核完全剖析 基于 0 12 内核 560 200 return 201 case 0 x3b FSTP ST i 202 ST code 203 fpop 204 return 205 case 0 x98 FADD ST i ST 206 fadd PST 0 PST code 207 real to real 208 return 209 case 0 x99 FMUL ST i ST 210 fmul PST 0 PST code 211 real to real 212 return 213 case 0 x9a FCOM ST i 214 fcom PST code 215 return 216 case 0 x9b FCOMP ST i 217 fcom PST code 218 fpop 219 return 220 case 0 x9c FSUBR ST i ST 221 ST code 222 fadd PST 0 PST code 223 real to real 224 return 225 case 0 x9d FSUB ST i ST 226 real to real 227 tmp exponent 0 x8000 228 fadd PST code 229 real to real 230 return 231 case 0 x9e FDIVR ST i ST 232 fdiv PST 0 PST code 233 real to real 234 return 235 case 0 x9f FDIV ST i ST 236 fdiv PST code 237 real to real 238 return 239 case 0 xb8 FFREE ST i 未实现 240 printk ffree not implemented n r 241 math abort info 1 SIGILL 1 242 case 0 xb9 FXCH ST i 243 fxchg 244 return 245 case 0 xba FST ST i 246 ST code 247 return 248 case 0 xbb FSTP ST i 249 ST code 250 fpop 251 return 252 case 0 xbc FUCOM ST i 253 fucom PST code 254 return 255 case 0 xbd FUCOMP ST i 第 11 章 数学协处理器 561 256 fucom PST code 257 fpop 258 return 259 case 0 xd8 FADDP ST i ST 260 fadd PST code 261 real to real 262 fpop 263 return 264 case 0 xd9 FMULP ST i ST 265 fmul PST code 266 real to real 267 fpop 268 return 269 case 0 xda FCOMP ST i 270 fcom PST code 271 fpop 272 return 273 case 0 xdc FSUBRP ST i ST 274 ST code 275 fadd PST 0 PST code 276 real to real 277 fpop 278 return 279 case 0 xdd FSUBP ST i ST 280 real to real 281 tmp exponent 0 x8000 282 fadd PST code 283 real to real 284 fpop 285 return 286 case 0 xde FDIVRP ST i ST 287 fdiv PST 0 PST code 288 real to real 289 fpop 290 return 291 case 0 xdf FDIVP ST i ST 292 fdiv PST code 293 real to real 294 fpop 295 return 296 case 0 xf8 FFREE ST i 未实现 297 printk ffree not implemented n r 298 math abort info 1 3 313 return 314 case 0 x23 FSTP 保存单精度实数 短实数 315 put short real PST 0 info code 316 fpop 317 return 318 case 0 x24 FLDENV 加载协处理器状态和控制寄存器等 319 address ea info code 320 for code 0 code 7 code 321 long 323 address 4 324 325 return 326 case 0 x25 FLDCW 加载控制字 327 address ea info code 328 unsigned short 330 return 331 case 0 x26 FSTENV 储存协处理器状态和控制寄存器等 332 address ea info code 333 verify area address 28 334 for code 0 code 7 code 335 put fs long long 337 address 4 338 339 return 340 case 0 x27 FSTCW 储存控制字 341 address ea info code 342 verify area address 2 343 put fs word I387 cwd short address 344 return 345 case 0 x62 FIST 储存短整形数 346 put long int PST 0 info code 347 return 348 case 0 x63 FISTP 储存短整形数 349 put long int PST 0 info code 350 fpop 351 return 352 case 0 x65 FLD 加载扩展 临时 实数 353 fpush 354 get temp real 355 real to real 356 return 357 case 0 x67 FSTP 储存扩展实数 358 put temp real PST 0 info code 359 fpop 360 return 361 case 0 xa2 FST 储存双精度实数 362 put long real PST 0 info code 363 return 364 case 0 xa3 FSTP 储存双精度实数 第 11 章 数学协处理器 563 365 put long real PST 0 info code 366 fpop 367 return 368 case 0 xa4 FRSTOR 恢复所有 108 字节的寄存器内容 369 address ea info code 370 for code 0 code 27 code 371 long 373 address

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论