By using 'bits 16', we can write code for 16-bit use the actual
assembly syntax rather than 'DB' and sometimes writing code with
seemingly incorrect operands because we know it will run correctly
when the processor is running in 16-bit mode.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com>
---
 MdePkg/Library/BaseLib/Ia32/Thunk16.nasm |  81 ++++++++-------------
 MdePkg/Library/BaseLib/X64/Thunk16.nasm  | 121 ++++++++++++++-----------------
 2 files changed, 87 insertions(+), 115 deletions(-)

diff --git a/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm 
b/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm
index d32b5c1..998cf2b 100644
--- a/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm
+++ b/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm
@@ -82,23 +82,24 @@ _BackFromUserCode:
     ; in IA32_REGS structure. This facilitates wrapper function to extract them
     ; into that structure.
     ;
+BITS    16
     push    ss
     push    cs
-    DB      66h
-    call    .Base                       ; push eip
+a32 call    .Base                       ; push eip
 .Base:
-    pushfw                              ; pushfd actually
+    pushfd
     cli                                 ; disable interrupts
     push    gs
     push    fs
     push    es
     push    ds
-    pushaw                              ; pushad actually
+    pushad
     DB      66h, 0bah                   ; mov edx, imm32
 .ThunkAttr: dd   0
     test    dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
     jz      .1
-    mov     eax, 15cd2401h              ; mov ax, 2401h & int 15h
+    mov     ax, 2401h
+    int     15h
     cli                                 ; disable interrupts
     jnc     .2
 .1:
@@ -108,24 +109,17 @@ _BackFromUserCode:
     or      al, 2
     out     92h, al                     ; deactivate A20M#
 .2:
-    xor     ax, ax                      ; xor eax, eax
-    mov     eax, ss                     ; mov ax, ss
-    DB      67h
-    lea     bp, [esp + IA32_REGS.size]
-    ;
-    ; esi's in the following 2 instructions are indeed bp in 16-bit code. Fact
-    ; is "esi" in 32-bit addressing mode has the same encoding of "bp" in 16-
-    ; bit addressing mode.
-    ;
-    mov     [esi - IA32_REGS.size + IA32_REGS._ESP], bp
-    mov     ebx, [esi - IA32_REGS.size + IA32_REGS._EIP]
-    shl     ax, 4                       ; shl eax, 4
-    add     bp, ax                      ; add ebp, eax
+    xor     eax, eax
+    mov     ax, ss
+    lea     ebp, [esp + IA32_REGS.size]
+    mov     [bp - IA32_REGS.size + IA32_REGS._ESP], ebp
+    mov     bx, [bp - IA32_REGS.size + IA32_REGS._EIP]
+    shl     eax, 4                      ; shl eax, 4
+    add     ebp, eax                    ; add ebp, eax
     DB      66h, 0b8h                   ; mov eax, imm32
 .SavedCr4:  DD      0
     mov     cr4, eax
-    DB      66h
-    lgdt    [cs:edi + (SavedGdt - .Base)]
+o32 lgdt [cs:bx + (SavedGdt - .Base)]
     DB      66h, 0b8h                   ; mov eax, imm32
 .SavedCr0:  DD      0
     mov     cr0, eax
@@ -134,8 +128,7 @@ _BackFromUserCode:
     mov     ss, eax
     DB      66h, 0bch                   ; mov esp, imm32
 .SavedEsp   DD      0
-    DB      66h
-    retf                                ; return to protected mode
+o32 retf                                ; return to protected mode
 
 _EntryPoint:
         DD      _ToUserCode - m16Start
@@ -153,45 +146,34 @@ _16GdtrBase:
 ; It will be shadowed to somewhere in memory below 1MB.
 ;------------------------------------------------------------------------------
 _ToUserCode:
-    mov     edx, ss
-    mov     ss, ecx                     ; set new segment selectors
-    mov     ds, ecx
-    mov     es, ecx
-    mov     fs, ecx
-    mov     gs, ecx
+BITS    16
+    mov     dx, ss
+    mov     ss, cx                      ; set new segment selectors
+    mov     ds, cx
+    mov     es, cx
+    mov     fs, cx
+    mov     gs, cx
     mov     cr0, eax                    ; real mode starts at next instruction
                                         ;  which (per SDM) *must* be a far JMP.
     DB      0eah
 .RealAddr: DW 0, 0
 
     mov     cr4, ebp
-    mov     ss, esi                     ; set up 16-bit stack segment
-    xchg    sp, bx                      ; set up 16-bit stack pointer
-
-;   mov     bp, [esp + sizeof(IA32_REGS)
-    DB      67h
-    mov     ebp, [esp + IA32_REGS.size] ; BackFromUserCode address from stack
-
-;   mov     cs:[bp + (_BackFromUserCode.SavedSs - _BackFromUserCode)], dx
-    mov     [cs:esi + (_BackFromUserCode.SavedSs - _BackFromUserCode)], edx
+    mov     ss, si                      ; set up 16-bit stack segment
+    xchg    esp, ebx                    ; set up 16-bit stack pointer
+    mov     bp, [esp + IA32_REGS.size]
+    mov     [cs:bp + (_BackFromUserCode.SavedSs - _BackFromUserCode)], dx
+    mov     [cs:bp + (_BackFromUserCode.SavedEsp - _BackFromUserCode)], ebx
+    lidt    [cs:bp + (_16Idtr - _BackFromUserCode)]
 
-;   mov     cs:[bp + (_BackFromUserCode.SavedEsp - _BackFromUserCode)], ebx
-    DB      2eh, 66h, 89h, 9eh
-    DW      _BackFromUserCode.SavedEsp - _BackFromUserCode
-
-;   lidt    cs:[bp + (_16Idtr - _BackFromUserCode)]
-    DB      2eh, 66h, 0fh, 01h, 9eh
-    DW      _16Idtr - _BackFromUserCode
-
-    popaw                               ; popad actually
+    popad
     pop     ds
     pop     es
     pop     fs
     pop     gs
-    popfw                                ; popfd
+    popfd
 
-    DB      66h                         ; Use 32-bit addressing for "retf" 
below
-    retf                                ; transfer control to user code
+o32 retf                                ; transfer control to user code
 
 ALIGN   0x10
 _NullSegDesc    DQ      0
@@ -221,6 +203,7 @@ GdtEnd:
 ;------------------------------------------------------------------------------
 global ASM_PFX(InternalAsmThunk16)
 ASM_PFX(InternalAsmThunk16):
+BITS    32
     push    ebp
     push    ebx
     push    esi
diff --git a/MdePkg/Library/BaseLib/X64/Thunk16.nasm 
b/MdePkg/Library/BaseLib/X64/Thunk16.nasm
index f817670..4073cdb 100644
--- a/MdePkg/Library/BaseLib/X64/Thunk16.nasm
+++ b/MdePkg/Library/BaseLib/X64/Thunk16.nasm
@@ -80,28 +80,25 @@ _BackFromUserCode:
     ; in IA32_REGS structure. This facilitates wrapper function to extract them
     ; into that structure.
     ;
-    ; Some instructions for manipulation of segment registers have to be 
written
-    ; in opcode since 64-bit MASM prevents accesses to those registers.
-    ;
-    DB      16h                         ; push ss
-    DB      0eh                         ; push cs
-    DB      66h
-    call    .Base                       ; push eip
+BITS    16
+    push    ss
+    push    cs
+o32 call    dword .Base                 ; push eip
 .Base:
-    DB      66h
-    push    0                           ; reserved high order 32 bits of EFlags
-    pushfw                              ; pushfd actually
+    push    dword 0                     ; reserved high order 32 bits of EFlags
+    pushfd
     cli                                 ; disable interrupts
     push    gs
     push    fs
-    DB      6                           ; push es
-    DB      1eh                         ; push ds
-    DB      66h, 60h                    ; pushad
+    push    es
+    push    ds
+    pushad
     DB      66h, 0bah                   ; mov edx, imm32
-.ThunkAttr:     dd   0
+.ThunkAttr: dd   0
     test    dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
     jz      .1
-    mov     eax, 15cd2401h              ; mov ax, 2401h & int 15h
+    mov     ax, 2401h
+    int     15h
     cli                                 ; disable interrupts
     jnc     .2
 .1:
@@ -111,43 +108,34 @@ _BackFromUserCode:
     or      al, 2
     out     92h, al                     ; deactivate A20M#
 .2:
-    xor     ax, ax                      ; xor eax, eax
-    mov     eax, ss                     ; mov ax, ss
-    lea     bp, [esp + IA32_REGS.size]
-    ;
-    ; rsi in the following 2 instructions is indeed bp in 16-bit code
-    ;
-    mov     [rsi - IA32_REGS.size + IA32_REGS._ESP], bp
-    DB      66h
-    mov     ebx, [rsi - IA32_REGS.size + IA32_REGS._EIP]
-    shl     ax, 4                       ; shl eax, 4
-    add     bp, ax                      ; add ebp, eax
-    mov     ax, cs
-    shl     ax, 4
-    lea     ax, [eax + ebx + (.64BitCode - .Base)]
-    DB      66h, 2eh, 89h, 87h          ; mov cs:[bx + (.64Eip - .Base)], eax
-    DW      .64Eip - .Base
+    xor     eax, eax
+    mov     ax, ss
+    lea     ebp, [esp + IA32_REGS.size]
+    mov     [bp - IA32_REGS.size + IA32_REGS._ESP], ebp
+    mov     ebx, [bp - IA32_REGS.size + IA32_REGS._EIP]
+    shl     eax, 4                      ; shl eax, 4
+    add     ebp, eax                    ; add ebp, eax
+    mov     eax, cs
+    shl     eax, 4
+    lea     eax, [eax + ebx + (.64BitCode - .Base)]
+    mov     [cs:bx + (.64Eip - .Base)], eax
     DB      66h, 0b8h                   ; mov eax, imm32
 .SavedCr4:  DD      0
-    mov     cr4, rax
-    ;
-    ; rdi in the instruction below is indeed bx in 16-bit code
-    ;
-    DB      66h, 2eh                    ; 2eh is "cs:" segment override
-    lgdt    [rdi + (SavedGdt - .Base)]
-    DB      66h
+    mov     cr4, eax
+o32 lgdt [cs:bx + (SavedGdt - .Base)]
     mov     ecx, 0c0000080h
     rdmsr
     or      ah, 1
     wrmsr
     DB      66h, 0b8h                   ; mov eax, imm32
 .SavedCr0:  DD      0
-    mov     cr0, rax
+    mov     cr0, eax
     DB      66h, 0eah                   ; jmp far cs:.64Bit
 .64Eip:     DD      0
 .SavedCs:   DW      0
 .64BitCode:
-    db      090h 
+BITS    64
+    nop
     db      048h, 0bch                 ; mov rsp, imm64
 .SavedSp:   DQ   0                     ; restore stack
     nop
@@ -169,40 +157,40 @@ _16Idtr:
 ; It will be shadowed to somewhere in memory below 1MB.
 ;------------------------------------------------------------------------------
 _ToUserCode:
-    mov     ss, edx                     ; set new segment selectors
-    mov     ds, edx
-    mov     es, edx
-    mov     fs, edx
-    mov     gs, edx
-    DB      66h
+BITS    16
+    mov     ss, dx                      ; set new segment selectors
+    mov     ds, dx
+    mov     es, dx
+    mov     fs, dx
+    mov     gs, dx
     mov     ecx, 0c0000080h
-    mov     cr0, rax                    ; real mode starts at next instruction
+    mov     cr0, eax                    ; real mode starts at next instruction
     rdmsr
     and     ah, ~1
     wrmsr
-    mov     cr4, rbp
-    mov     ss, esi                     ; set up 16-bit stack segment
-    mov     sp, bx                      ; set up 16-bit stack pointer
-    DB      66h                         ; make the following call 32-bit
-    call    .Base                       ; push eip
+    mov     cr4, ebp
+    mov     ss, si                      ; set up 16-bit stack segment
+    mov     esp, ebx                    ; set up 16-bit stack pointer
+    call    dword .Base                 ; push eip
 .Base:
-    pop     bp                          ; ebp <- address of .Base
-    push    qword [esp + IA32_REGS.size + 2]
-    lea     eax, [rsi + (.RealMode - .Base)]    ; rsi is "bp" in 16-bit code
-    push    rax
+    pop     ebp                         ; ebp <- address of .Base
+    push    word [dword esp + IA32_REGS.size + 2]
+    lea     ax, [bp + (.RealMode - .Base)]
+    push    ax
     retf                                ; execution begins at next instruction
 .RealMode:
-    DB      66h, 2eh                    ; CS and operand size override
-    lidt    [rsi + (_16Idtr - .Base)]
-    DB      66h, 61h                    ; popad
-    DB      1fh                         ; pop ds
-    DB      07h                         ; pop es
+
+o32 lidt    [cs:bp + (_16Idtr - .Base)]
+
+    popad
+    pop     ds
+    pop     es
     pop     fs
     pop     gs
-    popfw                               ; popfd
-    lea     sp, [esp + 4]               ; skip high order 32 bits of EFlags
-    DB      66h                         ; make the following retf 32-bit
-    retf                                ; transfer control to user code
+    popfd
+    lea     esp, [esp + 4]        ; skip high order 32 bits of EFlags
+
+o32 retf                                ; transfer control to user code
 
 ALIGN   0x8
 
@@ -245,6 +233,7 @@ GDT_SIZE equ $ - _NullSeg
 ;------------------------------------------------------------------------------
 global ASM_PFX(InternalAsmThunk16)
 ASM_PFX(InternalAsmThunk16):
+BITS    64
     push    rbp
     push    rbx
     push    rsi
@@ -300,7 +289,7 @@ ASM_PFX(InternalAsmThunk16):
     mov     [rcx], ebp                  ; save CR4 in 
_BackFromUserCode.SavedCr4
     and     ebp, ~30h                ; clear PAE, PSE bits
     mov     esi, r8d                    ; esi <- 16-bit stack segment
-    DB      6ah, DATA32                 ; push DATA32
+    push    DATA32
     pop     rdx                         ; rdx <- 32-bit data segment selector
     lgdt    [rcx + (_16Gdtr - _BackFromUserCode.SavedCr4)]
     mov     ss, edx
-- 
2.1.0


------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to