汇编 - 如何在 UEFI 中设置图形模式(无 VGA、无 BIOS、不推荐使用)



我正在使用的工具:nasm,qemu-system-x86_64。

我正在使用的操作系统:视窗 10。

所以我在 https://wiki.osdev.org/Real_Mode_OS_Warning 查看了"实模式操作系统警告">

这篇文章似乎暗示的是,一切都可以在不使用BIOS中断的情况下完成。我知道如何加载长模式,所以我已经这样做了,但现在我被困住了,因为到目前为止我只知道 BIOS 中断。我想做一些事情,比如将图形模式设置为全内存访问模式(如果您看过int 10h / AX = 4F02h / BX = 81FFh,听起来可能很熟悉(,但由于我不想使用已弃用的东西 (BIOS(,我一直在搜索网络上如何设置图形模式,然后仅在长模式下访问单个像素。

希望事实证明可以在StackOverflow上回答这个问题。我非常相信"它太复杂了"不会作为答案出现,特别是因为 OSDev 刚刚告诉我不要使用已弃用的东西。告诉某人这太难了,假设他们知道什么,以及他们能够学到什么,甚至不知道他们是谁。我只需要一个起点来了解如何做到这一点。

澄清一下,对我不起作用的事情:

进入图形模式,无需中断装配

这对我不起作用,因为答案给出了我不想要的 VGA 链接。

装配体 8086 中的图形模式

这对我不起作用,因为这个问题不是关于长模式,而是关于真实模式下的 VGA 图形。

如何在不使用 BIOS 的情况下将数据写入显卡?

这对我不起作用,因为答案本质上是"它太复杂了,使用已弃用的东西",这与我试图做的事情相反,并且与我刚刚在 OSDev 上被告知的内容非常矛盾。

通过英特尔 8086 上的图形卡直接绘图

这对我不起作用,因为答案与设置图形模式无关。

一些 x86 汇编语言问题

这对我不起作用,因为答案没有说明如何在 UEFI 中设置图形模式。他们只谈论已弃用的东西。

下面是使用 UEFI 获取和打印第一个图形设备上的可用图形模式并选择性地设置模式的示例代码。

我使用了这个参考:http://wiki.phoenix.com/wiki/index.php/EFI_GRAPHICS_OUTPUT_PROTOCOL。

实施注意事项:

  • 它调用定位协议来获取图形输出协议。我尝试使用 LocateHandle 获取支持图形输出协议的所有句柄。它返回了两个句柄,但OpenProtocol失败了。我没有机会使用 LocateHandle 调试版本。此版本使用定位协议有效。
  • 它打印可用模式的数量、当前模式以及每种模式的特性。
  • 函数的参数是要设置的模式。如果为 -1,则不更改模式。否则,它必须介于 0 和 N - 1 之间,其中 N 是支持的图形模式数。此函数不检查参数,但 SetMode 函数会检查它。
  • 它使用 Sys V x86-64 函数调用约定,但对 UEFI 函数的调用除外,这些函数使用 UEFI 约定。
  • 它使用一个名为 efi_printf 的函数,该函数的工作方式与 printf 类似,并使用 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL 写入 ConOut。
  • 它依赖于启动代码,该代码在名为 efi_boot_services 的全局变量中存储指向 EFI 引导服务表的指针。
  • 它是为气体而不是 nasm 编写的。

下面是示例输出:

max mode: 5
mode 1: size 36, ver 0, hor res 800, ver res 600, pixel format 1
frame buffer: b1000000, frame buffer size: 1d4c00
mode 0: size 36, ver 0, hor res 640, ver res 480, pixel format 1
mode 1: size 36, ver 0, hor res 800, ver res 600, pixel format 1
mode 2: size 36, ver 0, hor res 1024, ver res 768, pixel format 1
mode 3: size 36, ver 0, hor res 1280, ver res 1024, pixel format 1
mode 4: size 36, ver 0, hor res 1600, ver res 1200, pixel format 1

我假设你熟悉UEFI,所以我还没有解释一切是如何工作的,所以如果你需要更多的解释,请告诉我。

.intel_syntax noprefix
.section .text
.align  16
.globl  gfxmode
gfxmode:
push    rbx
push    rbp
push    r14
push    r15
sub     rsp, 0x38
mov     ebp, edi                // desired mode
lea     rcx, EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID[rip]
xor     edx, edx                // arg 2: unused
lea     r8, 0x20[rsp]           // arg 3: address of protocol
mov     rax, efi_boot_services[rip]
call    0x140[rax]              // locate protocol
test    rax, rax
js      2f
mov     r15, 0x20[rsp]          // graphics output protocol
mov     r14, 0x18[r15]          // mode
lea     rdi, trace1[rip]
mov     esi, [r14]              // max mode
call    efi_printf
mov     rdi, 8[r14]             // current mode info
mov     esi, 4[r14]             // current mode number
mov     edx, 16[r14]            // current mode info size
call    print_mode
lea     rdi, trace3[rip]
mov     rsi, 24[r14]            // frame buffer addr
mov     rdx, 32[r14]            // frame buffer size
call    efi_printf
xor     ebx, ebx
1:
mov     rcx, r15                // arg 1: graphics output protocol
mov     edx, ebx                // arg 2: mode number
lea     r8, 0x30[rsp]           // arg 3: &info size
lea     r9, 0x28[rsp]           // arg 4: &info
call    0x00[rcx]               // query mode
test    rax, rax
js      2f
mov     rdi, 0x28[rsp]          // mode info
mov     esi, ebx                // mode number
mov     edx, 0x30[rsp]          // mode info size
call    print_mode
mov     rax, efi_boot_services[rip]
mov     rcx, 0x28[rsp]          // mode info
call    0x48[rax]               // free pool
inc     ebx
cmp     ebx, [r14]              // max mode
jb      1b
xor     eax, eax
test    ebp, ebp                // new mode
js      2f
mov     rcx, r15                // arg 1: graphics output protocol
mov     edx, ebp                // arg 2: mode number
call    0x08[rcx]               // set mode
2:
add     rsp, 0x38
pop     r15
pop     r14
pop     rbp
pop     rbx
ret
.align  16
print_mode:
// rdi: mode info
// esi: mode number
// edx: mode size
mov     ecx, [rdi]              // mode version
mov     r8d, 4[rdi]             // hor res
mov     r9d, 8[rdi]             // ver res
mov     eax, 12[rdi]            // pixel format
push    rax
lea     rdi, trace2[rip]
call    efi_printf
add     rsp, 8
ret
trace1: .asciz  "max mode: %dn"
trace2: .asciz  "mode %d: size %d, ver %d, hor res %d, ver res %d, pixel format %dn"
trace3: .asciz  "frame buffer: %p, frame buffer size: %llxn"
.align  16
EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID:
.byte   0xde,0xa9,0x42,0x90,0xdc,0x23,0x38,0x4a
.byte   0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a

相关内容

  • 没有找到相关文章

最新更新