Archive for April, 2008

简单的引导程序

看了赵博的《Linux内核源代码完全注释》,读了潇前辈的《操作系统引导探究》《8259A保护模式下中断编程》,受益菲浅。想起N久前看到某期开发高手上的写自己的OS的文章,不由冲动起来,我要写一个~~~~~~引导程序:)。很简单的一个引导程序,仅仅打印几个字符而已,耗费了我几个小时,学到了很多东西。 首先建立实验环境。WinXP+VMWare(linux),用VMWare自带的模拟软驱的功能做了一个软驱镜像,ok了 然后用C写个工具,把引导程序写到软盘0扇区中。并标志最后两个字节为“55 AA” 在这篇日志里我并不打算详细说明系统启动和内存分布情况,强烈推荐《操作系统引导探究》,顺便勘误,图十中的引导区应为0x07c00到0x07dff,而原图误为到0x07cff 。同时补充一点,在IBM PC机中,中断向量表中每个表项占4字节,前两字节是中断处理程序段地址,另两字节存储偏移地址。另,参考了唐朔飞老师《计算机组成原理》一书,在硬向量方式中,IBM PC机中的中断表和潇前辈提到的JMP式中断表是很普遍的两种方式。只不过PC机采用前者(清华大学《IBM-PC汇编语言程序设计》) Ok了,进入正题。先把C代码贴出来。写入引导扇区的工具 /* the program is used to write a boot program to the boot section of the floopy */ #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<stdio.h> main(int argc,char* argv[]) { int bootp,flp; /* the bootp point to the boot program,flp point to the flooy */ char buf[512]; /* data [...]

Tags: ,
Posted in TTTech | No Comments »

as86 man手册

as86的资料实在是少之又少。翻译了man文档….不过翻译的很烂,就当练英文水平吧:) Linus为什么要用它来写boot程序呢,nnd..翻译真是一项辛苦的工作啊…特别是对翻译的东西还不了解的时候…. as86(1) 名称 as86 – as86-8086..80386处理器的汇编程序 概要格式 as86 [-0123agjuw] [-lm[list]] [-n name] [-o obj] [-b[bin]] [-s sym] [-t textseg] src as86_encap prog.s prog.v [prefix_] [as86 options] 描述 as86是8086..80386处理器下的汇编程序,它所采用的语法与Intel/MS采取的语法类似,而不同于广泛运用于UNIX下的汇编语法(译注,gas中的语法,AT&T汇编) 命令行中的src参数可为’-’,代表对标准输入进行汇编。 as86_encap是一个脚本,使用了as86汇编程序,并且把生成的二进制文件转为一个C文件prog.v,用于被连接或者包含到程序里,例如引导块安装程序。prefix_参数定义一个加到源文件中所有定义的变量的前缀,缺省前缀是源文件名。… 选项 -0 以16位代码段运行,当使用了高于8086指令集的指令时警告。 -1 以16位代码段运行,当使用了高于80186指令集的指令时警告。 -2 以16位代码段运行,当使用了高于80286指令集的指令时警告。 -3 以32位代码段运行,不对任何指令发出警告信息(就算使用了486或586的指令) -a 使汇编程序部分兼容于Minix asld.交换了[]与()的用法,并且改变了一些16位跳转与调用的语法(“jmp @(bx)” 就成了一个合法的指令) -g 仅仅把global符号写入目标或者符号文件中 -j 把所有短跳转指令(译注:8位跳转称为短跳转)换成相似的16位或者32位跳转。并且把16位条件转移指令换为一个条件短转移命令与一个无条件长跳转组合 -O 汇编程序会做几遍额外的工作,以尝试支持向前引用。最多30遍。不推荐使用 -l 产生清单文件(list file),文件名写在选项后 -m [...]

Tags: , ,
Posted in TTTech | No Comments »

Linux下的用户级多线程库 Fthread

Linux下的用户级多线程库 Fthread

1.Fthread简介 Linux下的用户级线程。不调用内核的任何线程功能。仅包含一句汇编,程序长度百行左右。非常简化的线程库。 2.线程简单说明 线程的特征 (1)并发执行。需要独立的程序计数器 (2)独立性。独立性弱于进程,可以互相影响。但是也有一定的独立性。因此必须为每个进程维护专属于线程的资源。 (3)协作性。线程不完全独立,都能使用进程的全局量、打开文件表等等资源。 (4)由协作性所引发的,同步问题。 教材所提及的线程包括的项:程序计数器、堆栈、寄存器集、子线程、状态。 Fthread对这些项做了简化,去掉了子线程和状态两项。 在线程间来回切换实际上就是对每个线程专属资源的切换,简单描述:开始线程1正在执行,在某一时刻线程切换信号产生,调度程序被唤醒,保存当前线程的专属资源,选择下一个执行的线程,并恢复其程序计数器、堆栈指针、相关寄存器值。线程即投入运行。 3.线程的专属资源 程序计数器:在32位机中即为EIP寄存器,包含下一条指令的地址。 堆栈与寄存器:与函数调用、局部变量等有关。 一个典型的Linux下进程内存分布见下图:(摘自《深入理解计算机系统》) 说明: (1)不同于DOS等16位操作系统,Linux使用32位的虚拟地址空间。在操作系统课也学过,每个进程都独立地拥有4GB的虚拟内存空间。互相不影响。在这些系统中,指针变量是32位的,记录32位的地址值。不需要像在16位系统中一样通过段偏移寻址和DOS特有的near far限定符来访问内存。 (2)Linux下的进程,其内存模型是分段的,各个段有自己的属性,比如只读可写等等。大体分为代码文本段、数据段和堆栈段,以及一些系统保留区域和禁止访问的区域,比如0地址。所有的程序代码指令都存于代码段中,数据段存储全局变量与静态变量。又可细分出BSS未初始化的数据与已初始化的数据、常量区等等。Malloc所分配的空间位于数据段中,称为heap堆,是由低地址空间往高地址空间增长的。 非法访问了或者企图改写禁止的区域,将会产生一个段错误信号,SIGSEGV。这是指针编程中常出的错误。在Windows下通常表现为一个非法操作。举个简单的例子 main() { int *p=0; *p=32; } 试图访问0地址(NULL指针)引发段错误。 运用gdb调试器有助于发现这种错误。在Windows下也有gcc系列工具,Devcpp开发环境就用的是gcc编译器。在windows下同样能运用gdb发现和改正错误。 (3)函数调用和访问局部变量都需要用到堆栈(Stack)。局部变量空间分配在栈里,函数调用记录也存储在栈里。一些函数调用参数等也存在栈里。 堆栈是一种LIFO后进先出的数据结构。栈由地址高空间往地址低空间向下增长。每当有数据进栈的时候,栈顶指针往下移,数据进栈。出栈时,栈顶指针往上移,数据出栈。 (4)与堆栈相关的寄存器: ESP寄存器:栈顶指针。 EBP寄存器:基址寄存器。主要用于访问局部变量和分隔函数调用记录 以 void holdtest() { int a = 3; } 为例。调用该函数过后,堆栈的分布如下: 高地址 ———————— 返回地址 ———————— 原来的EBP值 <===========EBP的值 ———————— a ————————<===========ESP的值 低地址 a=3这句赋值语句,在内部实际上是这样一句汇编指令来实现的 MOV [...]

Tags: , ,
Posted in TTTech | 1 Comment »