Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; Assemble with
- ; nasm -f bin unreal.asm -o unreal.obj
- ;
- ; Link with Watcom Linker to unreal.exe
- ; wlink format dos file unreal.obj
- ;
- ; Or link with MS 16-bit segmented linker
- ; link16 unreal.obj;
- ;
- ; Or link with TLink (Turbo link)
- ; tlink unreal.obj
- ; Macro to build a GDT descriptor entry
- %define MAKE_GDT_DESC(base, limit, access, flags) \
- (((base & 0x00FFFFFF) << 16) | \
- ((base & 0xFF000000) << 32) | \
- (limit & 0x0000FFFF) | \
- ((limit & 0x000F0000) << 32) | \
- ((access & 0xFF) << 40) | \
- ((flags & 0x0F) << 52))
- bits 16
- segment data
- align 4
- gdt:
- FLAT_SEL equ .flat - .start
- .start:
- .null:
- dq MAKE_GDT_DESC(0, 0, 0, 0) ; null descriptor
- .flat:
- dq MAKE_GDT_DESC(0, 0x000fffff, 10010010b, 1100b)
- ; 32-bit data, 4kb gran, limit 0xffffffff bytes, base=0
- .end:
- .gdtr:
- dw .end - .start - 1
- ; limit (Size of GDT - 1)
- dd .start ; base of GDT. Needs to be fixed up at runtime
- in_pmode_str: db "Processor already in protected mode - exiting", 0x0a, 0x0d, "$"
- section code
- ; ..start is a special label for the DOS entry point
- ..start:
- ; Save initial EFLAGS state
- pushfd
- cli
- ; Initialize DS to our DOS DATA segment (needed for EXEs)
- ; SS:SP will be set by the DOS EXE loader to our stack segment
- mov ax, data
- mov ds, ax
- check_pmode:
- smsw ax
- test ax, 0x1 ; Check if we are already in protected mode
- ; This may be the case if we are in a VM8086 task.
- ; EMM386 and other expanded memory manager often
- ; run DOS in a VM8086 task. DOS extenders will have
- ; the same effect
- jz not_prot_mode ; If not in protected mode proceed to switch
- mov dx, in_pmode_str ; otherwise print an error and exit back to DOS
- mov ah, 0x9
- int 0x21 ; Print Error
- jmp exit ; Exit program
- not_prot_mode:
- ; Apply a fixup to the GDTR base to convert to a linear address
- mov eax, ds
- shl eax, 4
- add [gdt.gdtr+2], eax
- lgdt [gdt.gdtr] ; Load our GDT
- mov cx, ds ; Save DS so it can be restored
- mov eax, cr0
- or al, 1
- mov cr0, eax ; Set protected mode flag
- jmp .next1 ; Flush the instruction pefetch queue
- .next1:
- ; In 16-bit protected mode
- ; Since we aren't changing CS
- ; we don't need to enter 32-bit protected mode
- mov bx, FLAT_SEL
- mov ss, bx
- mov ds, bx
- mov es, bx
- mov fs, bx
- mov gs, bx
- and al, ~1
- mov cr0, eax ; Unset protected mode flag
- jmp .next2 ; Flush the instruction pefetch queue
- .next2:
- ; Unreal mode here
- ; Restore SS=DS=ES
- mov ss, cx
- mov ds, cx
- mov es, cx
- ; Print UNR to the screen using a flat 4GiB selector
- ; This code won't work in regular real mode
- xor ax, ax
- mov fs, ax
- mov word fs:[dword 0xb8000+80*2*3+0], 0x57<<8 | 'U'
- mov word fs:[dword 0xb8000+80*2*3+2], 0x57<<8 | 'N'
- mov word fs:[dword 0xb8000+80*2*3+4], 0x57<<8 | 'R'
- exit:
- ; Restore initial EFLAGS state
- popfd
- ; DOS exit
- mov ax, 0x4c00
- int 0x21
- segment stack stack
- resb 1024
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement