- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 NASM 中编写“Hello_world”EFI 应用程序,但似乎无法使其正常工作。当我运行应用程序(在 VirtualBox 中)时,它不打印任何内容。它只是挂起。这是我的代码:
Bits 64
DEFAULT REL
START:
PE:
HEADER_START:
STANDARD_HEADER:
.DOS_SIGNATURE db 'MZ' ; The DOS signature. This is apparently compulsory
.DOS_HEADERS times 60-($-STANDARD_HEADER) db 0 ; The DOS Headers. Probably not needed by UEFI
.SIGNATURE_POINTER dd .PE_SIGNATURE - START ; Pointer to the PE Signature
.DOS_STUB times 64 db 0 ; The DOS stub. Fill with zeros
.PE_SIGNATURE db 'PE', 0x00, 0x00 ; This is the pe signature. The characters 'PE' followed by 2 null bytes
.MACHINE_TYPE dw 0x8664 ; Targetting the x64 machine
.NUMBER_OF_SECTIONS dw 3 ; Number of sections. Indicates size of section table that immediately follows the headers
.CREATED_DATE_TIME dd 1657582794 ; Number of seconds since 1970 since when the file was created
.SYMBOL_TABLE_POINTER dd 0x00 ; Pointer to the symbol table. There should be no symbol table in an image so this is 0
.NUMBER_OF_SYMBOLS dd 0x00 ; Because there are no symbol tables in an image
.OPTIONAL_HEADER_SIZE dw OPTIONAL_HEADER_STOP - OPTIONAL_HEADER_START ; Size of the optional header
.CHARACTERISTICS dw 0b0010111000100010 ; These are the attributes of the file
OPTIONAL_HEADER_START:
.MAGIC_NUMBER dw 0x020B ; PE32+ (i.e. pe64) magic number
.MAJOR_LINKER_VERSION db 0 ; I'm sure this isn't needed. So set to 0
.MINOR_LINKER_VERSION db 0 ; This too
.SIZE_OF_CODE dd CODE_END - CODE ; The size of the code section
.INITIALIZED_DATA_SIZE dd DATA_END - DATA ; Size of initialized data section
.UNINITIALIZED_DATA_SIZE dd 0x00 ; Size of uninitialized data section
.ENTRY_POINT_ADDRESS dd EntryPoint - START ; Address of entry point relative to image base when the image is loaded in memory
.BASE_OF_CODE_ADDRESS dd CODE - START ; Relative address of base of code
.IMAGE_BASE dq 0x400000 ; Where in memory we would prefer the image to be loaded at
.SECTION_ALIGNMENT dd 0x1000 ; Alignment in bytes of sections when they are loaded in memory. Align to page boundry (4kb)
.FILE_ALIGNMENT dd 0x1000 ; Alignment of sections in the file. Also align to 4kb
.MAJOR_OS_VERSION dw 0x00 ; I'm not sure UEFI requires these and the following 'version woo'
.MINOR_OS_VERSION dw 0x00 ; More of these version thingies are to follow. Again, not sure UEFI needs them
.MAJOR_IMAGE_VERSION dw 0x00 ; Major version of the image
.MINOR_IMAGE_VERSION dw 0x00 ; Minor version of the image
.MAJOR_SUBSYSTEM_VERSION dw 0x00 ;
.MINOR_SUBSYSTEM_VERSION dw 0x00 ;
.WIN32_VERSION_VALUE dd 0x00 ; Reserved, must be 0
.IMAGE_SIZE dd END - START ; The size in bytes of the image when loaded in memory including all headers
.HEADERS_SIZE dd HEADER_END - HEADER_START ; Size of all the headers
.CHECKSUM dd 0x00 ; Hoping this doesn't break the application
.SUBSYSTEM dw 10 ; The subsystem. In this case we're making a UEFI application.
.DLL_CHARACTERISTICS dw 0b000011110010000 ; I honestly don't know what to put here
.STACK_RESERVE_SIZE dq 0x200000 ; Reserve 2MB for the stack... I guess...
.STACK_COMMIT_SIZE dq 0x1000 ; Commit 4kb of the stack
.HEAP_RESERVE_SIZE dq 0x200000 ; Reserve 2MB for the heap... I think... :D
.HEAP_COMMIT_SIZE dq 0x1000 ; Commit 4kb of heap
.LOADER_FLAGS dd 0x00 ; Reserved, must be zero
.NUMBER_OF_RVA_AND_SIZES dd 0x10 ; Number of entries in the data directory
DATA_DIRECTORIES:
EDATA:
.address dd 0 ; Address of export table
.size dd 0 ; Size of export table
IDATA:
.address dd 0 ; Address of import table
.size dd 0 ; Size of import table
RSRC:
.address dd 0 ; Address of resource table
.size dd 0 ; Size of resource table
PDATA:
.address dd 0 ; Address of exception table
.size dd 0 ; Size of exception table
CERT:
.address dd 0 ; Address of certificate table
.size dd 0 ; Size of certificate table
RELOC:
.address dd END - START ; Address of relocation table
.size dd 0 ; Size of relocation table
DEBUG:
.address dd 0 ; Address of debug table
.size dd 0 ; Size of debug table
ARCHITECTURE:
.address dd 0 ; Reserved. Must be 0
.size dd 0 ; Reserved. Must be 0
GLOBALPTR:
.address dd 0 ; RVA to be stored in global pointer register
.size dd 0 ; Must be 0
TLS:
.address dd 0 ; Address of TLS table
.size dd 0 ; Size of TLS table
LOADCONFIG:
.address dd 0 ; Address of Load Config table
.size dd 0 ; Size of Load Config table
BOUNDIMPORT:
.address dd 0 ; Address of bound import table
.size dd 0 ; Size of bound import table
IAT:
.address dd 0 ; Address of IAT
.size dd 0 ; Size of IAT
DELAYIMPORTDESCRIPTOR:
.address dd 0 ; Address of delay import descriptor
.size dd 0 ; Size of delay import descriptor
CLRRUNTIMEHEADER:
.address dd 0 ; Address of CLR runtime header
.size dd 0 ; Size of CLR runtime header
RESERVED:
.address dd 0 ; Reserved, must be 0
.size dd 0 ; Reserved, must be 0
OPTIONAL_HEADER_STOP:
HEADER_END:
SECTION_HEADERS:
SECTION_CODE:
.name db ".text", 0x00, 0x00, 0x00
.virtual_size dd CODE_END - CODE
.virtual_address dd CODE - START
.size_of_raw_data dd CODE_END - CODE
.pointer_to_raw_data dd CODE - START
.pointer_to_relocations dd 0 ; Set to 0 for executable images
.pointer_to_line_numbers dd 0 ; There are no COFF line numbers
.number_of_relocations dw 0 ; Set to 0 for executable images
.number_of_line_numbers dw 0 ; Should be 0 for images
.characteristics dd 0x70000020 ; Need to read up more on this
SECTION_DATA:
.name db ".data", 0x00, 0x00, 0x00
.virtual_size dd DATA_END - DATA
.virtual_address dd DATA - START
.size_of_raw_data dd DATA_END - DATA
.pointer_to_raw_data dd DATA - START
.pointer_to_relocations dd 0
.pointer_to_line_numbers dd 0
.number_of_relocations dw 0
.number_of_line_numbers dw 0
.characteristics dd 0xD0000040
SECTION_RELOC:
.name db ".reloc", 0x00, 0x00
.virtual_size dd 0
.virtual_address dd 0
.size_of_raw_data dd 0
.pointer_to_raw_data dd END - START
.pointer_to_relocations dd 0
.pointer_to_line_numbers dd 0
.number_of_relocations dw 0
.number_of_line_numbers dw 0
.characteristics dd 0xC2000040
times 4096-($-PE) db 0
CODE:
; The code begins here with the entry point
EntryPoint:
; First order of business is to store the values that were passed to us by EFI
mov [EFI_IMAGE_HANDLE], rcx
mov [EFI_SYSTEM_TABLE], rdx
; Locate OutputString of the TEXT_OUTPUT_PROTOCOL
add rdx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
mov rcx, [abs rdx] ; This is the first parameter to the call
mov rdx, [abs rdx] ; Now rdx points to simple text output protocol
add rdx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OutputString ; Now rdx points to output string
mov rax, [abs rdx] ; We'll later do `call rax`
lea rdx, [hello_message] ; The string to be printed
sub rsp, 40 ; Shadow space on the stack before the call
call rax
mov eax, EFI_SUCCESS
retn
align 4096
CODE_END:
; Data begins here
DATA:
EFI_IMAGE_HANDLE dq 0x00 ; EFI will give use this in rcx
EFI_SYSTEM_TABLE dq 0x00 ; And this in rdx
hello_message db __utf16__ `Hello_world\0` ; EFI strings are UTF16 and null-terminated
align 4096
DATA_END:
END:
; Define the needed EFI constants and offsets here.
EFI_SUCCESS equ 0
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL equ 64
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_Reset equ 0
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OutputString equ 8
假设文件保存为“hello.asm”,我使用 nasm -f bin -o hello.efi hello.asm
进行汇编。我可能做错了什么?
P.S:我知道我可以使用结构来计算偏移量,但我想自己进行计算。
P.P.S:这是我在网上找到的一个有效的 FASM 版本:http://x86asm.net/articles/uefi-programming-first-steps/index.html#Building-an-UEFI-application .我使用这个在线工具 (https://manalyzer.org/) 进行检查,发现它的入口点位于 .data
部分。现在我很好奇它的工作原理和原因。
最佳答案
多亏了 osdev forum 的人,我才能够解决这个问题. .HEADERS_SIZE
应该包括章节标题并且应该是 .FILE_ALIGNMENT
的倍数。这意味着 HEADER_END:
行应该紧接在 times 4096-($-PE) db 0
之后,因为我正在通过执行 .HEADERS_SIZE
计算 HEADER_END - HEADER_START
。
总而言之,这是对我有用的修改后的代码:
Bits 64
DEFAULT REL
START:
PE:
HEADER_START:
STANDARD_HEADER:
.DOS_SIGNATURE db 'MZ' ; The DOS signature. This is apparently compulsory
.DOS_HEADERS times 60-($-STANDARD_HEADER) db 0 ; The DOS Headers. Probably not needed by UEFI
.SIGNATURE_POINTER dd .PE_SIGNATURE - START ; Pointer to the PE Signature
.DOS_STUB times 64 db 0 ; The DOS stub. Fill with zeros
.PE_SIGNATURE db 'PE', 0x00, 0x00 ; This is the pe signature. The characters 'PE' followed by 2 null bytes
.MACHINE_TYPE dw 0x8664 ; Targetting the x64 machine
.NUMBER_OF_SECTIONS dw 3 ; Number of sections. Indicates size of section table that immediately follows the headers
.CREATED_DATE_TIME dd 1657582794 ; Number of seconds since 1970 since when the file was created
.SYMBOL_TABLE_POINTER dd 0x00 ; Pointer to the symbol table. There should be no symbol table in an image so this is 0
.NUMBER_OF_SYMBOLS dd 0x00 ; Because there are no symbol tables in an image
.OPTIONAL_HEADER_SIZE dw OPTIONAL_HEADER_STOP - OPTIONAL_HEADER_START ; Size of the optional header
.CHARACTERISTICS dw 0b0010111000100010 ; These are the attributes of the file
OPTIONAL_HEADER_START:
.MAGIC_NUMBER dw 0x020B ; PE32+ (i.e. pe64) magic number
.MAJOR_LINKER_VERSION db 0 ; I'm sure this isn't needed. So set to 0
.MINOR_LINKER_VERSION db 0 ; This too
.SIZE_OF_CODE dd CODE_END - CODE ; The size of the code section
.INITIALIZED_DATA_SIZE dd DATA_END - DATA ; Size of initialized data section
.UNINITIALIZED_DATA_SIZE dd 0x00 ; Size of uninitialized data section
.ENTRY_POINT_ADDRESS dd EntryPoint - START ; Address of entry point relative to image base when the image is loaded in memory
.BASE_OF_CODE_ADDRESS dd CODE - START ; Relative address of base of code
.IMAGE_BASE dq 0x400000 ; Where in memory we would prefer the image to be loaded at
.SECTION_ALIGNMENT dd 0x1000 ; Alignment in bytes of sections when they are loaded in memory. Align to page boundry (4kb)
.FILE_ALIGNMENT dd 0x1000 ; Alignment of sections in the file. Also align to 4kb
.MAJOR_OS_VERSION dw 0x00 ; I'm not sure UEFI requires these and the following 'version woo'
.MINOR_OS_VERSION dw 0x00 ; More of these version thingies are to follow. Again, not sure UEFI needs them
.MAJOR_IMAGE_VERSION dw 0x00 ; Major version of the image
.MINOR_IMAGE_VERSION dw 0x00 ; Minor version of the image
.MAJOR_SUBSYSTEM_VERSION dw 0x00 ;
.MINOR_SUBSYSTEM_VERSION dw 0x00 ;
.WIN32_VERSION_VALUE dd 0x00 ; Reserved, must be 0
.IMAGE_SIZE dd END - START ; The size in bytes of the image when loaded in memory including all headers
.HEADERS_SIZE dd HEADER_END - HEADER_START ; Size of all the headers
.CHECKSUM dd 0x00 ; Hoping this doesn't break the application
.SUBSYSTEM dw 10 ; The subsystem. In this case we're making a UEFI application.
.DLL_CHARACTERISTICS dw 0b000011110010000 ; I honestly don't know what to put here
.STACK_RESERVE_SIZE dq 0x200000 ; Reserve 2MB for the stack... I guess...
.STACK_COMMIT_SIZE dq 0x1000 ; Commit 4kb of the stack
.HEAP_RESERVE_SIZE dq 0x200000 ; Reserve 2MB for the heap... I think... :D
.HEAP_COMMIT_SIZE dq 0x1000 ; Commit 4kb of heap
.LOADER_FLAGS dd 0x00 ; Reserved, must be zero
.NUMBER_OF_RVA_AND_SIZES dd 0x10 ; Number of entries in the data directory
DATA_DIRECTORIES:
EDATA:
.address dd 0 ; Address of export table
.size dd 0 ; Size of export table
IDATA:
.address dd 0 ; Address of import table
.size dd 0 ; Size of import table
RSRC:
.address dd 0 ; Address of resource table
.size dd 0 ; Size of resource table
PDATA:
.address dd 0 ; Address of exception table
.size dd 0 ; Size of exception table
CERT:
.address dd 0 ; Address of certificate table
.size dd 0 ; Size of certificate table
RELOC:
.address dd END - START ; Address of relocation table
.size dd 0 ; Size of relocation table
DEBUG:
.address dd 0 ; Address of debug table
.size dd 0 ; Size of debug table
ARCHITECTURE:
.address dd 0 ; Reserved. Must be 0
.size dd 0 ; Reserved. Must be 0
GLOBALPTR:
.address dd 0 ; RVA to be stored in global pointer register
.size dd 0 ; Must be 0
TLS:
.address dd 0 ; Address of TLS table
.size dd 0 ; Size of TLS table
LOADCONFIG:
.address dd 0 ; Address of Load Config table
.size dd 0 ; Size of Load Config table
BOUNDIMPORT:
.address dd 0 ; Address of bound import table
.size dd 0 ; Size of bound import table
IAT:
.address dd 0 ; Address of IAT
.size dd 0 ; Size of IAT
DELAYIMPORTDESCRIPTOR:
.address dd 0 ; Address of delay import descriptor
.size dd 0 ; Size of delay import descriptor
CLRRUNTIMEHEADER:
.address dd 0 ; Address of CLR runtime header
.size dd 0 ; Size of CLR runtime header
RESERVED:
.address dd 0 ; Reserved, must be 0
.size dd 0 ; Reserved, must be 0
OPTIONAL_HEADER_STOP:
SECTION_HEADERS:
SECTION_CODE:
.name db ".text", 0x00, 0x00, 0x00
.virtual_size dd CODE_END - CODE
.virtual_address dd CODE - START
.size_of_raw_data dd CODE_END - CODE
.pointer_to_raw_data dd CODE - START
.pointer_to_relocations dd 0 ; Set to 0 for executable images
.pointer_to_line_numbers dd 0 ; There are no COFF line numbers
.number_of_relocations dw 0 ; Set to 0 for executable images
.number_of_line_numbers dw 0 ; Should be 0 for images
.characteristics dd 0x70000020 ; Need to read up more on this
SECTION_DATA:
.name db ".data", 0x00, 0x00, 0x00
.virtual_size dd DATA_END - DATA
.virtual_address dd DATA - START
.size_of_raw_data dd DATA_END - DATA
.pointer_to_raw_data dd DATA - START
.pointer_to_relocations dd 0
.pointer_to_line_numbers dd 0
.number_of_relocations dw 0
.number_of_line_numbers dw 0
.characteristics dd 0xD0000040
SECTION_RELOC:
.name db ".reloc", 0x00, 0x00
.virtual_size dd 0
.virtual_address dd END - START
.size_of_raw_data dd 0
.pointer_to_raw_data dd END - START
.pointer_to_relocations dd 0
.pointer_to_line_numbers dd 0
.number_of_relocations dw 0
.number_of_line_numbers dw 0
.characteristics dd 0xC2000040
times 4096-($-PE) db 0
HEADER_END:
CODE:
; The code begins here with the entry point
EntryPoint:
; First order of business is to store the values that were passed to us by EFI
mov [EFI_IMAGE_HANDLE], rcx
mov [EFI_SYSTEM_TABLE], rdx
; Locate OutputString of the TEXT_OUTPUT_PROTOCOL
add rdx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
mov rcx, [rdx] ; This is the first parameter to the call
mov rdx, [rdx] ; Now rdx points to simple text output protocol
add rdx, EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OutputString ; Now rdx points to output string
mov rax, [rdx] ; We'll later do `call rax`
lea rdx, [hello_message] ; The string to be printed
sub rsp, 32 ; Shadow space on the stack before the call
call rax
add rsp, 32
mov rax, EFI_SUCCESS
ret
align 4096
CODE_END:
; Data begins here
DATA:
EFI_IMAGE_HANDLE dq 0x00 ; EFI will give use this in rcx
EFI_SYSTEM_TABLE dq 0x00 ; And this in rdx
hello_message db __utf16__ `Hello_world\0` ; EFI strings are UTF16 and null-terminated
align 4096
DATA_END:
END:
; Define the needed EFI constants and offsets here.
EFI_SUCCESS equ 0
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL equ 64
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_Reset equ 0
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OutputString equ 8
关于assembly - 如何在 NASM 中编写 'Hello_world' EFI 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72947069/
我被告知“汇编”是您在文件中编写的内容,让您的“汇编程序”将其转换为二进制代码。 但我看到这两个术语在各种作品中混合搭配。我什至听说你编写了“汇编器”,然后“汇编器”使其可执行。 正确的用词是什么?
我在正确终止用 Assembly 编写的 16 位 DOS 程序时遇到问题。这是部分代码: .386P .model flat stack_s segment stack 'stack'
我需要多少档才能正确执行以下指令。我对我所做的事情有些困惑,所以我在这里看到专家的答案。 lw $1,0($2); beq $1,$2,Label; 请注意,检查是否会发生分支将在解码阶段完成。但是在
我正在尝试在汇编中进行简单的乘法运算,但是由于某些原因,当标记了MUL函数时,我看不到寄存器会发生变化。 mov bx, 5 mov cx, 10 mul cx 最佳答案 这些称为指令,它们指定
我正在尝试在 Assembly 中实现递归斐波那契程序。但是,我的程序崩溃了,出现了未处理的异常,我似乎无法找出问题所在。我不怀疑这涉及我对堆栈的不当使用,但我似乎无法指出哪里...... .386
我编写了以下代码: .386 .model small .stack 100h .data text db "Paper",0 .code start : lea dx ,
我有一个用汇编语言编写的裸机 ARM 的启动代码,我正在尝试了解它是如何工作的。该二进制文件被写入一些外部闪存中,并在启动时将其自身的一部分复制到 RAM 中。尽管我读过这篇文章wikipedia e
我在数据部分定义了一个二维数组和两个一维数组(一个用于列总和,一个用于行总和),并且我编写了一个函数,将二维数组求和到一维数组中。我使用 eax 和 ebx 作为二维数组的索引,但是当 eax 或 e
我正在开始组装,我正在使用 nasm 来组装代码,我正在尝试处理驻留在内存中的字符串并更改它,我想检查一个字节是否在某个范围内(ascii),这样我就可以决定如何处理它,我似乎不知道如何检查一个值是否
虽然您通常不希望将一个整体程序集用于小型项目以外的任何事情,但可能会将事物分离得太多。 组装分离过多的迹象/气味是什么? 最佳答案 第一个(明显的)是:在一个有很多项目的解决方案中,其中只有少数(比如
我正在尝试编写斐波那契的汇编代码版本,它给出第 n 个斐波那契数并返回它。 出于某种原因,它在存储斐波那契数的返回值和添加它们时遇到问题。 我希望它打印第 n 个斐波那契数。 我对我的代码做了一些修改
我有一个最小的、可重现的示例有两个问题,该示例具有三个针对 .NET Core 3.1 的项目。但我也想以 .NET Standard 2.0 为目标。 该示例适用于需要在运行时加载程序集并使用提供的
: 运算符在汇编中做什么?代码如下:DS:DX我还没有找到该运算符(operator)的任何文档。(我正在使用 NASM) 最佳答案 那实际上只是一个寄存器分隔符,而不是运算符。这意味着使用 DX 寄
我在哪里可以找到为 gmp-5.0.0 编写的程序的汇编代码我正在使用 UBUNTU 和 G++ 编译器..编译代码的命令是“g++ test.cc -o outp -lgmp” 实际上我想知道在 1
我是组装新手,我有一个关于如何表示负数的问题 我有三个 DWORDS 变量,比如说: result DWORD 0 i DWORD 3 j DWORD 5 我想计算这个公式:result = i -
我想编写我的第一个汇编程序。我在论文上做了一些程序,但这是我第一次使用编译器。我正在使用 ideone .我的程序很简单, 翻译 A = 5 - A到 assembly NEG A ADD A, 5
程序集,masm 嘿,我写了宏来打印存储在 dane1 段中的 1 字节值。 我将值除以 16,然后将提醒推送到堆栈,直到值==0。然后我弹出提醒将它们转换为 ASCII 码,并打印它们。 有人可以看
我正在研究 nasm 的一个大学项目。唯一的问题是我无法生成 162 和 278 之间的偶数随机数。我尝试了很多算法,但似乎无法限制范围内的数字。 是否有一个小技巧或调整来获得所需的范围内的数字?目的
终于在无数次错误的漫长 session 之后,希望这是最后一个。 没有编译或运行时错误,只是一个逻辑错误。 编辑:(固定伪代码) 我的伪代码: first = 1; second = 1; thir
我知道在程序集r0中调用函数时,包含第一个参数,直到r3是第四个。我知道,当它超过四个时,将使用堆栈指针,但是我不太确定具体细节。 r0-r3仍然保持前四个,其余的进入堆栈吗?我正在看下面的程序集,试
我是一名优秀的程序员,十分优秀!