• <自己动手写操作系统>2011033001


    【分析】

    部分代码

        mov    dh, 0                ; "Booting  "

        call    DispStr            ; 显示字符串

    跳转到这个函数
    ;----------------------------------------------------------------------------

    ; 函数名: DispStr

    ;----------------------------------------------------------------------------

    ; 作用:

    ;    显示一个字符串, 函数开始时 dh 中应该是字符串序号(0-based)

    DispStr:

        mov    ax, MessageLength

        mul    dh

        add    ax, BootMessage

        mov    bp, ax            ; ┓

        mov    ax, ds            ; ┣ ES:BP = 串地址

        mov    es, ax            ; ┛

        mov    cx, MessageLength    ; CX = 串长度

        mov    ax, 01301h        ; AH = 13,  AL = 01h

        mov    bx, 0007h        ; 页号为0(BH = 0) 黑底白字(BL = 07h)

        mov    dl, 0

        int    10h

        ret
       
    说明,此函数的实现仍然是Int 10H中断
    使用了AH=13H的功能

    功能号:13H

    功能:在Teletype模式下显示字符串
    入口参数:AH=13H
              BH=页码
              BL=属性(若AL=00H或01H)
              CX=显示字符串长度
              (DH、DL)=坐标(行、列)
    ES:BP=显示字符串的地址 AL= 显示输出方式
     0—字符串中只含显示字符,其显示属性在BL中。显示后,光标位置不变
     1—字符串中只含显示字符,其显示属性在BL中。显示后,光标位置改变
     2—字符串中含显示字符和显示属性。显示后,光标位置不变
     3—字符串中含显示字符和显示属性。显示后,光标位置改变

    具体参看http://www.programfan.com/blog/article.asp?id=16290内容

    好,一句句分析
    代码中跳入函数体前,dh=0h,
    随后ax=MessageLength(ps,此MessageLength在后续代码中定义为9)
    后面一句mul dh

    这里先看下mul指令
    mul指令是乘法指令,无符号乘。使用mul做乘法的时候:
    1) 两个相乘的数:两个相乘的数,要么都是8位,要么都是16位。如果是8位,一个默认放在AL中,另外一个存放在8为寄存器或字节内存单元中;如果是16位,一个默认在AX中,另外一个放在16为寄存器或内存寄存器字单元中。

    2) 结果:如果是8位乘法,结果默认放在AX中;如果是16位乘法,结果高位默认在DX中存放,低位在AX中存放。

    格式:
    mul reg
    mul 内存单元

    内存单元可以用不同的寻址方式给出,比如:
    mul byte ptr ds:[0]
    含义:(ax) =(al)*((ds)*16+0);

    mul word ptr [bx+si+8]
    含义:(ax) =(ax)*((ds)*16+(si)+8)结果的低16位;(dx) =(ax)*((ds)*16+(si)+8)的结果的高16位。

    例如:
    计算100*10
    分析:100和10小于255,可以做8为乘法。
    mov al, 100
    mov bl, 10
    mov bl
    结果:(ax) =03E8H(即是:1000).

    计算100*10000
    分析:100小于255,10000大于255,所以必须做16位乘法。
    mov ax, 100
    mov bx, 10000
    mul bx
    结果:(ax) =4240H, (dx) =000FH(总的结果:F4240H =1000000).

    这个部分可以看出乘法结果放在AX寄存器中

    回到代码中,mul dh,结果Ax=0
    随后add    ax, BootMessage,把BootMessage地址给了Ax
        mov    bp, ax
        mov    ax, ds
        mov    es, ax
    这三句实现“ES:BP=显示字符串的地址(参看int 10H,AH=13h功能描述)”,其中es用ds来复制,说明串数据来源于DS数据段寄存器

    后面代码根据AH=13h功能描述,也就明了了
    mov    cx, MessageLength    ; CX = 串长度
    mov    ax, 01301h        ; AH = 13,  AL = 01h
    mov    bx, 0007h        ; 页号为0(BH = 0) 黑底白字(BL = 07h)
    mov    dl, 0

    最后,看下各个寄存器到底放了什么数据
    AX    01301h
    BX    0007h
    CX    9=1001h
    DX=DH+DL=0h,说明输出坐标是(0,0)

    ES=DS
    BP=BootMessage地址

    OK,关于DispStr函数的分析就此结束~~

    回过头看下loader.s的代码,发现这个又是另一种输出的方式,直接在显存地址上输出
    mov    ax, 0B800h;0B800h是PC机显存的开始地址,http://hi.baidu.com/numax/blog/item/9c51e464f8d736f8f6365439.html
    mov    gs, ax
    mov    ah, 0Fh                ; 0000: 黑底    1111: 白字
    mov    al, 'L'
    mov    [gs:((80 * 0 + 39) * 2)], ax    ; 屏幕第 0 行, 第 39 列。

    输出的"L"字符

    有些硬件的相关内容很重要~
  • 相关阅读:
    HAOI2008题解
    codeforces round375(div.2)题解
    codeforces round373(div.2) 题解
    TJOI2015题解
    CF976D. Degree Set
    dtoj#4243. 熊猫(i)
    dtoj#4242. 大爷(w)&&CF1061E
    CF786C Till I Collapse
    dtoj#4239. 删边(cip)
    dtoj#2504. ZCC loves cube(cube)
  • 原文地址:https://www.cnblogs.com/GoGoagg/p/1999986.html
Copyright © 2020-2023  润新知