flat assembler
Message board for the users of flat assembler.

flat assembler > Main > UEFI questions

Goto page 1, 2, 3  Next
Author
Thread Post new topic Reply to topic
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Hello, I've been trying to figure out how to start coding with UEFI in assembler.
I found a few examples of very basic programs from osdev in fasm, tried them and yay, they worked.

Since I'm new to UEFI in asm I have a couple of questions. The one to start off with:

1. Why do we have to save ebp on entry and restore it before exit?

Code:
include 'efi.inc' main: push ebp; !!!!!!!!!!!!!!!!!!!!!!!! ---- Saving mov ebp, esp ... blah blah blah ... mov ecx, [edx + 4] mov eax, EFI_SYSTEM_TABLE_SIGNATURE2 cmp eax, ecx jne error ... blah blah blah ... success: mov eax, EFI_SUCCESS pop ebp ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --- Restoring retn error: mov eax, 1 pop ebp ; !!!!!!!!!!!!!!!!!!!!!!!!!!! --- And once again retn
Post 17 Aug 2016, 20:38
View user's profile Send private message Reply with quote
Trinitek



Joined: 06 Nov 2011
Posts: 257
UEFI on x86-64 platforms uses Microsoft's x64 calling convention. You would see the same saving and restoring procedure when entering and leaving a 64-bit function in userspace code on Windows as well.
Post 17 Aug 2016, 22:51
View user's profile Send private message Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Thank you Trinitec.
I looked that up, so very interesting thing to read.
Post 18 Aug 2016, 06:56
View user's profile Send private message Reply with quote
Trinitek



Joined: 06 Nov 2011
Posts: 257
Actually, since that's 32-bit code, that would be the cdecl calling convention, but the saving/restoring procedure is the same. Not sure why I didn't catch that.
Post 18 Aug 2016, 12:46
View user's profile Send private message Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3475
Location: Bulgaria
ebp is used for comfortable access to the arguments and local variables, both located on the stack.
Of course, you can access these variables using esp directly, but if you push/pop some values in the stack, esp will change and the offset to the variables will change as well. This will make the code much less readable and the risk of bugs increases. In the same time, once, esp is copied to ebp, you can use ebp with constant offset to every local variable (function argument).

So, this way, If you don't use local variables or procedure arguments and don't change ebp, there is no need to save it.
Post 18 Aug 2016, 13:20
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Umm I've read there about preserving registers, calling conventions, shadow space in the stack... Do I have to adhere to all that within my code as well or does it only refer to external calls and rets (apart from readability issues)?
Post 19 Aug 2016, 06:34
View user's profile Send private message Reply with quote
Trinitek



Joined: 06 Nov 2011
Posts: 257
MrFox wrote:
Umm I've read there about preserving registers, calling conventions, shadow space in the stack... Do I have to adhere to all that within my code as well or does it only refer to external calls and rets (apart from readability issues)?
It's absolutely required that you adhere to the convention when calling external functions. You can do whatever you want with internal functions, however. I think that you should be aware that there are macros available that allow you to define and call functions of a particular convention, so you do not have to write the entry and exit procedures yourself.
Post 19 Aug 2016, 06:55
View user's profile Send private message Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Thanks, Trinitec, that's what I needed to know.
AFAIK, there are not only macros but even special x86 assembly instructions created especially to do such things.
Enter and Leave: http://stackoverflow.com/questions/5858996/enter-and-leave-in-assembly
does FASM support them?

Question #2
I'm wracking my brains around the http://wiki.osdev.org/Uefi.inc and can't figure out why on earth the guy needed all those bells and whistles with redefining data types and structures (see efi.inc titled "The include file" at the middle of the page).

Namely, I can't get why he needed all those:
Code:
... struc int64 { align 8 . dq ? } ... macro struct name { virtual at 0 name name end virtual } ... struc EFI_TABLE_HEADER { .Signature int64 .Revision int32 .HeaderSize int32 .CRC32 int32 .Reserved int32 } struct EFI_TABLE_HEADER struc EFI_SYSTEM_TABLE { .Hdr EFI_TABLE_HEADER .FirmwareVendor dptr .FirmwareRevision int32 .ConsoleInHandle dptr .ConIn dptr .ConsoleOutHandle dptr .ConOut dptr .StandardErrorHandle dptr .StdErr dptr .RuntimeServices dptr .BootServices dptr .NumberOfTableEntries intn .ConfigurationTable dptr } struct EFI_SYSTEM_TABLE ...


why don't we just use:

Code:
struc EFI_TABLE_HEADER {virtual at 0 ;---------------------- .Signature dq ? .Revision dd ? .HeaderSize dd ? .CRC32 dd ? .Reserved dd ? ;---------------------- end virtual}
Post 24 Aug 2016, 18:02
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15864
Location: 162173 Ryugu
When you put "virtual at 0" inside the struc definition then you won't be able to instantiate the structure into any memory address other than 0. So probably not a good idea unless you know that you never need anything else.

For "enter" and "leave", yes fasm supports them. But most people don't use them because of concerns about performance. But you are free to use them if you wish to.
Post 24 Aug 2016, 18:14
View user's profile Send private message Visit poster's website Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Oh, thanks. What do you mean by performance? Any issues using them?

If I understood that code correctly, that guy uses the structures to only provide offsets, like this:
Code:
mov edx, dword [rax+EFI_BLOCK_IO_MEDIA.MediaId]

or this:
Code:
clear: mov eax, EFI_SYSTEM_TABLE.ConOut mov ecx, [SystemTable] add ecx, eax mov ecx, [ecx] mov edx, ecx mov eax, SIMPLE_TEXT_OUTPUT_INTERFACE.ClearScreen add edx, eax push ecx ; [arg] SystemTable.ConOut mov edx, [edx] call edx add esp, 4

I guess my interpretation of his code will work exactly the same way, won't it?
Post 24 Aug 2016, 18:28
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15864
Location: 162173 Ryugu
By performance, this is how other people view them. Other people think that enter/leave are slow so they avoid them. Sometimes this makes sense, sometimes it doesn't matter. It depends upon what you are doing and where you use them.

If you only ever reference the struc in the way you show then it makes no difference. But you still need to initialise the values by instantiating the struc somewhere, you can't escape this requirement. Merely declaring the struc will not define the value of EFI_TABLE_HEADER.Signature. So you lose some flexibility without any gain in simplicity IMO.
Post 24 Aug 2016, 18:38
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6865
Location: Kraków, Poland
revolution wrote:
If you only ever reference the struc in the way you show then it makes no difference. But you still need to initialise the values by instantiating the struc somewhere, you can't escape this requirement. Merely declaring the struc will not define the value of EFI_TABLE_HEADER.Signature. So you lose some flexibility without any gain in simplicity IMO.
It could be a little bit simpler if "struc" was not used at all:
Code:
virtual at 0 EFI_TABLE_HEADER: .Signature dq ? .Revision dd ? .HeaderSize dd ? .CRC32 dd ? .Reserved dd ? end virtual
This is how structure offsets used to be defined before fasm had "struc" implemented.
Post 24 Aug 2016, 19:01
View user's profile Send private message Visit poster's website Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Ok, I got it. Thanks.
The thing is, we do not initialize any of these tables or handles. They all already reside in memory when our UEFI app (they call it 'Image') starts and we only need these structures to address offsets within those tables. The app gains System_Table pointer and Loaded_Image handle pointer through stack when it's loaded and all the other references are being made relative to these pointers, 'browsing' the existing tree of structs and handles. That's why I think (as of now, at least) I'll never have to initialize those structures, only to map them on existing addresses. I may be mistaken though as I'm a lil noobie. Smile

Would you recommend that I stick to his way of declaration when introducing other structures from UEFI spec (there are tons of them) into that file?

---------------

Added: Thanks, Tomasz!!! Simplicity is what I need as these are my 'first steps' at fasm.
Post 24 Aug 2016, 19:07
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15864
Location: 162173 Ryugu
MrFox wrote:
Would you recommend that I stick to his way of declaration when introducing other structures from UEFI spec (there are tons of them) into that file?
It is just personal preference. I would suggest that you do what makes sense to you, not necessarily what gives the most flexibility, or whatever other metric, if it confuses you. But it is nice to be able to understand the various methods and know that you can use them when you might need the extra flexibility in the future.
Post 24 Aug 2016, 19:13
View user's profile Send private message Visit poster's website Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Okay, as of now, I think I'll do what suits me best, i.e. put it as Tomasz suggested, because I hate it when there are pieces in MY code that I don't 100% understand (even if they are technically more correct).

And of course, I'll be 'reading the source' in order to improve my personal understanding of fasm syntax and working principles to get that extra flexibility in the future.

Thanks, guys, you rock!
Post 24 Aug 2016, 19:24
View user's profile Send private message Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Code:
virtual at 0 EFI_TABLE_HEADER: .Signature dq ? .Revision dd ? .HeaderSize dd ? .CRC32 dd ? .Reserved dd ? end virtual

How can I implement nested structures?

I need something like this:
Code:
struc EFI_SYSTEM_TABLE { .Hdr EFI_TABLE_HEADER .FirmwareVendor dptr .FirmwareRevision int32 .ConsoleInHandle dptr .ConIn dptr .ConsoleOutHandle dptr .ConOut dptr .StandardErrorHandle dptr .StdErr dptr .RuntimeServices dptr .BootServices dptr .NumberOfTableEntries intn .ConfigurationTable dptr }
Post 25 Aug 2016, 05:53
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6865
Location: Kraków, Poland
For this you need "struc", because you need to instantiate the same structure in different places. Simplified variant is not your friend in such case.
Post 25 Aug 2016, 07:08
View user's profile Send private message Visit poster's website Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Thanks!

I have a question regarding programming technique.

The task is to browse through the system table and its subtables. They contain values and pointers. This man uses different registers to move along the table and jump to pointers:

Code:
clear: mov eax, EFI_SYSTEM_TABLE.ConOut mov ecx, [SystemTable] add ecx, eax mov ecx, [ecx] mov edx, ecx mov eax, SIMPLE_TEXT_OUTPUT_INTERFACE.ClearScreen add edx, eax push ecx ; [arg] SystemTable.ConOut mov edx, [edx] call edx add esp, 4 ret


Why don't we just use one register for all that? Would it be faster or slower?

Code:
clear: mov eax, [SystemTable] add eax, EFI_SYSTEM_TABLE.ConOut mov eax, [eax] push eax ; [arg] SystemTable.ConOut add eax, SIMPLE_TEXT_OUTPUT_INTERFACE.ClearScreen mov eax, [eax] call eax add esp, 4 ret
Post 25 Aug 2016, 11:16
View user's profile Send private message Reply with quote
MrFox



Joined: 17 Aug 2016
Posts: 52
Location: Russia
Afterthought: maybe that's done this way to prevent local overheating EAX cpu cirquitry?
Post 25 Aug 2016, 11:32
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15864
Location: 162173 Ryugu
Don't worry about "overheating" any particular part of the CPU. Use whatever registers you want.

And besides, modern CPUs use register renaming so such a thing isn't possible even if you tried to do it deliberately.
Post 26 Aug 2016, 07:51
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2, 3  Next

< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 2004-2018, Tomasz Grysztar.

Powered by rwasa.