30天自制操作系统第二天学习笔记

暑假学习小日本的那本书:30天自制操作系统

qq交流群:159336168

A:开发环境:我是完全在ubuntu下面进行的学习,实验。

开源的好处不用多说了。各种软件直接sudo apt-get install就行了,不用到处找。


学习笔记:

org address ; nasm汇编器没有lds文件,所以通过这个方式指定链接地址,

jmp entry


entry;
    mov ax,0
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov sp,0x7c00 ;这一部分代码只是初始代segment寄存器,没有说不定也可以
    mov si,msg    ;送的是指针
putcharloop:
     mov al,[si]
    add si,1
    cmp al,0
    je finish  ;decide when to finish displaying
    
    ;this is interrupt to display one character

    mov ah,0x0e  ;one character
     mov bx,15    ;the color of character
    int 0x10;    
    jmp putcharloop
finish:
    hlt
    jmp finish

msg:
    db "\n\nhello,world\n\0"

times 510-($-$$) db 0

dw 0xaa55



这里要学习的重要知识:
bios的0x10中断:
传递的参数al=character ah=function, bx=display color
     int 0x10 ; 就这样就可以显示一个字符了,如果要显示多个字符,只要多调用几次 int 0x10

还有if 和loop的实现

cmp al,0
je  finish  ; 这两条代码实现了c中的 if(al==0) goto finish;

loop 的最简单:
loop:
     xxx     ;这一部分的指令需要有跳出loop的判断语句
     jmp loop     



所以这个代码的两个重点:1:int 0x10 2: loop 中if判断的实现

下面是伪c代码:

org 0x7c00
goto entry


entry:
   ax=0;
   ds=ax;
   es=ax;
   ss=ax;
   sp=0x7c00;

   si=msg

putcharloop:
   al=*si;
   si++;
   if(al==0)
    goto finish;

   ah=0x0e ;
   bx=15
   interrupt(al,ah,bx);
   goto putcharloop;

finish:
    while(1);
    goto finish;
char *msg="\n\nhello,world\n"

times 510-($-$$) db 0;
short boot_flag=0xaa55;


通过c伪代码 理解整个结构,不要局限于汇编的细节,汇编只有两点新内容
loop:
xxx
cmp al,0
je finish
xxx
jmp loop


还有两条语句拿出来做对比:                              char *msg="\n\nhello,world\n\0"
mov si,msg   ;这个是得到指针,就是地址        si=msg;
mov al,[si]  ;    这个是得到指针指向的内容        al=*si;



x86的几个寄存器:
ax:accumulator
bx:base
cx:counter
dx:data
上面几个是通用的,

bp:base pointer 都是指针,所以通常放的是地址
sp:stack pointer

si: source index    数据来源的 地址
di: destination index 数据目的的 地址

全是16位的,上面四个通用的可以折成两个8位,如ax=ah,al 其它三个一样。

16位是说放二进制的数16bits。

读内存mov al,[si]
寄存器之间,mov ds,ax

寄存器只有名字,没有地址,内存有地址。

寄存器的全名是说:通常情况下,这个寄存器是用来干这个活的,盘子是装菜的,但是装其它的东西也行。

add cx,0x1234  ;机器码 4个字节
add ax,0x1234  ;机器码 3个字节

上面的例子说明了一个道理:cpu内部对每个寄存器做了不同的优化,每个寄存器都有自己擅长的操作。ax寄存器就是擅长做add操作,cx这方面就是不好ax
桶就是用来装水的,用桶来装菜,在桌上放着了不方便吃。让每个寄存器发挥自己的优点。从寄存的名字,考虑怎么用这些寄存器。
ax,bx,cx,dx: accumulator,base,counter,data

每个寄存器都有自己的优点:如同金刚葫芦娃一样,每个娃都有自己的牛逼这处。
上面有8个寄存器,每个都是16位的,所以寄存器的存储空间为16个字节。

bp,sp,di,si,这四个寄存器通常都是放的地址,也就是说当指针用,内存的地址通常都是很多位的,8位的内存地址有什么用呢??只有在51单片机中可能有有

如果要用到bp,sp,di,si的高低8位,怎么办,间接的达到目的,曲线救国
mov ax,bp
这时就可以访问al,ah了。

我家的电脑是32位的,这个32位就是通常指的是寄存器的最大位数,
eax,ebx,ecx,edx,esp,ebp,edi,esi
上面是32位的寄存器,低16位与原来的保持兼容,高16位的部分没有名字,所以要访问高16位的数据时,要用移位指令把高16位的数据移到低16位才能使用。
如eax:低16为ax,但是高16位的部分,没有名字,通过移位访问。

几个segment寄存器:
cs,ds,es,ss,fs,gs
code,data,extra,stack,

关于地址的访问:
jmp address   ;address为内存的一个地址,pc为指向这个地址
mov si ,msg   ; 此时msg 为内存的一个地址

msg,address 都称为标号,英文为label,汇编器负责把这些label翻译成具体的地址。org指令会对编译有label的指令产生影响。因为label地址的产生是以org为基准的,所以
org后面的地址变了,编译器计算出label的地址也会变。

[]方括号,是指针操作,是访问内存中数据的操作
mov al, [si] ; 等效于al =*si;

内存是大规模的放数据的一张表,这个表由表格组成,每个表格都有一个地址。
英文称为memory.

不管是32位的机器,还是16位的机器,寄存器的存储容量都太小了。所以memory用来存放code and data.  32个字节连bootsector的代码都放不了,所以code是必须要放到cpu外部,就是memory中,memory的容量是很大的,所以需要地址方便管理。人少可以叫名字,人多了就只能给学生编上学号,方便管理。

因为内存很大,为了方便管理,每个空间搞个线性的地址。
因为寄存器很少,干脆给每个寄存器起个名字,

cpu与内存进行通信,也就是交换数据,中间还有一个东东,称为memory controller
这个东西用来协调cpu与memory的数据交换过程。


mov al,[si] ;读内存
mov byte  [reg] ,123 or reg     ;写内存
mov word  [reg] ,123 or reg     ;写内存
mov dword [reg] ,123 or reg     ;写内存


mov byte  [address] ,123 or reg ;写内存
mov word  [address] ,123 or reg ;写内存
mov dword [address] ,123 or reg ;写内存

有方括号就是与读写内存有关的操作,具体数据的长度看byte word dword


mov bx,dx
mov al,byte[bx]  ;读内存
mov al,[bx]     ;al 只有8bit 所以读一个字节

add si,1 ; si++;
if a==3

;this is important
cmp al,3
je         ;jump if equal


label means address


int 0x10只是一个中断服务程序,bios提供的一个函数,输入参数为al=character you want to display,ah=how many character ,bx=color

int:interrupt
int is provided by bios

hlt:means halt
halt指令只是sleep的状态,一旦有外部中断发生,还是会执行中断

bios会所启动设备的头512字节的代码复制到内存中地址为0x7c00-0x7dff处

bios把代码复制到0x7c00处,可能没有什么特别的原因,只是这样做可以罢了。可能有个时代背景的原因。但这个对现在的人已经不重要,只是一个rule.
ipl:inital program loader

makefile文件的学习比较简单,注意语法,格式就行了,依赖关系搞清楚。

msg:后面的字符串如果当code解释,
0x0a 0x0a,解释成代码是 or cl,[bp+si]
0x68 0x65 0x6c,解释成代码是push 0x6c65

作者,把msg:后面的"\n\nhello,world\n"
本来是显示的信息,如果当代码解释 就是上面的两条代码。


cpu一直是把pc指向的内容当指令。不管他是指令还是信息,都会当指令去执行。
人才是程序的编写着,安排着,要知道什么是code,什么是data.

cpu是不关心这些电信号是干什么的,只有人类正确的安装,上下文件,才会产生伟大的程序。安排好cpu要做的一切,内存中哪部分是code,哪部分是data.

可能性的存在:数码相机拍一个照片,当程序给cpu执行,可能就是一个很好的程序
                           写一个程序,保存成jpg的格式,可能就是一幅好的 艺术品。

有点问题:hlt指好像没有起作用,不知为什么。

在hello.asm中,用下面的代码测试了hlt指令,但是好像没有用,会一直打印1
finish:
    hlt
    mov al,0x31 ; ascii for 1
    int 0x10
    hlt
    jmp finish

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值