之前说过Bootmgr要负责切换CPU到保护模式甚至长模式,所以我们肯定要碰到GDT的设置,而GDT表项的结构异常复杂,于是我就直接写了一个小工具算GDT,之前使用的是nasm的宏,但是其实GDT没必要每次编译都算,我记得Linux也是写死的,所以我就打算直接算出来然后硬编码。今天这个Part就是这个小工具的源代码,用node.js写的。
I said before that bootmgr will be responsible for switching the CPU into protected mode or even long mode, so we should set GDT first. Since the GDT is very complex, so I just write a tool to calculate GDT directly. I used to use the macro in nasm to calculate GDT, but I think it's not necessary to calculate GDT when compiling, and even Linux hard coded the GDT, so I decide to do the same way. This part is the source code of the small tool, written in node.js.
#!/usr/local/bin/node
(function(){
var fs=require("fs");
var fd=fs.openSync("/dev/stdin","rs");
global.readLine=function(){
var buffer=new Buffer(1);
var string="";
while(true){
fs.readSync(fd, buffer, 0, 1);
if(buffer[0]==10){
break;
}
string+=String.fromCharCode(buffer[0]);
}
return string;
}
global.print=function(x){process.stdout.write(x);}
global.prompt=function(x, def){
print(x+ " ["+def+"]: ");
var input=readLine();
if(!input)input=def;
return input;
}
})();
function GDT(base, limit, ext){
ext|=0x80; // Present
ext|=0x10; // Code/Data
ext|=0x2; // Read/Write
function trunc(x){
x="00000000"+x;
return x.substring(x.length-8);
}
if(limit>1<<20){
limit>>=12;
ext|=0x8000;
}
ext|=(limit&0xF0000)>>8;
var w1=(base&0xFF000000)|(ext<<8)|((base>>16)&0xFF);
var w2=((base&0xFFFF)<<16)|(limit&0xFFFF);
return trunc(w1.toString(16))+trunc(w2.toString(16));
}
var base, limit, ext;
console.log("GDT Calculator: ");
base=parseInt(prompt("Base", "0"));
limit=parseInt(prompt("Limit", "0xFFFFFFFF"));
ext|=(prompt("Code", "y")=="y"?8:0);
{var bits=prompt("Bits", 32);ext|=bits==32?0x4000:(bits==16?0:0x2000)}
ext|=parseInt(prompt("Ring", "0"))<<5;
console.log(GDT(base, limit, ext));