zoukankan      html  css  js  c++  java
  • 数据段描述符和代码段描述符(二)——《x86汇编语言:从实模式到保护模式》读书笔记11

    这篇博文,我们编写一个C语言的小程序,来解析数据段或者代码段描述符的各个字段。这样我们阅读原书的代码就会方便一点,只要运行这个小程序,就可以明白程序中定义的数据段或者代码段的描述符了。眨眼

    这段代码,我用了“位字段”的知识,这还是第一次使用C语言的这个特性呢,如果有不对的地方,欢迎博友斧正。

    写代码之前,我们再复习一下数据段描述符和代码段描述符的格式。(图片选自赵炯老师的《Linux内核完全剖析》)


    #include <stdio.h>
    
    //定义描述符中的低32位
    struct seg_des_low_word
    {
        unsigned int limit_0_15:16;
        unsigned int base_0_15 :16;
        
    };
    
    //定义描述符中的高32位
    struct seg_des_high_word
    {
        unsigned int base_16_23 :8;
        unsigned int type       :4;
        unsigned int s          :1;
        unsigned int dpl        :2;
        unsigned int p          :1;
        unsigned int limit_16_19:4;
        unsigned int avl        :1;
        unsigned int l          :1;
        unsigned int d_b        :1;
        unsigned int g          :1;
        unsigned int base_24_31 :8;
    };
    
    
    //对TYPE字段进行解析
    void parse_type(unsigned int t)
    {
        if(t<=7)
            printf("数据段: ");
        else
            printf("代码段: ");
        switch(t)
        {
            case 0:
            case 1:
                printf("只读
    ");
                break;
            case 2:
            case 3:
                printf("可读可写
    ");
                break;
            case 4:
            case 5:
                printf("向下扩展,只读
    ");
                break;
            case 6:
            case 7:
                printf("向下扩展,可读可写
    ");
                break;
            case 8:
            case 9:
                printf("仅执行
    ");
                break;
            case 10:
            case 11:
                printf("可读,可执行
    ");
                break;
            case 12:
            case 13:
                printf("一致性段,仅执行
    ");
                break;
            case 14:
            case 15:
                printf("一致性段,可读,可执行
    ");
                break;
            default:
                break;
    
        }
    
    }
    
    void parse_seg_des(struct seg_des_low_word* pl, struct seg_des_high_word* ph)
    {
        unsigned int seg_base;
        //拼接基地址字段
        seg_base = (ph->base_24_31<<24)|(ph->base_16_23<<16)|pl->base_0_15;
        printf("seg_base = %#X
    ",seg_base);
        
        unsigned int seg_limit;
        //拼接段限长字段
        seg_limit = (ph->limit_16_19<<16)|pl->limit_0_15;
        printf("seg_limit = %#X
    ",seg_limit);
        
        //下面的字段输出是不是很方便?这就是位字段的好处之一
        printf("S = %d
    ",ph->s);
        printf("DPL = %d
    ",ph->dpl);
        printf("G = %d
    ",ph->g);
        printf("D/B = %d
    ",ph->d_b);
        printf("TYPE = %d
    ",ph->type);
    
        //解析TYPE(目前只支持数据段描述符和代码段描述符,其他类型的,可以自己扩充)    
        parse_type(ph->type);
    }
    
    
    
    int main(void)
    {
        printf("please input the segment descriptor, low= high=
    ");
        struct seg_des_high_word *high;
        struct seg_des_low_word *low;
        
        unsigned int l_word = 0;
        unsigned int h_word = 0;
    
        //请求用户输入描述符,先是低32位,再是高32位
        scanf("%x" "%x",&l_word,&h_word);
        printf("-----------------------
    ");
        high =(struct seg_des_high_word*)&h_word;
        low =(struct seg_des_low_word*)&l_word;
    
        parse_seg_des(low,high);
        printf("------------------------
    ");
        
        return 0;
    }


    好了,代码就是这样。下面看看结果吧。编译后并运行。提示我们输入:



    我们就输入原书的配书代码c11_mbr.asm中

      ;创建#1描述符,保护模式下的代码段描述符
             mov dword [bx+0x08],0x7c0001ff     
             mov dword [bx+0x0c],0x00409800     
    注意,输入格式是16进制(不需要前导的0x),先输入低32位,也就是7c0001ff,然后空格,再输入高32位,也就是00409800,最后回车,就出结果了。


    效果还不错吧。哈哈。


    (完)



  • 相关阅读:
    npm常用命令
    React进阶
    ant按需加载、配置configoverrides.js文件、项目中引入less、解决TypeError: this.getOptions is not a function错误
    数组常用api
    react项目实战简单登录注册
    Hoot新特性
    win10全局安装插件却不能全局用,https:/go.microsoft.com/ fwlink/?LinkID=135170禁止运行脚本
    Ant Design编辑表格(类组件)
    反射解决类的复制
    基于Jquery和Ajax的多选框
  • 原文地址:https://www.cnblogs.com/longintchar/p/5224404.html
Copyright © 2011-2022 走看看