30天自制操作系统第4天

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、实验主要内容

1、让C语言读写内存

上次实验隐约知道画面显示与vram有关,但具体的对应关系未知。这次我们用C语言来改写vram看看。作者首先用了汇编语言辅助函数,用了简单的方法,便于我们理解。中增加了一个函数可供C语言调用的函数_write_mem8,用于实现直接写入指定内存地址的语句。如果C语言中write_mem8(0x1234,0x56);语句,则动作上相当于汇编的MOV

BYTE[0x1234],0x56。第一个数字在内存里的存放地址[ESP+4] ,下一个数字的存放就依次累加4。这里两个参数,一个地址,一个数据。

汇编与C语言结合时能自由使用的寄存区只有EAX,ECX,EDX3个,其他寄存区用于记忆非常重要的值,只能读不能写。这段代码中还增加了INSTRSET指令,是用来告诉nask这个程序是给486使用的,不然会被默认解释成8086机器使用(偶尔使用)的标签(label)或者常数。C语言代码:

void io_hlt(void);

void write_mem8(int addr, int data);

void HariMain(void)

{

int i;

for (int i = 0xa0000; i <= 0xaffff; i++)

{

write_mem8(i, 15); /*将数据15写入地址i*/

}

for(;;) {

io_hlt();

}

}

2、绘制条纹

只需要在中修改写入值”15”为”i&0x0f”:

write_mem8(i, i & 0x0f);

对图形来说,0和1并不是作为数字来使用,重点是0和1 的排列方式。对于0和1的互相变化,有位运算”或”(OR)运算、”与”(AND)运算和”异或”(XOR)运算。这些我们在数字逻辑和离散数学里都学过。这样,写入的值就高四位变为0,其余不变。就这样,每隔16个像素,色号就反复一次。

3、直接用C语言写内存

用指针写。指针符号是”*”,*p中的p是地址,而*p是p指向地址的内容。使用*i = i * 0x0f可直接将i*0x0f写入i指向的内存地址中。 *i = i * 0x0f对应汇编的MOV [i], ( i * 0x0f),但如果直接这样写就不清楚[i]到底是BYTE还是WORD还是DWORD。由于MOV

指令的两个对象必须是相同字节长度,即同类型(BYTE/WORD/DWORD),除非另一方是寄存器才可以省略。同理,在使用指针时需要事先声明它的类型,即指针所指向内容的类型。 char i 是类似AL的1字节变量,short i是类似于AX的2字节变量,int i是类似于EAX的4字节变量。

char p ; / 用于BYTE类地址 * /

short p; / 用于 WORD 类地址* /

int p ; / 用于DWORD 类地址 * /

以上指针中的p都是4字节,因为p是用于记录地址的变量。在汇编语言中,地址也像ECX一样,用4字节的寄存器来指定,所以也是4字节。

p = i; /带入地址/

p = i & 0x0f; /这可以替代write_mem8(i, i&0x0f)*/

在执行make run之后出现了“warning: assignment makes pointer from integer without a cast”这句话。

在C语言中,普通数值和表示内存地址的数值被认为是两种不同的东西。如果将普通整数值赋给内存地址变量就会有警告,可以在赋值的时候使用强制类型转换:

p = (char * ) i; /*注意i的类型要和p类型一样*/

指针应用

p = (char *) 0xa0000; /*给地址变量赋值*/

for (int i = 0; i <= 0xffff; ++i)

{

*(p + i) = i & 0x0f;

}

在声明p的时候给它赋值为写入内存的起始地址,之后i作为地址增量,由p+i来指定写入内存的地址。C语言中,*(p+i)还可以改写成p[i]这种形式:

p = (char *) 0xa0000; /*给地址变量赋值*/

for (int i = 0; i <= 0xffff; ++i)

{

p[i] = i & 0x0f;

}

p[i]与*(p + i)意思相同 ,这两者的差距只有前者4个字符,后者6个字符。但是p[i]并不能说是数组,只是一个看起来像是数列的使用了地址变量的省略写法而已。加法运算可以交换顺序,于是(p+i)和(i+p),p[i]和i[p],a[2]和2[a]都是一个意思,这更能说明它们与数组没有关系。

4、调色板

这次我们使用的是320*200的8位颜色模式,只有256种颜色,而计算机表示表示颜色时,都是用#ffffff一类的数,就是RGB表示法,可以表示256*256*256种颜色。那么我们现在8位数怎么表示颜色呢,其实我们这次只用到了16种。给每种颜色编上号码,像这样就可以使用了。

再根据作者讲解修改完中的代码后,作者以汇编的角度解说table_rgb的声明部分。

RESB指令是“reserve byte”的略写预约字节,如果想要从当前位置向后空出3个字节来,并且填0,就可以用

RESB 3

在RESB 3前面加上地址就变成了:

a:

RESB 3

与C语言中的char a[3]一个意思。

但是汇编中RESB的内容能够保证是0,但是C语言不能保证,因此需要在这个声明后加上“={…}”,还可以写上数据的初始值。

如char a[3] = {1, 2, 3};

Char a[3];

相关文档
最新文档