Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无法使用e820获取内存映射_C_Assembly_Memory Management_Operating System_X86 16 - Fatal编程技术网

C 无法使用e820获取内存映射

C 无法使用e820获取内存映射,c,assembly,memory-management,operating-system,x86-16,C,Assembly,Memory Management,Operating System,X86 16,我正在编写一个非常基本的内核,为了获得物理内存映射,我使用了 C代码如下: uint8_t memMapLength=0; uint64_t availableMemBytes=0; typedef struct memoryMapEntry{ uint32_t baseLow; uint32_t baseHigh; uint64_t length; uint32_t type; uint32_t acpi_null; } memoryM

我正在编写一个非常基本的内核,为了获得物理内存映射,我使用了

C代码如下:

uint8_t memMapLength=0;
uint64_t availableMemBytes=0;

typedef struct memoryMapEntry{
    uint32_t baseLow;
    uint32_t baseHigh;
    uint64_t length;   
    uint32_t type;
    uint32_t acpi_null; 
    } memoryMapEntry;

memoryMapEntry* memMapArr=0; 
void DetectMem(){
    memMapArr= (memoryMapEntry*)(0x00007c40);
    uint8_t i;
    for(i=0;i<memMapLength;i++){
            if(memMapArr[i].type==1){           
                availableMemBytes += memMapArr[i].length;               
            }               
    }
}
do_e820();
DetectMem();
char *arr = (char *)&availableMemBytes;
terminal_write(arr);
 

然而,我无法启动我的内核,因为启动卡在一个无限循环中。我犯了什么错误?

此答案使用英特尔汇编。
您刚刚删除了一段非常重要的代码

mov di, 0x8004
不要使用
jmp.done
而是使用
ret

删除
.done
空块。
您是否使用实模式?因此,您应该在引导加载程序中执行此操作。
使用
pusha
popa

使其遵循调用约定。要使其符合以下要求:

pop es
要使其工作,请使用此程序集:

    jmp kmain
do_e820:
    pop es
    pusha
    mov di, 0x8004
    xor ebx, ebx
    xor bp, bp
    mov edx, 0x0534D4150
    mov eax, 0xe820
    mov [es:di + 20], dword 1
    mov ecx, 24
    int 0x15
    jc short .failed
    mov edx, 0x0534D4150    ; Some BIOSes apparently trash this register?
    cmp eax, edx        ; on success, eax must have been reset to "SMAP"
    jne short .failed
    test ebx, ebx       ; ebx = 0 implies list is only 1 entry long (worthless)
    je short .failed
    jmp short .jmpin
.e820lp:
    mov eax, 0xe820     ; eax, ecx get trashed on every int 0x15 call
    mov [es:di + 20], dword 1   ; force a valid ACPI 3.X entry
    mov ecx, 24     ; ask for 24 bytes again
    int 0x15
    jc short .e820f     ; carry set means "end of list already reached"
    mov edx, 0x0534D4150    ; repair potentially trashed register
.jmpin:
    jcxz .skipent       ; skip any 0 length entries
    cmp cl, 20      ; got a 24 byte ACPI 3.X response?
    jbe short .notext
    test byte [es:di + 20], 1   ; if so: is the "ignore this data" bit clear?
    je short .skipent
.notext:
    mov ecx, [es:di + 8]    ; get lower uint32_t of memory region length
    or ecx, [es:di + 12]    ; "or" it with upper uint32_t to test for zero
    jz .skipent     ; if length uint64_t is 0, skip entry
    inc bp          ; got a good entry: ++count, move to next storage spot
    add di, 24
.skipent:
    test ebx, ebx       ; if ebx resets to 0, list is complete
    jne short .e820lp
.e820f:
    mov di, 0x8000
    mov [es:di], bp
    clc
    popa
    ret
.failed:
    stc
    popa
    ret
用内核主函数名替换
kmain

构建:
为此使用Linux或WSL。
准备:

sudo apt install python3 wget -y
wget http://dl.devdrive.org/xcdk.py -o ./xcdk.py
sudo python3 ./xcdk.py
用于生成的Envar表:

Envar        Description
=================================
CFILE        A file with your C code! No spaces. Extension must be .c
ASM          A file with the above assembly! No spaces. Extension must be .asm
TEMP         A temporary file. No spaces.
OUT          This is gonna be your build result. No spaces.
建造:

xcbuild 16 $ASM $CFILE $TEMP
nasm -fbin -o $OUT $TEMP

关于
xcbuild
:它使用
gcc
intel2gas
将不同的文件合并到一个NASM程序集文件中。安装程序脚本将为您安装此。它支持
.asm
.s
.c
文件。没有C++支持,因为C++需要一个标准库。code>xcbuild基于Python,目前处于实验阶段。它有时会创建大的部件文件。它不会更改任何指针,因此您必须更改这些指针。如果您使用64位输出,由于
intel2gas
中的当前错误,您将在NASM中获得少量气体(来自
push
指令)。您可以直接调用它的原因是shebang行。由于
intel2gas
中的其他错误,
xcbuild
执行intel2gas前任务和intel2gas后任务。
intel2gas
之前的任务正在对代码进行“二值化”,以便为
intel2gas
做好准备。二进制化包括删除前4行,以及
LFE*:
行和它们下面的3行。它还删除
.cfi.*
行和其他垃圾
LFB
是代码,
LFE
是Linux垃圾。

[ES:DI]指向哪里?很难说,因为这不是一个问题。另外,要学会使用调试器,至少要确定哪个部件卡住了。你不能将汇编的使用限制在对e820服务的单个调用中吗?此外,汇编代码是实模式,C代码也是?此外,您正在从C调用asm代码,但似乎没有遵循任何调用约定,您确定您的编译器对诸如归零
bp
之类的内容满意吗?根据Tommylee2k已经提出的问题,如何设置es:di;mov-es,bx;mov-di,0h;
xcbuild 16 $ASM $CFILE $TEMP
nasm -fbin -o $OUT $TEMP