Opened 12 years ago
Closed 12 years ago
#11510 closed defect (fixed)
Fault in ASM loop instruction
Reported by: | SiGiS | Owned by: | |
---|---|---|---|
Component: | EFI | Version: | VirtualBox 4.0.18 |
Keywords: | UEFI, loop, OutputString, Stack Corruption | Cc: | |
Guest type: | other | Host type: | Linux |
Description (last modified by )
There seems to be an anomily with the loop instruction, when running under UEFI boot services mode. Either the stack is being corrupted or the loop instruction it self becomes irratic/unstable. The same code, run outside of a virtual-machine on a physical machine, gives the expected result and not the faulty result as received from the VM.
The UEFI OutputString command, that acts as the replacement for the BIOS video int, makes use of the rcx and rdx registers for parameters. This requires the rcx register to be pushed onto the stack, when used within a loop instruction, in order to maintain the loop count on return from the OutputString function. On return and pop of the rcx register, however, the loop fails, in that the value in the rcx register either breaks the loop instruction or causes a (seamingly) infinite loop due to the value of the rcx register. Put simply, the rcx register is not restored to the proper value from the stack.
The following is an example of what the actual code does :
Expected result / Received when run through a physical machine: 332211
Faulty result / Received when run through a virtual machine: 3
Output:
mov rcx, [.Count]; Number of itterations .PrintLoop: ; Step 1 - Show the current count mov [.CountTest], 0x30 ; Numeric char's in ASCII starts at 30hex add [.CountTest], rcx ; Add the current counter value lea rdx, [.CountTest] ; OutputString value parameter push rcx ; Save loop count as UEFI uses rcx as ; parameter for the pointer to the instance pushf ; Loop does not rely on flags, but tested ; in any case mov rcx, [SystemTable] ; UEFI System table pointer mov rcx, [rcx + ConsoleOut] ; OutputString first parameter call [rcx + OutputString] ; UEFI OutputString function xor rcx, rcx ; Be dead sure rcx is 0 popf ; Restore flags and loop count pop rcx ; Step 2 - Show the rcx value after the print call mov [.CountTest], 0x30 ; Numeric char's in ASCII starts at 30hex add [.CountTest], rcx ; Add the current counter value lea rdx, [.CountTest] ; OutputString value parameter push rcx ; Save loop count as UEFI uses rcx as ; parameter for the pointer to the instance pushf ; Loop does not rely on flags, but tested ; in any case mov rcx, [SystemTable] ; UEFI System table pointer mov rcx, [rcx + ConsoleOut] ; OutputString first parameter call [rcx + OutputString] ; UEFI OutputString function xor rcx, rcx ; Be dead sure rcx is 0 popf ; Restore flags and loop count pop rcx loop .PrintLoop retn .Count dq 0x03 ; Itteration count .CountTest dq ? ; Current count test
Change History (4)
comment:1 by , 12 years ago
Description: | modified (diff) |
---|
comment:2 by , 12 years ago
comment:3 by , 12 years ago
Great, thanks frank.
This actually makes a lot of sense. Boot services shouldn't really need to rely on 64bit mode to begin with, so it's not as critical but would be usefull to test it in 64bit as the UEFI specification has a specific cpu execution mode (For instance, the cpu runs in long mode) which could cause anomilies, as long mode has some implications in terms of the supported opperations and opperands.
Thanks again for looking into this :)
comment:4 by , 12 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
There were many changes in the EFI code with VBox 4.3. Please reopen if still relevant with VBox 4.3.2.
This has nothing to do with the loop instruction. I think the VBox EFI code expects to be accessed in 32-bit mode (not 64-bit). That might be a bug.