Assembly 汇编-如何在UEFI中设置图形模式(没有VGA,没有BIOS,没有不推荐的)
我正在使用的工具:nasm、qemu-system-x86_64 我使用的操作系统:Windows10 所以我在 这篇文章似乎暗示的是,任何事情都可以在不使用BIOS中断的情况下完成。我知道如何加载长模式,所以我已经这样做了,但现在我被卡住了,因为BIOS中断是我现在所知道的全部。我想做一些类似于将图形模式设置为完全内存访问模式的事情(如果您看过Assembly 汇编-如何在UEFI中设置图形模式(没有VGA,没有BIOS,没有不推荐的),assembly,graphics,64-bit,uefi,Assembly,Graphics,64 Bit,Uefi,我正在使用的工具:nasm、qemu-system-x86_64 我使用的操作系统:Windows10 所以我在 这篇文章似乎暗示的是,任何事情都可以在不使用BIOS中断的情况下完成。我知道如何加载长模式,所以我已经这样做了,但现在我被卡住了,因为BIOS中断是我现在所知道的全部。我想做一些类似于将图形模式设置为完全内存访问模式的事情(如果您看过int10h/AX=4F02h/BX=81FFh,听起来可能会很熟悉),但因为我不想使用不推荐使用的东西(BIOS),我在网上搜索如何设置图形模式,然后
int10h/AX=4F02h/BX=81FFh
,听起来可能会很熟悉),但因为我不想使用不推荐使用的东西(BIOS),我在网上搜索如何设置图形模式,然后只在长模式下访问单个像素时遇到了问题
希望能在StackOverflow上回答这个问题。我非常相信“它太复杂了”不会作为答案出现,特别是因为OSDev刚刚告诉我不要使用不推荐的东西。告诉别人这太难了,假设他们知道什么,他们能学到什么,甚至不知道他们是谁。我只需要一个起点来找出如何做到这一点
要澄清的是,对我不起作用的事情:
这对我不起作用,因为答案给出了指向VGA的链接,我不想要
这对我不起作用,因为问题不是问长模式,而是问真实模式下的VGA图形
这对我来说不起作用,因为答案基本上是“太复杂了,使用不推荐的东西”,这与我试图做的相反,也与我刚刚在OSDev上听到的相反
这对我不起作用,因为答案与设置图形模式无关
这对我不起作用,因为答案没有说明如何在UEFI中设置图形模式。他们只谈论不推荐的东西。下面是使用UEFI在第一个图形设备上获取和打印可用图形模式的示例代码,并可以选择设置模式 我使用了以下引用: 关于执行情况的说明:
- 它调用LocateProtocol以获取图形输出协议。我尝试使用LocatHandle获取所有支持图形输出协议的句柄。它返回了两个句柄,但OpenProtocol失败。我还没有机会用LocateHandle调试这个版本。此版本使用LocateProtocol工作
- 它打印可用模式的数量、当前模式以及每个模式的特征
- 该功能的参数是要设置的模式。如果为-1,则模式不变。否则它必须介于0和N-1之间,其中N是支持的图形模式数。此函数不检查参数,但SetMode函数检查它
- 它使用Sys V x86-64函数调用约定,但对UEFI函数的调用除外,该函数使用UEFI约定
- 它使用一个名为efi_printf的函数,该函数的工作原理与printf类似,并使用efi_SIMPLE_TEXT_OUTPUT_协议写入ConOut
- 它依赖于在名为EFI_Boot_Services的全局变量中存储指向EFI Boot Services表的指针的启动代码
- 它是为气体而不是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: %d\n"
trace2: .asciz "mode %d: size %d, ver %d, hor res %d, ver res %d, pixel format %d\n"
trace3: .asciz "frame buffer: %p, frame buffer size: %llx\n"
.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
如果您只需要切换一次图形模式,则使用UEFI的图形输出协议在UEFI引导加载程序中切换视频模式如果您需要在操作系统启动后切换图形模式,则需要为您想要支持的每种视频卡编写视频驱动程序。与BIOS服务不同,UEFI服务在操作系统加载后不工作。这“因为答案基本上是”太复杂了,请使用不推荐使用的东西“其实包含了相当详细的答案,从哪里开始。。。不确定您还希望得到什么,复制~5000行文档以使堆栈溢出没有多大意义,您可以自己阅读(英特尔集成卡手册,其他供应商通常更难获得文件,或者对于个人来说完全不可能)我主要在寻找一个具体的源代码示例,它展示了一种使用UEFI设置视频模式的方法,然后我就可以进行反向工程。这是我学习新东西的最好方法之一。尝试Linux源代码,但它不使用UEFI设置视频模式,因为正如我所解释的,它不能。你可以看看GRUB GOP驱动程序,我想:哦,我对UEFI一无所知,我到目前为止只使用过BIOS,这就是我发布这篇文章的原因。你知道除了UEFI(一个用于各种事情的内存地址列表,或者一个协议列表,而不是一个中断列表),我在哪里可以找到与拉尔夫·布朗(Ralph Brown)相同的中断列表比拉尔夫·布朗的中断列表要好得多,因为它是一个实际的规范,而不仅仅是随着时间的推移而演变的软件接口的积累。