探测内存

作者: HAPPYers | 来源:发表于2019-03-21 22:43 被阅读0次

    本文介绍三种探测内存的方法
    探测内存是通过调用 BIOS 中断 0x15 实现的
    分别 是 BIOS 中断 0x15 的 3 个子功能

    • EAX=OxE820:遍历主机上全部内存。
    • AX =OxE801: 分别检测低15MB和 16MB~4GB 的内存,最大支持 4GB。
    • AH=Ox88:最多检测出 64MB 内存,实际内存超过此容量也按照 64MB 返回。

    一、利用 BIOS 中断 Ox15 子功能 0xE820 获取内存

    INT15h BIOS 中断的详细调用参数:
    eax:e820h:INT 15 的中断调用参数;
    edx:534D4150h (即 4 个 ASCII 字符―SMAP‖) ,这只是一个签名而已;
    ebx:如果是第一次调用或内存区域扫描完毕,则为 0。 如果不是,则存放上次调用之后的计数值;
    ecx:保存地址范围描述符的内存大小,应该大于等于 20 字节;
    es:di:指向保存地址范围描述符结构的缓冲区,BIOS 把信息写入这个结构的起始地址。
    此中断的返回值为:
    cflags 的 CF 位:若 INT 15 中断执行成功,则不置位,否则置位;
    eax:534D4150h ('SMAP') ;
    es:di:指向保存地址范围描述符的缓冲区,此时缓冲区内的数据已由 BIOS 填写完毕
    ebx:下一个地址范围描述符的计数地址
    ecx :返回 BIOS 往 ES:DI 处写的地址范围描述符的字节大小
    ah:失败时保存出错代码



    通过调用 INT 15h BIOS 中断,递增 di 的值(20 的倍数),让 BIOS 帮我们查找出一个一个的内存布局 entry,并放入到一个 保存 地址范围描述符(见文章 INTEL基础结构) 结构的缓冲区中,供后续使用.

    ARDS地址范围描述符
    struct e820map {
    int nr_map;
    struct {
    long long addr;
    long long size;
    long type;
    } map[E820MAX];
    };
    
    probe_memory:
        movl $0, 0x8000
        xorl %ebx, %ebx
        movw $0x8004, %di
    start_probe:
        movl $0xE820, %eax
        movl $20, %ecx
        movl $SMAP, %edx
        int $0x15
        jnc cont
        movw $12345, 0x8000
        jmp finish_probe
    cont:
        addw $20, %di
        incl 0x8000
        cmpl $0, %ebx
        jnz start_probe
    finish_probe:
    

    二、利用 BIOS 中断0x15 子功能 0xE801 获取内存



    三、利用 BIOS 中断 0x15 子功能 0x88 获取内存

    最后一个获取内存的方法也同样是 BIOS 0x15 中断,子功能号是 0x88。
    该方法使用最简单,但功能也最简单,简单到只能识别最大 64MB的内存。即使内存容量大于 64MB,也只会显示 63MB。因为此中断只会显示 1MB 之上的内存,不包括1MB。在使用的时候记得加上 1M.



    相关文章

      网友评论

        本文标题:探测内存

        本文链接:https://www.haomeiwen.com/subject/cyyxvqtx.html