标签: real-mode

Grub并进入实模式(低级汇编语言编程)

我一直在玩玩具操作系统,并一直使用grub作为我的引导加载程序.最近在尝试使用VGA时,我发现我无法使用硬件中断.我发现这是因为我被grub挂入了保护模式.

有没有人知道怎么回到实模式而不必摆脱grub?

x86 assembly grub real-mode

7
推荐指数
1
解决办法
1676
查看次数

近呼叫/跳转表并不总是在引导加载程序中工作

一般问题

我一直在开发一个简单的引导加载程序,并且在某些环境中偶然发现问题,这些环境中的指令不起作用:

mov si, call_tbl      ; SI=Call table pointer
call [call_tbl]       ; Call print_char using near indirect absolute call
                      ; via memory operand
call [ds:call_tbl]    ; Call print_char using near indirect absolute call
                      ; via memory operand w/segment override
call near [si]        ; Call print_char using near indirect absolute call
                      ; via register
Run Code Online (Sandbox Code Playgroud)

这些中的每一个碰巧涉及间接接近CALL到绝对存储器偏移.我发现如果我使用类似的JMP表,我会遇到问题.相对的呼叫和跳转似乎没有受到影响.像这样的代码有效:

call print_char 
Run Code Online (Sandbox Code Playgroud)

我已经通过海报讨论了Stackoverflow上提出的建议,讨论了编写引导加载程序的注意事项.特别是我看到这个Stackoverflow回答了一般的Bootloader技巧.第一个提示是:

  1. 当BIOS跳转到您的代码时,您不能依赖具有有效或预期值的CS,DS,ES,SS,SP寄存器.应在引导加载程序启动时正确设置它们.您只能保证将从物理地址0x07c00加载并运行引导加载程序,并将引导驱动器号加载到DL寄存器中. …

x86 assembly real-mode nasm bootloader

7
推荐指数
1
解决办法
584
查看次数

为什么在从实模式切换到保护模式之前需要禁用中断?

我在许多ose(和一些引导程序)中看到,它们cli在从实模式切换到保护模式之前都禁用了interrupt().为什么我们需要这样做?

x86 operating-system real-mode osdev bootloader

6
推荐指数
1
解决办法
1049
查看次数

真实模式程序和保护模式程序之间的真正区别是什么?

从操作系统和硬件的角度来看,我知道实模式和保护模式之间的区别.

但我想弄清楚程序对真实模式或保护模式的"了解"是什么?你怎么能在看源代码/目标代码时说它是真正的模式程序呢?

寻找答案,我能想到的是"实模式"程序使用BIOS子程序和OS子程序,而"保护模式"程序仅使用OS子程序.指令代码不同,因为寄存器的操作码是不同的,并且偏移地址的长度不同.是否还有其他功能可以区分真实和受保护的模式程序?

operating-system real-mode protected-mode

6
推荐指数
3
解决办法
1万
查看次数

为什么要在进入保护模式之前在引导加载程序中测试端口0x64?

在我的MIT OS课程(686)中,我发现了一些我不理解的代码。我想了解指令inb $0x64, %al启动 / boot.S。我的理解是它正在从数据端口0x64读一个字节到AL,端口0x64是什么?正在测试哪个设备或机制?我对代码忙中的注释感到困惑吗?评论是什么意思,它指的是什么?

# Enable A20:
#   For fascinating historical reasons (related to the fact that
#   the earliest 8086-based PCs could only address 1MB of physical memory
#   and subsequent 80286-based PCs wanted to retain maximum compatibility),
#   physical address line 20 is tied to low when the machine boots.
#   Obviously this a bit of a drag for us, especially when trying to …
Run Code Online (Sandbox Code Playgroud)

x86 assembly real-mode osdev bootloader

6
推荐指数
1
解决办法
1815
查看次数

在 CR0 中设置 PE 标志如何启用保护模式?

我试图了解机器如何从开机到运行内核。从我收集到的信息来看,在启动期间切换到保护模式以访问更多可寻址内存是很有用的,即使我们最终将切换到更传统的虚拟内存计划,并关闭页目录和页表以及分段.

似乎要切换到保护模式必须完成 3 件事:

  1. 设置全局描述符表(gdt)并使用lgdt指令加载它
  2. 将控制寄存器 CR0 中的 PE 标志/位设置为启用(即值 1)
  3. 执行跳远 ljmp

我想知道将段寄存器和指令指针转换为索引和偏移量以与 gdt 一起使用的逻辑。这个逻辑是硬件实现的吗?如果是这样,哪个硬件以及为什么要执行ljmp该过程的一部分?为什么不简单地在 CR0 中设置 PE 标志以启用保护模式(没有以下内容ljmp)?

assembly operating-system kernel real-mode protected-mode

6
推荐指数
1
解决办法
1543
查看次数

用于实模式内核开发的 16 位 C 编译器?

我已经尝试了几乎所有 C 编译器的每种设置,但我还没有找到一个可以将 C 编译成适合实模式内核开发的 Intel x86 代码的 C 编译器。我不需要任何解释为什么你应该使用保护模式;我只需要知道编译一个没有操作系统依赖性的 16 位独立二进制文件需要哪个 C 编译器(以及运行它的设置(如果需要),等等。只是实模式下的裸机,仅此而已。

我很确定这不是 [16 bit C code for real mode kernel]: 16 bit C code for real mode kernel的重复,因为他们接受切换到保护模式作为答案,并且我明确指出结果必须有效对于实模式。

c x86 kernel real-mode 16-bit

6
推荐指数
1
解决办法
2194
查看次数

在Linux内核中从真实模式转换为保护模式

我目前正在研究操作系统的低级组织.为了实现我想要了解Linux内核是如何加载的.

我无法理解的是从16位(实模式)到32位(保护模式)的转换.它发生在这个文件中.

protected_mode_jump函数对稍后执行的32位代码执行各种辅助计算,然后启用调节器中的PECR0

    movl    %cr0, %edx
    orb $X86_CR0_PE, %dl    # Protected mode
    movl    %edx, %cr0
Run Code Online (Sandbox Code Playgroud)

然后执行长跳转到32位代码:

    # Transition to 32-bit mode
    .byte   0x66, 0xea      # ljmpl opcode
2:  .long   in_pm32         # offset
    .word   __BOOT_CS       # segment
Run Code Online (Sandbox Code Playgroud)

据我所知in_pm32,32位函数的地址在下面声明protected_mode_jump:

    .code32
    .section ".text32","ax"
GLOBAL(in_pm32)
    # some code
    # ...
    # some code
ENDPROC(in_pm32)
Run Code Online (Sandbox Code Playgroud)

__BOOT_CS扇区基是0(GDT被设定预先这里),因此这意味着,偏移应该是基本上绝对地址in_pm32的功能.

这就是问题所在.在机器代码生成期间,汇编器/链接器不应该知道in_pm32函数的绝对地址,因为它不知道在实模式下它将在内存中加载的位置(各种引导加载程序可以占用不同的空间量,以及实模式内核)在引导加载程序之后加载).

此外,链接器脚本(setup.ld在同一文件夹中)将代码的原点设置为0,因此看起来in_pm32地址将是从实模式内核开始的偏移量.它应该可以正常使用16位代码,因为CS寄存器设置正确,但是当发生长跳转时,CPU已经处于保护模式,因此相对偏移不应该起作用.

所以我的问题:.byte …

x86 assembly real-mode protected-mode linux-kernel

6
推荐指数
1
解决办法
555
查看次数

在DOS EXE程序中从保护模式切换到实模式

我学会了使用基于DOS的简单Bootloader切换到保护模式。该加载程序加载kernel.bin到缓冲区中,并将缓冲区复制到100000h(内核为8KiB)。然后将控制权转移到内核。当我从内核返回并尝试切换到实模式时,我遇到了一个问题。

我的FASM汇编代码(类似于我先前的Stackoverflow问题)如下:

format MZ
push cs
pop ds
mov eax,cs
shl eax,4
mov [AdresSegmentuProgramu_32],eax ;Calculating real mode segment
add eax,gdt_table
mov [gdtr+2],eax
mov ax,[AdresSegmentuProgramu_32+2]
mov [code_realsegment_descriptor+3],ax  
mov al,[AdresSegmentuProgramu_32+1]       ;Setting 16-bit descriptors to return from protected mode
    mov [code_realsegment_descriptor+2],al
    mov ax,[AdresSegmentuProgramu_32+2]
    mov [data_realsegment_descriptor+3],ax
mov al,[AdresSegmentuProgramu_32+1]
mov [data_realsegment_descriptor+2],al
mov ax,3d00h
mov dx,NazwaPliku
int 21h
mov bx,ax
mov ax,3f00h
mov cx,8192
mov dx,KernelGDOS32
int 21h
mov ax,3e00h
int 21h
lgdt [gdtr]

mov eax,[AdresSegmentuProgramu_32]

add eax, pmode_entry ;Far jump to …
Run Code Online (Sandbox Code Playgroud)

x86 assembly real-mode protected-mode fasm

6
推荐指数
1
解决办法
265
查看次数

是否有 43 行或更多的标准 BIOS Int 10h 视频模式?

我正在编写在加载任何操作系统之前以实模式运行的代码。我的程序的一部分涉及将信息转储到视频显示,而标准 80x25 文本模式无法剪切它。

许多版本的 Windows 和其他操作系统在显示内核恐慌时似乎可以毫无困难地切换到更大的文本模式,我认为是 43 行。我知道更大的文本模式已经存在很长时间了,所以我希望至少有一种标准模式。

这里有一个相当大的 BIOS 视频模式列表:

http://www.columbia.edu/~em36/wpdos/videomodes.txt

不幸的是,相同的模式编号在芯片组之间的含义似乎有很大差异。

曾几何时,我似乎记得使用过一种名为 VESA BIOS 的东西以独立于设备的方式访问超级 VGA 图形模式,但我似乎还记得涉及必须加载的 DOS TSR。这不是一个选项这里因为 DOS 没有运行。

我正在寻找一种能够在最广泛的硬件上运行的模式,包括 VMware ESXi 中的虚拟视频适配器。更改模式的代码也需要紧凑,所以我希望一个简单的 Int 10h 就能做到这一点。

有任何想法吗?Windows 和 VMware 内核恐慌是如何发生的?

video x86 real-mode bios

5
推荐指数
1
解决办法
2301
查看次数