>>> Âðåçêà ïåðåõîä â 64-ðàçðäÿíûé ðåæèì
 èñõîäíèêàõ FreeBSD ìîæíî íàéòè ôàéë amd64_tramp.S, áûñòðî è ãðÿçíî ïåðåâîäÿùèé ïðîöåññîð â 64-ðåæèì. Îòêîìïèëèðîâàâ, åãî ìîæíî çàïèñàòü â boot-ñåêòîð, çàãðóæàþùèé íàøó ñîáñòâåííóþ îïåðàöèîííóþ ñèñòåìó (âû âåäü ïèøèòå åå, ïðàâäà?) èëè ñëèíêîâàòü com-ôàéë, çàïóñêàåìûé èç ðåàëüíîãî x86-ðåæèìà (äëÿ ýòîãî ïîòðåáóåòñÿ ÷èñòàÿ MS-DOS áåçî âñÿêèõ ýêñòåíäåðîâ).  îáùåì, âàðèàíòîâ ìíîãî…
//$FreeBSD: /repoman/r/ncvs/src/sys/boot/i386/libi386/amd64_tramp.S,v 1.4 2004/05/14
/*
* Quick and dirty trampoline to get into 64 bit (long) mode and running
* with paging enabled so that we enter the kernel at its linked address.
*/
#define MSR_EFER 0xc0000080
#define EFER_LME 0x00000100
#define CR4_PAE 0x00000020
#define CR4_PSE 0x00000010
#define CR0_PG 0x80000000
/* GRRR. Deal with BTX that links us for a non-zero location */
#define VPBASE 0xa000
#define VTOP(x) ((x) + VPBASE)
.data
.p2align 12,0x40
.globl PT4
PT4:
.space 0x1000
.globl PT3
PT3:
.space 0x1000
.globl PT2
PT2:
.space 0x1000
gdtdesc:
.word gdtend - gdt
.long VTOP(gdt) # low
.long 0 # high
gdt:
.long 0 # null descriptor
.long 0
.long 0x00000000 # %cs
.long 0x00209800
.long 0x00000000 # %ds
.long 0x00008000
gdtend:
.text
.code32
.globl amd64_tramp
amd64_tramp:
/* Be sure that interrupts are disabled */
cli
/* Turn on EFER.LME */
movl $MSR_EFER, %ecx
rdmsr
orl $EFER_LME, %eax
wrmsr
/* Turn on PAE */
movl %cr4, %eax
orl $(CR4_PAE | CR4_PSE), %eax
movl %eax, %cr4
/* Set %cr3 for PT4 */
movl $VTOP(PT4), %eax
movl %eax, %cr3
/* Turn on paging (implicitly sets EFER.LMA) */
movl %cr0, %eax
orl $CR0_PG, %eax
movl %eax, %cr0
/* Now we're in compatability mode. set %cs for long mode */
movl $VTOP(gdtdesc), %eax
movl VTOP(entry_hi), %esi
movl VTOP(entry_lo), %edi
lgdt (%eax)
ljmp $0x8, $VTOP(longmode)
.code64
longmode:
/* We're still running V=P, jump to entry point */
movl %esi, %eax
salq $32, %rax
orq %rdi, %rax
pushq %rax
ret