flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > Pushing relocatable addresses onto UEFI stack |
Author |
|
sinsi 17 Jan 2024, 04:22
Code: lea rax,[Buffer] push rax Extra bonus, this is now position-independent code, since LEA should use RIP-relative addressing (as long as it is within 2GB) Just curious, how does removing the qword qualifier work? |
|||
17 Jan 2024, 04:22 |
|
Tomasz Grysztar 17 Jan 2024, 06:48
pfranz wrote: And how can I detect that a parameter is a relocatable address in fasm? Code: if ~ Buffer relativeto 0 |
|||
17 Jan 2024, 06:48 |
|
pfranz 17 Jan 2024, 06:52
Yes, using registers (either with lea or mov) works, I wanted to avoid it or at least give a warning when an address would be passed to "push".
Removing "qword" shouldn't change anything. |
|||
17 Jan 2024, 06:52 |
|
sinsi 17 Jan 2024, 06:58
LEA uses RIP-relative (PIC), MOV will use a relocatable address (not PIC)
|
|||
17 Jan 2024, 06:58 |
|
revolution 17 Jan 2024, 07:35
pfranz wrote: YRemoving "qword" shouldn't change anything. |
|||
17 Jan 2024, 07:35 |
|
Tomasz Grysztar 17 Jan 2024, 07:50
revolution wrote:
I consider this a legacy feature, which I dropped when implementing instruction encoders for fasm 2 - there the new instruction decorators would allow to control the encoding when really necessary (which is rare). |
|||
17 Jan 2024, 07:50 |
|
pfranz 17 Jan 2024, 13:05
But in this case nothing changes, addresses need at least 32 bit and push only encodes 32 bits, can't encode 64 bits. You always get 68h + 32bit address.
PE64 stores 32bit for the address that is more than enough when assembling; but what happens if that address gets relocated beyond 4GB? Push only have space for 32 bits. |
|||
17 Jan 2024, 13:05 |
|
revolution 17 Jan 2024, 13:22
This is what happens for values out of range for push.
Code: push 1 shl 31 processed: push 1 shl 31 error: value out of range. |
|||
17 Jan 2024, 13:22 |
|
pfranz 17 Jan 2024, 14:17
revolution wrote: This is what happens for values out of range for push. Also, using RIP relative code is not the only solution. You can also use mov r64, relocatable address push r64 and it will work because that kind of mov encodes all 64 bits and relocation works fine. But you still must use registers, what I wanted to avoid |
|||
17 Jan 2024, 14:17 |
|
Tomasz Grysztar 17 Jan 2024, 14:17
revolution wrote: Also note that you can't push relocatable addresses unless you use RIP relative code, as mentioned by sinsi above. An address that is relocatable needs all 64-bits. |
|||
17 Jan 2024, 14:17 |
|
pfranz 17 Jan 2024, 14:22
Tomasz Grysztar wrote:
There is no linker involved when I produce bootx64.efi with "format pe64 efi". I believe a warning from fasm is needed. |
|||
17 Jan 2024, 14:22 |
|
revolution 17 Jan 2024, 15:57
pfranz wrote: I pushed relocatable addresses (see my initial post) without any error.FASM doesn't complain because at assemble time the value is small. Why is there difficulty with using registers? Last edited by revolution on 17 Jan 2024, 16:42; edited 1 time in total |
|||
17 Jan 2024, 15:57 |
|
Tomasz Grysztar 17 Jan 2024, 16:37
If you try fasm 2, you can disable the option of making 32-bit relocations by adding a "purge dword?" line after the format setting:
Code: format PE64 purge dword? ; disables 32-bit relocations with fasm 2, has no effect on fasm 1 data fixups end data mov rax,$ ; 64-bit relocation push $ ; 32-bit relocation |
|||
17 Jan 2024, 16:37 |
|
pfranz 17 Jan 2024, 17:33
revolution wrote: Why is there difficulty with using registers? It just happened: my loader worked fine everywhere, then I tried it on a 4GB machine and it would get stuck. It took me some time to find the problem out. |
|||
17 Jan 2024, 17:33 |
|
bzt 17 Jan 2024, 19:40
pfranz wrote: I am writing a general purpose macro to call uefi functions Code: macro InitializeLib { clc or rdx, rdx jz .badout cmp dword [rdx], 20494249h je @f .badout: xor rcx, rcx xor rdx, rdx stc @@: mov [efi_handler], rcx ; ImageHandle mov [efi_ptr], rdx ; pointer to SystemTable } ;invoke an UEFI function macro uefi_call_wrapper interface,function,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11 { numarg = 0 if ~ arg11 eq numarg = numarg + 1 if ~ arg11 eq rdi mov rdi, arg11 end if end if if ~ arg10 eq numarg = numarg + 1 if ~ arg10 eq rsi mov rsi, arg10 end if end if if ~ arg9 eq numarg = numarg + 1 if ~ arg9 eq r14 mov r14, arg9 end if end if if ~ arg8 eq numarg = numarg + 1 if ~ arg8 eq r13 mov r13, arg8 end if end if if ~ arg7 eq numarg = numarg + 1 if ~ arg7 eq r12 mov r12, arg7 end if end if if ~ arg6 eq numarg = numarg + 1 if ~ arg6 eq r11 mov r11, arg6 end if end if if ~ arg5 eq numarg = numarg + 1 if ~ arg5 eq r10 mov r10, arg5 end if end if if ~ arg4 eq numarg = numarg + 1 if ~ arg4 eq r9 mov r9, arg4 end if end if if ~ arg3 eq numarg = numarg + 1 if ~ arg3 eq r8 mov r8, arg3 end if end if if ~ arg2 eq numarg = numarg + 1 if ~ arg2 eq rdx mov rdx, arg2 end if end if if ~ arg1 eq numarg = numarg + 1 if ~ arg1 eq rcx if ~ arg1 in <ConsoleInHandle,ConIn,ConsoleOutHandle,ConOut,StandardErrorHandle,StdErr,RuntimeServices,BootServices> mov rcx, arg1 end if end if end if xor rax, rax mov al, numarg if interface in <ConsoleInHandle,ConIn,ConsoleOutHandle,ConOut,StandardErrorHandle,StdErr,RuntimeServices,BootServices> mov rbx, [efi_ptr] mov rbx, [rbx + EFI_SYSTEM_TABLE.#interface] else if ~ interface eq rbx mov rbx, interface end if end if if arg1 in <ConsoleInHandle,ConIn,ConsoleOutHandle,ConOut,StandardErrorHandle,StdErr,RuntimeServices,BootServices> mov rcx, rbx end if if defined SIMPLE_INPUT_INTERFACE.#function mov rbx, [rbx + SIMPLE_INPUT_INTERFACE.#function] else if defined SIMPLE_TEXT_OUTPUT_INTERFACE.#function mov rbx, [rbx + SIMPLE_TEXT_OUTPUT_INTERFACE.#function] else if defined EFI_BOOT_SERVICES_TABLE.#function mov rbx, [rbx + EFI_BOOT_SERVICES_TABLE.#function] else if defined EFI_RUNTIME_SERVICES_TABLE.#function mov rbx, [rbx + EFI_RUNTIME_SERVICES_TABLE.#function] else if defined EFI_GRAPHICS_OUTPUT_PROTOCOL.#function mov rbx, [rbx + EFI_GRAPHICS_OUTPUT_PROTOCOL.#function] else if defined EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.#function mov rbx, [rbx + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE.#function] else mov rbx, [rbx + function] end if end if end if end if end if end if call uefifunc } ;********************************************************************* ;* Library functions * ;********************************************************************* section '.text' code executable readable uefifunc: ;save stack pointer mov qword [uefi_rsptmp], rsp ;set up new aligned stack and esp, 0FFFFFFF0h ;alignment check on arguments bt eax, 0 jnc @f push rax ;arguments @@: cmp al, 11 jb @f push rdi @@: cmp al, 10 jb @f push rsi @@: cmp al, 9 jb @f push r14 @@: cmp al, 8 jb @f push r13 @@: cmp al, 7 jb @f push r12 @@: cmp al, 6 jb @f push r11 @@: cmp al, 5 jb @f push r10 @@: ;space for ;r9 ;r8 ;rdx ;rcx sub rsp, 4*8 ;call function call rbx ;restore old stack mov rsp, qword [uefi_rsptmp] ret section '.data' data readable writeable efi_handler: dq 0 efi_ptr: dq 0 uefi_rsptmp: dq 0 |
|||
17 Jan 2024, 19:40 |
|
pfranz 17 Jan 2024, 21:08
I had started from yours, but modified it because it was too cumbersome, in my opinion, and most of all trashes too many registers. You don't have my problem because you use a register for each parameter, even those pushed on the stack, but this creates a mess when you use a register as argument.
It may be difficult to figure out what happens in these cases: mov r10, 57 uefi_call interface, function, r10, 1,2,3,4 With your code, you think you pass 57 as first parameter, but you are actually passing 4. |
|||
17 Jan 2024, 21:08 |
|
revolution 17 Jan 2024, 21:13
There is a simple fix that doesn't trash any registers.
Code: push rax lea rax,[arg] xchg rax,[rsp] |
|||
17 Jan 2024, 21:13 |
|
pfranz 17 Jan 2024, 23:52
revolution wrote: There is a simple fix that doesn't trash any registers. But you can use mov instead of lea, that works. I was trying to do something simpler, that is why I asked whether it was possible to force bootx64.efi to be loaded in the first 2GB. In the first 4GB you may use push arg mov dword [rsp+4], 0 which is simpler but you have to test whether arg is an immediate negative number, a 64-bit memory reference, a register ... (in which case you skip the mov), or else make sure it is a relocatable address with relativeto 0 as Tomasz suggested. Either way, it's not so simple. |
|||
17 Jan 2024, 23:52 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.