是否允许访问跨越x86中零边界的内存? [英] Is it allowed to access memory that spans the zero boundary in x86?

查看:75
本文介绍了是否允许访问跨越x86中零边界的内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否允许单次访问跨越x86 1 00xFFFFFF...之间的界限?

Is it allowed for a single access to span the bounary between 0 and 0xFFFFFF... in x861?

例如,假设eax(64位中的rax)为零,是否允许以下​​访问:

For example given that eax (rax in 64-bit) is zero, is the following access allowed:

mov ebx, DWORD [eax - 2]

在答案不同的情况下,我对x86(32位)和x86-64都感兴趣.

I'm interested in both x86 (32-bit) and x86-64 in case the answers are different.

1 当然,考虑到该区域是在您的过程中映射的,等等.

1 Of course given that the region is mapped in your process etc.

推荐答案

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

I just tested with this EFI program. (And it worked, as expected.) If you want to reproduce this result, you would need an implementation of efi_printf, or another way to view the result.

#include <stdint.h>
#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;
}

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

If it works as expected, the last 4 lines should be:

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

从内存的最后16位字开始写入0x56785678的值,并且应该将其包装到内存的第16位字中.

A value of 0x56785678 is written starting in the last 16-bit word of memory and should wrap to the first 16-bit word of memory.

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

Note: p needed to be a global variable, otherwise GCC changed *(p+4) into ud2

这篇关于是否允许访问跨越x86中零边界的内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆