OSDev.org
https://forum.osdev.org/

Simple Assembly UEFI Application -- Can't Exit Boot Services
https://forum.osdev.org/viewtopic.php?f=1&t=33666
Page 2 of 2

Author:  MichaelPetch [ Mon Apr 29, 2019 2:22 pm ]
Post subject:  Re: Simple Assembly UEFI Application -- Can't Exit Boot Serv

zaval wrote:
[code]
main:
push rbx
push r12
sub rsp, 6 * 8 ; keeping it 16 byte aligned
The stack isn't aligned at the EFI entry point (it was before the call instruction executed). It is misaligned by 8 upon entry since the return address was pushed on the stack by the call. 8+8+6*8 has to have an additional 8 added to it to get the stack properly aligned. It should be sub rsp, 6 * 8 + 8

Author:  zaval [ Mon Apr 29, 2019 3:28 pm ]
Post subject:  Re: Simple Assembly UEFI Application -- Can't Exit Boot Serv

MichaelPetch wrote:
zaval wrote:
Code:
main:
   push   rbx
   push   r12
   sub   rsp, 6 * 8   ; keeping it 16 byte aligned


The stack isn't aligned at the EFI entry point (it was before the call instruction executed). It is misaligned by 8 upon entry since the return address was pushed on the stack by the call. 8+8+6*8 has to have an additional 8 added to it to get the stack properly aligned. It should be sub rsp, 6 * 8 + 8

yes, I added and removed some nonvolatile registers and it ended up misaligned (this is the price of writing in assembly). it is allowed to be misaligned within a prolog (the piece above), but the prolog should make it aligned back. it's my fault, I'll fix it. because the main function doesn't make use of any stack variables, it's enough to make it 5 * 8.

Btw, your code preserves volatile registers (why?) and doesn't nonvolatile ones (rbx for example), but uses it. For example, here:
Code:
printhex:
                         ; Stack msialigned by 8 at function entry
mov rbp, 16          ; <--- should be preserved before usage
push rax             ; <--- shouldn't be preserved
push rcx              ; <--- shouldn't be preserved
push rdx                ; 3 pushes also align stack on 16 byte boundary
                         ; (8+3*8)=32, 32 evenly divisible by 16
sub rsp, 32             ; Allocate 32 bytes of shadow space
.loop:
    rol rbx, 4         ;<--- should be preserved before usage

Author:  MichaelPetch [ Mon Apr 29, 2019 4:09 pm ]
Post subject:  Re: Simple Assembly UEFI Application -- Can't Exit Boot Serv

zaval wrote:
MichaelPetch wrote:
zaval wrote:
Code:
main:
   push   rbx
   push   r12
   sub   rsp, 6 * 8   ; keeping it 16 byte aligned


The stack isn't aligned at the EFI entry point (it was before the call instruction executed). It is misaligned by 8 upon entry since the return address was pushed on the stack by the call. 8+8+6*8 has to have an additional 8 added to it to get the stack properly aligned. It should be sub rsp, 6 * 8 + 8

yes, I added and removed some nonvolatile registers and it ended up misaligned (this is the price of writing in assembly). it is allowed to be misaligned within a prolog (the piece above), but the prolog should make it aligned back. it's my fault, I'll fix it. because the main function doesn't make use of any stack variables, it's enough to make it 5 * 8.

Btw, your code preserves volatile registers (why?) and doesn't nonvolatile ones (rbx for example), but uses it. For example, here:
Code:
printhex:
                         ; Stack msialigned by 8 at function entry
mov rbp, 16          ; <--- should be preserved before usage
push rax             ; <--- shouldn't be preserved
push rcx              ; <--- shouldn't be preserved
push rdx                ; 3 pushes also align stack on 16 byte boundary
                         ; (8+3*8)=32, 32 evenly divisible by 16
sub rsp, 32             ; Allocate 32 bytes of shadow space
.loop:
    rol rbx, 4         ;<--- should be preserved before usage
Because his printhex routine did it, and since printhex can be any calling convention he chooses I kept it as is so that I didn't have to look over the rest of his code to find and change other register usage if I shifted to using nonvolatile registers (I had actually considered doing that originally, and chose to keep his code more or less the same where I could). The only intention I had with printhex was to assure that the alignment was maintained across the function calls, and to keep his calling convention for it the same. As an internal function printhex doesn't need to be a specific convention. There are other things in that code that are inefficient but my goal was to keep his code the same where I could.

Would have been a different story is printhex and others had some kind of external linkage and there was a requirement for the 64-bit ABI. It would have been a far bigger concern had the main code (starting at the entry point) had to return back to the caller(FI shell etc), but it doesn't so one can get away in this case with non standard register usage and conventions as long as he calls the UEFI services with the required registers, stack layout, and alignment. This of course isn't good coding practice especially if he were to return back to an EFI shell.

Had I written this it would have been substantially different. I had also observed that although this code generates an EFI program that seems to work, and Objdump understands it enough to dump it as a 64-bit PE file, but interestingly enough the utility file sees it only as some kind of DOS executable. I didn't spend time looking at file's source code and debugging it to find out what it didn't like or whether there may be a real compatibility issue or not.

Author:  charlesap [ Mon May 13, 2019 6:42 pm ]
Post subject:  Re: Simple Assembly UEFI Application -- Can't Exit Boot Serv

Michael, Zaval, everybody, thank you very much -- my complete ignorance of the stack requirements for fastcall was indeed the source of the problem. All I really wanted is to get UEFI out of the way in as short a code sequence as I can manage... and now I have it!

Ignorance is bliss only when what you're ignorant of doesn't bite you in the ... anyway, much appreciated.

Page 2 of 2 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/