OS之路第六章 --- 12.11日学习总结

1. equ是一个代码替换指令

equ 作用类似于 define。
str_len equ $-str语句的意思:str-0 则是str字符串的长度,用str_len来代替

2.C语言extern关键字的用法

修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。

函数声明的作用是: 一方面告诉编译器该函数的参数所需要的栈空间大小及返回值,这样编译器能为其准备好执行环境:另一方面如果该函数是在外部文件中定义的,一定要在链接阶段时将其对应的目标文件一块链接进来。

其主要是用作在一个文件中引用另一个文件的内容,使用方法如下:
main.c

#include<stdio.h>

int main()
{
    extern const int num;
    printf("%d",num);
    return 0;
}

a.c

#include<stdio.h>
const int num = 5;
void func()
{
    printf("fun in a.c");
}
3.在汇编代码中导出符号供外部引用是用的关键字 global,引用外部文件的符号是用的关键宇 extern 。

• 在 C 代码中只要将符号定义为全局便可以被外部引用(一般情况下无需用额外关键宇修饰),引用外部符号时用 extern 声明即可。

4.#ifndef的介绍

这是"if not defined"的简写,是宏定义的一种,它是可以根据是否已经定义了一个变量来进行分支选择,一般用于调试等等。
作用:

  1. 防止头文件的重复包含和编译
  2. 便于程序的调试和移植

#ifndef x //先测试x是否被宏定义过
#define x
程序段1 //如果x没有被宏定义过,定义x,并编译程序段 1
#else
程序段2 //如果x已经定义过了则编译程序段2的语句,“忽视”程序段 1。
#endif//终止if

5.不能直接把立即数送入段选择子中
6.global put_char

通过关键字 global 把函数 put_char 导出为全局符号,这样对外部文件便可见了,外部文件通过声明便可以调用。

7.PUSHAD 是 push all double,该指令压入所有双字长的寄存器,这里的“所有” 一共是 8 个,它们的入栈先后顺序是 EAX->ECX->EDX->EBX-> ESP-> EBP->ESl->EDI, EAX 是最先入栈。
8.往端口读或写数据

当往端口是独立编址的时候,就不能把它当作内存使用,所以就不能用mov指令。因此CPU提供了一个专门的指令:in和out

in指令用于从端口中读取数据,其一般形式为:
(ps:这是intel汇编语言形式,目的操作数=源操作数)
(1)in al,dx
(2)in ax,dx
其中al和ax用来存储从端口获取的数据,dx是指端口号
out指令用于往端口中写入数据,其一般形式为:
(1) out dx,al;
(2) out dx,ax;
(3) out 立即数,al;
(4)out 立即数,ax;

9.字符在显存中占 2 字节,低字节是 ASCII 码,高字符是属性
10.cld,字符串“搬运”指令movs[bwd]和rep三剑客组合 完成大数据的复制。

cld 指令清除方向位,就是把 eflags 寄存器中方 向标志位DF (DirectionFlag)清0。

11.

用户进程是需要用 iretd中断返回指令上 CPU 运行的。CPU 在执行 iretd 指令时会做特权检查,它检查 DS、 ES、 FS、 GS “数据”段寄存器的内容,这里的数据加了引号,它用来指除代码段寄存器 cs 和堆栈段寄存器 SS 之外的段寄存器。在 32位保护模式下它们中存储的都是选择子。

要是有任何一个段寄存器所指向的段描述符的 DPL 权限高于从 iretd命令返回后的 CPL ( 这个返回后的 CPL 也就是新的 CPL。 CPL 就是加载到 cs 寄存器中选择子 的 RPL), CPU 就会将该段寄存器赋值为 0。

一旦将来用该段寄存器访问内存时,由于选择子为 0,这表示选择子中的索引位、TI位和 RPL 位都为 0,所以会在 GDT 中检索到第 0 个段描述符,由于第 0 个段描述符是空的不可用(这是 Intel有意为之的,为避免忘记初始化选择子而误选到了 GDT 中的第 0个描述符),这就会导致CPU抛出异常。

猜你喜欢

转载自blog.csdn.net/qq_37414405/article/details/84955013
今日推荐