VirtualBox

Opened 11 years ago

Last modified 11 years ago

#11510 closed defect

Fault in ASM loop instruction — at Version 1

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 Frank Mehnert)

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 (1)

comment:1 by Frank Mehnert, 11 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.

© 2023 Oracle
ContactPrivacy policyTerms of Use