热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

是否允许访问跨越x86零边界的内存?

如何解决《是否允许访问跨越x86零边界的内存?》经验,为你挑选了1个好方法。

是否允许单个访问跨越x86 1之间0和之间的边界?0xFFFFFF...

例如,假设eax(rax在64位中)为零,则允许以下访问:

mov ebx, DWORD [eax - 2]

如果答案不同,我对x86(32位)和x86-64都很感兴趣.


1当然,鉴于该区域已在您的流程中映射等.



1> prl..:

我刚刚使用此EFI程序进行了测试。(并且按预期工作。)如果要重现此结果,则需要实现efi_printf或另一种查看结果的方式。

#include 
#include "efi.h"

uint8_t *p = (uint8_t *)0xfffffffffffffffcULL;

int main()
{
    uint64_t cr3;
    asm("mov %%cr3, %0" : "=r"(cr3));
    uint64_t *pml4 = (uint64_t *)(cr3 & ~0xfffULL);

    efi_printf("cr3 %lx\n", cr3);
    efi_printf("pml4[0] %lx\n", pml4[0]);
    uint64_t *pdpt = (uint64_t *)(pml4[0] & ~0xfffULL);
    efi_printf("pdpt[0] %lx\n", pdpt[0]);
    if (!(pdpt[0] & 1)) {
        pdpt[0] = (uint64_t)efi_alloc_pages(EFI_BOOT_SERVICES_DATA, 1) | 0x03;
        efi_printf("pdpt[0] %lx\n", pdpt[0]);
    }
    uint64_t *pd = (uint64_t *)(pdpt[0] & ~0xfffULL);
    efi_printf("pd[0] %lx\n", pd[0]);
    if (!(pd[0] & 1)) {
        pd[0] = (uint64_t)efi_alloc_pages(EFI_BOOT_SERVICES_DATA, 1) | 0x03;
        efi_printf("pd[0] %lx\n", pd[0]);
    }
    if (!(pd[0] & 0x80)) {
        uint64_t *pt = (uint64_t *)(pd[0] & ~0xfffULL);
        efi_printf("pt[0] %lx\n", pt[0]);
        if (!(pt[0] & 1)) {
            pt[0] = (uint64_t)efi_alloc_pages(EFI_BOOT_SERVICES_DATA, 1) | 0x03;
            efi_printf("pt[0] %lx\n", pt[0]);
        }
    }

    efi_printf("[0] = %08x\n", *(uint32_t *)(p+4));

    efi_printf("pml4[0x1ff] %lx\n", pml4[0x1ff]);
    if (pml4[0x1ff] == 0) {

        uint64_t *pt = (uint64_t *)efi_alloc_pages(EFI_BOOT_SERVICES_DATA, 4);
        uint64_t x = (uint64_t)pt;

        efi_printf("pt = %p\n", pt);

        pml4[0x1ff] = x | 0x3;
        pt[0x1ff] = x + 0x1000 | 0x3;
        pt[0x3ff] = x + 0x2000 | 0x3;
        pt[0x5ff] = x + 0x3000 | 0x3;

        *(uint32_t *)p = 0xabcdabcd;
        *(uint32_t *)(p + 4) = 0x12341234;

        efi_printf("[0] = %08x\n", *(uint32_t *)(p+4));
        efi_printf("[fffffffffffc] = %08x\n", *(uint32_t *)(x + 0x3ffc));

        *(uint32_t *)(p + 2) = 0x56785678;

        efi_printf("p[0] = %08x\n", ((uint32_t *)p)[0]);
        efi_printf("p[1] = %08x\n", ((uint32_t *)p)[1]);
    }

    return 0;
}

如果它按预期工作,则最后四行应为:

[0] = 12341234
[fffffffffffc] = ABCDABCD
p[0] = 5678ABCD
p[1] = 12345678

从存储器的最后一个16位字开始写入0x56785678的值,并且应该将其包装到存储器的第一个16位字中。


注意:p必须是全局变量,否则GCC更改*(p+4)ud2


[我发现](/sf/ask/17360801/#comment82366009_47702410)仅使用` -Og`而不是`-O2`或更高版本得到gcc来制作我想要的asm。但是可以肯定的是,全局变量也可以阻止优化器查看编译时常量。
推荐阅读
author-avatar
透支的灬漂移_255
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有