Dex4U: Here's the complete source. I have commented location where's the problem is. The line number seems to be 295.
So the problem is not the the instruction you mentioned but enabling ints back on with sti instruction.
;****************************************************************************
;
;AMDO64 by valy, 2004-2005. Alpha version
;For AMD64 machines (Opteron OK... Athlon 64 ? a priori)
;
;DOS->RM16->PM16->PM64 long mode AND idt64 OK->PM16->RM16->DOS
;1 GB RAM available through paging (easily extensible)
;
;note Win9x does NOT appreciate a "DOS reboot" : u should start only from DOS
;compile with yasm 0.3 : yasm mypgm.asm -fbin -omypgm.com
;launch this demo with a previous "mode con lines=50" to have a real screen,
;can u live with only 25 lines ?
;
;INTERRUPTS DO WORK now, AFTER a short while (cannot figure why)
;
;This source code is FRIENDWARE :
;if u want to use it, mention my name
;if u find some bugs, if SMP is easy to implement, please tell me
;
;****************************************************************************
;****************************************************************************
;
;What's new ? kbd bug solved : actually kbd.handler.dummy must at least
; make an "in al,60h" else pressing ESC several times may bug
;
;nasm/yasm cannot compile lea rcx,[rcx-something] and error msg is ambiguous :
;code this instead : lea rcx,[dword rcx-something] !!!
;if I make an assembler, the default will be the shorter command
;****************************************************************************
org 0x100
use16
jmp Start ;skip definitions
;from Masm32 to YASM
;%define SHL <<
;%define SHR >>
;%define AND &
;%define use64 [BITS 64]
;======================================
;Real mode code starts from here
;======================================
;************
;section .text
;************
Start:
mainRM16:
;--------------------------------
;Test CPUID command availability
;--------------------------------
pushfd ; save EFLAGS
pop eax ; store EFLAGS in EAX
mov ebx, eax ; save in EBX for later testing
xor eax, 00200000h ; toggle bit 21
push eax ; push to stack
popfd ; save changed EAX to EFLAGS
pushfd ; push EFLAGS to TOS
pop eax ; store EFLAGS in EAX
cmp eax, ebx ; see if bit 21 has changed
jz .no_cpuid ; if no change, no CPUID
jmp cpuid_ok
.no_cpuid:
jmp cpuid_command_not_ok
;--------------------------------
; Use CPUID to determine if the
; processor supports long mode.
;--------------------------------
cpuid_ok:
mov eax, 80000000h ; Extended-function 8000000h.
cpuid ; Is largest extended function
cmp eax, 80000000h ; any function > 80000000h?
jbe no_long_mode ; If not, no long mode.
mov eax, 80000001h ; Extended-function 8000001h.
cpuid ; Now EDX = extended-features flags.
bt edx, 29 ; Test if long mode is supported.
jnc no_long_mode ; Exit if not supported.
cli
call RM_disable_NMI ;disable NMI and redirect pics
push word 2
popf
mov ax,fs
mov [fs_save],ax
mov ax,gs
mov [gs_save],ax
xor ax,ax
mov fs,ax
mov gs,ax
mov dword[mm6_variable], esp ;movd mm6,esp
mov esp,0fff0h ;SP16
xor ebx,ebx
mov bx,cs
shl ebx,4 ;ebx is our CS relocation
mov dword[mm7_variable],ebx ;movd mm7,ebx
add [pGDT32+2],ebx
add [pidt64+2],ebx
add [jmp_64+2],ebx
add [jmp64_16+3],ebx
add [bootcode16+2],ebx
add [bootdata16+2],ebx
add [patchidt+4],ebx
add [patchidt2+4],ebx
add [bootvideo16+2],dword 0b8000h
;build idt64
pxor mm0,mm0
mov ecx,63*16
mov edx,int6463
add edx,ebx
.idtentry:
mov eax,edx
shr eax,16
mov word[idt64+0+ecx],dx
mov word[idt64+2+ecx],(bootcode64-gdt)
mov word[idt64+4+ecx],08E00h ;1000111000000000b
mov word[idt64+6+ecx],ax
movq [idt64+8+ecx],mm0
sub edx,64 ;sizeof(int64xx)
sub ecx,16 ;sizeof(idt_entry)
jns .idtentry
;enable A20 gate
;-----------------
call RM_enableA20
mov ax,0b800h
mov es,ax
call RM_init_paging2M
;load gdt
;----------
lgdt [pGDT32]
;Enable protected mode (CR0.PE=1).
;---------------------------------
mov eax,cr0
or al,1
mov cr0,eax
;Execute a far jump to turn protected mode on.
;code16_sel must point to the previously-established 16-bit
;code descriptor located in the GDT (for the code currently
;being executed).
;-----------------------------------------------------------
db 0eah ;Far jump...
dw PMnow
dw bootcode16-gdt ;in current code segment.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;At this point we are in 16-bit protected mode,but long
;mode is still disabled.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PMnow:
;
;Set up the protected-mode stack pointer,SS:ESP.
;Stack_sel must point to the previously-established stack
;descriptor (read/write data segment),located in the GDT.
;----------------------------------------------------------
mov ax,bootdata16-gdt
mov ds,ax
mov ss,ax
mov ax,bootvideo16-gdt
mov es,ax
mov esp,0fff0h ;SP16 ;normally esp==SP16 before that
mov [es:2],dword 'P M ' ;indicate 16 bit protected mode
mov [es:2+4],dword '1 6 '
xor eax,eax
mov cr2,eax
;Enable the 64-bit page-translation-table entries by
;setting CR4.PAE=1 (this is _required_before activating
;long mode).Paging is not enabled until after long mode
;is enabled.
;------------------------------------------------------
mov eax,cr4
bts eax,5 ;PAE
bts eax,8 ;PCE, Perf Counters
bts eax,9 ;OSFXSR, Save/Restore of x87/64/128-bit states, enabling XMM too
mov cr4,eax
;
;Create the long-mode page tables,and initialize the
;64-bit CR3 (page-table base address)to point to the base
;of the PML4 page table.The PML4 page table must be located
;below 4 Gbytes because only 32 bits of CR3 are loaded when
;the processor is not in 64-bit mode.
;----------------------------------------------------------
mov eax,90000h ;+SYSPAGEPML4 ;Pointer to PML4 table (<4GB).
mov cr3,eax ;Initialize CR3 with PML4 base.
;Enable long mode (set EFER.LME=1).
;----------------------------------------------------------
mov ecx,0c0000080h ;EFER MSR number.
rdmsr ;Read EFER.
bts eax,8 ;Set LME=1.
wrmsr ;Write EFER.
;Enable paging to activate long mode (set CR0.PG=1)
;----------------------------------------------------------
mov eax,cr0 ;Read CR0.
bts eax,31 ;Set PE=1.
mov cr0,eax ;Write CR0.
db 0ebh,0 ;jmp0
;At this point,we are in 16-bit compatibility mode
;(LMA=1,CS.L=0,CS.D=0 ).
;Now,jump to the 64-bit code segment.The offset must be
;equal to the linear address of the 64-bit entry point,
;because 64-bit code is in an unsegmented address space.
;The selector points to the 32/64-bit code selector in the
;current GDT.
;----------------------------------------------------------
mov edx,2000000
mov ebx,0b8000h + 160*15 + 10
and esp,0fff0h
jmp_64:
db 066h
db 0eah
dd main64
dw bootcode64-gdt ;do NOT bother ds,es,ss : cs descriptor is enough
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;
;;;Start of 64-bit code
;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 8
use64
main64: ;At this point,we're using 64-bit code
mov rsp,7FFF0h ;SYS_STACK
db 0ebh,0 ;jmp0
mov eax,82008h ;SYS_SP16 ;not to place just after entering 64-bit mode (else bugs)
mov ebx,dword[mm6_variable] ;movd rbx,mm6
mov [rax],rbx
mov eax,82000h ;SYS_CS16
mov ebx,dword[mm7_variable] ;movd rbx,mm7
mov [rax],rbx
mov ebx,dword[mm7_variable] ;movd ebx,mm7
add ebx,pidt64
patchidt:
lidt [pidt64] ;yasm : DB 0fh,1,1ch,25h,dword
db 0ebh,0 ;jmp0
mov byte[82050h],0 ;SYS_SCANCODE
mov eax,07000700h
mov [82040h],eax ;SYS_SCR
mov [82040h+4],eax ;SYS_SCR
mov [82040h+8],eax ;SYS_SCR
mov [82040h+12],eax ;SYS_SCR
;clear text screen
;------------------
call LM_Clear_screen
;=========================================
;PROBLEM: Enabling interrupts will cause
;fasm version to tripple fault.
;=========================================
; sti ;enable int's
;test timer/kbd interrupt : wait an ESC key
;-------------------------------------------
mov byte[82050h],0 ;SYS_SCANCODE
.wait_esc:
call LM_show_action
mov al,byte[82050h] ;SYS_SCANCODE
push rdi
mov edi,0b8000h+20 ;show scancode on screen.
mov [edi],al ;show scancode on screen.
pop rdi
cmp al,81h ;SYS_SCANCODE
jne .wait_esc
;kill timer/kbd interrupt
cli
mov ebx,[82000h] ;SYS_CS16
mov edx,ebx
add edx,timer_handler_dummy
mov eax,edx
shr eax,16
mov word[ebx+idt64+0+(32*16)],dx
mov word[ebx+idt64+6+(32*16)],ax
mov ebx,[82000h] ;SYS_CS16
mov edx,ebx
add edx,kbd_handler_dummy
mov eax,edx
shr eax,16
mov word[ebx+idt64+0+(33*16)],dx
mov word[ebx+idt64+6+(33*16)],ax
mov ebx,[82000h] ;SYS_CS16
add ebx,pidt64
patchidt2:
lidt [pidt64] ;yasm : DB 0fh,1,1ch,25h,dword
db 0ebh,0 ;jmp0
sti
;test dummy isr functions with
;the patched IDT64
;--------------------------------------------
mov edx,1000000000
.wait:
dec edx
jnz .wait
cli
;return to PM16
;------------------
gobacktoPM16:
movd mm6,[82008h] ;SYS_SP16
movd mm7,[82000h] ;SYS_CS16
jmp64_16:
db 0ffh,2ch,25h
dd jmpmem
use16
PM64Z:
mov esp,0fff0h ;SP16
mov ax,bootdata16-gdt ;necessary to successfully go back to RM !!
mov ds,ax
mov es,ax
mov ss,ax
;disable paging
;--------------
mov eax,cr0 ;Read CR0.
btr eax,31 ;Set PE=0.
mov cr0,eax ;Write CR0.
db 0ebh,0 ;jmp0
;disable LME
;--------------
mov ecx,0c0000080h ;EFER MSR number.
rdmsr ;Read EFER.
btr eax,8 ;Set LME=0.
wrmsr ;Write EFER.
db 0ebh,0 ;jmp0
;leave PM
;--------------
mov eax,cr0
and al,0feh
mov cr0,eax
db 0ebh,0 ;jmp0
mov eax,dword[mm7_variable] ;movd eax,mm7
shr eax,4
push ax
push word RM16
retf
RM16:
mov ds,ax
mov ss,ax
mov ax,0b800h
mov es,ax
mov [es:5*160],dword 'E N '
mov [es:5*160+4],dword 'D ! '
mov esp,dword[mm6_variable] ;movd esp,mm6
mov word[pIDT16.limit],03ffh
mov dword[pIDT16.base],0
mov ax,[fs_save]
mov fs,ax
mov ax,[gs_save]
mov gs,ax
lidt [pIDT16]
;RESTORE NMI
;/* setup PIC */
mov bl,8
mov bh,0x70
call RM_pic_setup
;/* restore IRQ masks */
mov al,byte [old_IRQ_mask]
out 0x20+1,al
mov al,byte [old_IRQ_mask+1]
out 0xA0+1,al
sti
jmp theend ;skip long mode not detected complaint.
;============================================
;Handle cases where cpuid command is not
;supported.
;============================================
cpuid_command_not_ok:
push es
mov ax,0b800h
mov es,ax
mov [es:0] ,dword 'N O ' ;hardcoded error message!
mov [es:4] ,dword ' C '
mov [es:8] ,dword 'P U '
mov [es:12] ,dword 'I D '
mov [es:16] ,dword ' S '
mov [es:20] ,dword 'U P '
mov [es:24] ,dword 'P O '
mov [es:28] ,dword 'R T '
mov [es:32] ,dword 'E D '
mov [es:32] ,dword '! '
pop es
jmp theend
;=============================================
;Handle cases where long mode is not detected.
;=============================================
no_long_mode:
push es
mov ax,0b800h
mov es,ax
mov [es:0] ,dword 'N O ' ;hardcoded error message!
mov [es:4] ,dword ' L '
mov [es:8] ,dword 'O N '
mov [es:12] ,dword 'G M '
mov [es:16] ,dword 'O D '
mov [es:20] ,dword 'E '
mov [es:24] ,dword 'F O '
mov [es:28] ,dword 'U N '
mov [es:32] ,dword 'D ! '
pop es
jmp theend
;********************
;The end
;********************
theend:
mov ah,0 ;wait a key
int 0x16
mov ax,3 ;set vga text mode
int 0x10
mov ax,0x4C00
int 21h
; ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use16
;messages
;---------
long_mode_detected_msg db 13,10,'Long mode detected!',0
;*************************************************************************
;RM_disable_NMI: Disables non-maskable ints and redirect pics
;
;input: --
;output: --
;*************************************************************************
RM_disable_NMI:
;DISABLE NMI to enter 64-bit mode later
;save IRQ masks
;--------------------
in al,0x20+1
mov byte [old_IRQ_mask],al
in al,0xA0+1
mov byte [old_IRQ_mask+1],al
;setup PIC to redirect external
;interrupts to range 32-47
;-------------------------------
mov bl,0x21
mov bh,0x29
call RM_pic_setup ;(0x20, 0x28);
;/* set new IRQ masks */
mov al,0xfc ;1st bit is for timer, 2nd for keyboard (master)
out 0x20+1,al
mov al,0xff
out 0xA0+1,al ;/* disable all (slave) */
ret ;end of procedure
;*************************************************************************
; RM_pic_setup: redirects pics
;
;input: bl=master vector,bh=slave vector
;
;output: --
;*************************************************************************
RM_pic_setup:
mov al,0x11
out 0x20,al ;start 8259 initialization
out 0xA0,al
mov al,bl ;master_vector ;master base interrupt vector
out 0x20+1,al
mov al,bh ;slave_vector ;slave base interrupt vector
out 0xA0+1,al
mov al,4 ;1<<2 ;bitmask for cascade on IRQ2
out 0x20+1,al
mov al,2
out 0xA0+1,al ;cascade on IRQ2
mov al,1
out 0x20+1,al ;finish 8259 initialization
out 0xA0+1,al
ret ;end of procedure
;*************************************************************************
; RM_enableA20: Enables A20 gate.
;
;input: --
;
;output: --
;*************************************************************************
RM_enableA20:
call enablea201
jnz enablea20done
mov al,0d1h
out 64h,al
call enablea201
jnz enablea20done
mov al,0dfh
out 60h,al
enablea201:
mov ecx,20000h
enablea201l:
jmp $+2 ;short $+2
in al,64h
test al,2
loopnz enablea201l
enablea20done:
ret ;end of procedure
;*************************************************************************
; RM_init_paging2M: Creates memory page table for long mode.
;
;input: --
;
;output: --
;*************************************************************************
RM_init_paging2M: ;here, 512*2 MB bytes = 1 GB
mov ax,ds
push ax ;!!! NO push cs !!!
mov ax,9000h
mov ds,ax
xor eax,eax
mov ecx,2048
pxor mm0,mm0
xor esi,esi
.init_paging2M0:
movq [ds:esi],mm0
add esi,8
dec ecx
jnz .init_paging2M0
;PML4/PDPE/PDE
mov [ds:0],dword 90000h + 4096+15
mov [ds:4096],dword 90000h + 8192 +15
;PDE
xor esi,esi
mov ecx,15+128 ;128==PDE.PS
mov eax,1 SHL 21 ;2097152
.init_paging2M1:
mov [ds:8192+esi],ecx
add ecx,eax
add esi,8
cmp esi,8*512 ;we paginate 512*2 MB bytes
jne .init_paging2M1
pop ax
mov ds,ax
ret
;*************************************************************************
; RM_DisplayMessage: Displays ASCIIZ string at ds:si via BIOS
;
;input: ds:si ASCIIZ string pointer
;
;output: --
;*************************************************************************
RM_DisplayMessage:
lodsb ; load next character
or al, al ; test for NUL character
jz RM_DisplayMessage.done
mov ah, 0x0E ; BIOS teletype
mov bh, 0x00 ; display page 0
mov bl, 0x07 ; text attribute
int 0x10 ; invoke BIOS
jmp RM_DisplayMessage
.done:
ret ; end of procedure
use64
;*************************************************************************
;LM_show_action: show some action on text srceen
;
;input: --
;output: --
;*************************************************************************
align 4
LM_show_action:
push rax
push rdi
mov edi,0b8000h+30 ;show '!' character
mov byte[edi], '!'
inc edi
inc byte[edi] ;update color
pop rdi
pop rax
ret ;end of procedure
;********************************************************************
;
; IRQ0 = Default handler for timer. Incoming byte is read from
; the port but nothing else is done.
;
;
;********************************************************************
align 16
timer_handler_dummy:
push rax
mov al,0x20 ;send end of interrupt command
out 0x20,al
pop rax
iretq
;********************************************************************
;
; IRQ1 = Default handler for keyboard. Incoming byte is read from
; the port but nothing else is done.
;
;
;********************************************************************
align 16
kbd_handler_dummy:
push rax
in al,60h
mov al,0x20 ;send end of interrupt command
out 0x20,al
pop rax
iretq
use64
;********************************************************************
;
; IRQ0 = Handler for timer. Text screen word is increased by one when
; timer interrupt occures.
;
;
;********************************************************************
align 16
timer_handler:
push rax
inc word[0b8000h+40] ;indicate timer handler activity
mov al,0x20 ;send end of interrupt command
out 0x20,al
pop rax
ret
use64
;********************************************************************
;
; IRQ1 = Handler for keyboard. Incoming byte is read from
; the port and stored into memory location.
;
;
;********************************************************************
align 16
kbd_handler:
push rax
in al,0x60
mov [82050h],al ;SYS_SCANCODE
mov al,0x20 ;send end of interrupt command
out 0x20,al
pop rax
ret
use64
;*************************************************************************
;LM_Clear_screen: Clears text screen
;
;input: --
;output: --
;*************************************************************************
align 4
LM_Clear_screen:
mov edi,0b8000h
movaps xmm0,[82040h] ;SYS_SCR
.loop:
movaps [edi],xmm0
add edi,16
cmp edi,0b8000h+50*160
jl .loop
ret ;end of procedure
;=============
;YASM variant
;=============
use64
; %macro myint 1;{
; int64%1:
;
; ;;;cli
;
; mov ebx,%1
; cmp ebx,32
; jl .reboot
;
;.noreboot:
; cmp ebx,20h
; jne .timer_handlerz ;short .skip
; call timer_handler
;.timer_handlerz:
; cmp ebx,21h
; jne .kbd_handlerz ;short .skip
; call kbd_handler
;.kbd_handlerz:
;
;
;.skip:
; mov al,0x20
; out 0x20,al ;send end of interrupt command
; ;;;sti
; iretq
;
;.reboot:
; cli;;;
; jmp gobacktoPM16
;
; int64z%1:
; times (64-int64z%1+int64%1) db 0
; %endmacro
;=============
;FASM variant
;=============
use64
macro myint Number {
int64#Number:
;;;cli
mov ebx,#Number
cmp ebx,32
jl .reboot
.noreboot:
cmp ebx,20h
jne .timer_handlerz ;short .skip
call timer_handler
.timer_handlerz:
cmp ebx,21h
jne .kbd_handlerz ;short .skip
call kbd_handler
.kbd_handlerz:
.skip:
mov al,0x20
out 0x20,al ;send end of interrupt command
;;;sti
iretq
.reboot:
cli;;;
jmp gobacktoPM16
int64z#Number:
times (64-int64z#Number+int64#Number) db 0
};%endmacro
;-------------------------
;create interrupt handlers
;-------------------------
align 16
myint 0
myint 1
myint 2
myint 3
myint 4
myint 5
myint 6
myint 7
myint 8
myint 9
myint 10
myint 11
myint 12
myint 13
myint 14
myint 15
myint 16
myint 17
myint 18
myint 19
myint 20
myint 21
myint 22
myint 23
myint 24
myint 25
myint 26
myint 27
myint 28
myint 29
myint 30
myint 31
myint 32
myint 33
myint 34
myint 35
myint 36
myint 37
myint 38
myint 39
myint 40
myint 41
myint 42
myint 43
myint 44
myint 45
myint 46
myint 47
myint 48
myint 49
myint 50
myint 51
myint 52
myint 53
myint 54
myint 55
myint 56
myint 57
myint 58
myint 59
myint 60
myint 61
myint 62
myint 63
use64
;************
;section .data
;************
align 16
;==========================
; Global descriptor table
;==========================
mydata:
pGDT32:
dw gdtend-gdt ;gdt32_limit ;GDT limit ...
dd gdt ;gdt32_base ;and 32-bit GDT base
dd 0
pGDT64: ;label tbyte ;Used by LGDT.
dw gdtend-gdt ;GDT limit ...
dq gdt ;and 64-bit GDT base
align 8
gdt: dd 0,0 ;null descriptor
gdtCS16:
bootcode16:
dd 0ffffh
dd 09b00h
bootdata16:
dd 0ffffh
dd 09300h
bootvideo16:
dd 0ffffh
dd 09300h
gdtCS64:
bootcode64:
dd 0ffffh
dd 0af9b00h
gdtend:
;============================
; Interrupt descriptor table
;============================
pidt64:
dw idt64end-1-idt64 ;idt_limit
dd idt64 ;idt_base to be patched : linear address
dd 0
align 16
idt64:
;low offset,code selector,std values,medium offset,high offset,highest offset,0,0
times 64 dw 0,bootcode64-gdt,8E00h,0,0,0,0,0
idt64end:
jmpmem:
dw PM64Z
dw 0
dw bootcode16-gdt
align 16
mystack: dq 0,0,0,0,0,0,0,0
pIDT16:
.limit: dw 03ffh ;idt_limit
.base: dd 0 ;idt_base
fs_save: dw 0
gs_save: dw 0
old_IRQ_mask: db 0,0
irqmask: db 0,0
mm6_variable: dd 0 ;just for debugging purposes (Fasm doesn't accept some movd variants. We need to use variables instead.)
mm7_variable: dd 0 ;just for debugging purposes