正在加载……
专注、离线、切勿分心
; 编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串 'welcome to masm!'
assume cs:codesg , ds:datasg , ss:stacksg
datasg segment
        db 'welcome to masm!'                 ;要显示字符串
        db 2h , 24h , 71h                            ;3行字符串分别的显示效果
datasg ends
stacksg segment
        dw 0h,0h,0h,0h,0h,0h,0h,0h          ;其实2个字单元就可以搞定了,程序只用到了2个字单元;刚开始写习惯性开辟16个字节刚好一行;这段空间是为了暂存一些子程序要重复用到的寄存器的值。
stacksg ends
codesg segment
start:  mov ax , datasg
        mov ds , ax

        mov ax , stacksg
        mov ss , ax
        mov sp , 16                                  ;设置栈顶偏移,指向空栈的下一位16

        mov ax , 0B872h   
                                              ;一页25行,设置显示的第一行的位置
                                              ;SA=0B800,EA=6E0H(12行的偏移,11*160(每行160个字节)=1760)+40H【偏移到中间,(160-16*2(一个字母还要在后面存贮一个显示属性,16*2算出显示指定字符串要占用的字节,然后用一行总的字节数减去显示占用的,剩下没用过的空间除以二得出一行偏移多少可以在中间显示字符串) )%2=64】
                                              ;SA+EA=0B8720H, cpu寄存器有限,为了节省寄存器,可以直接设置SA=0B87c,后面偏移在*16+EA(A0)结果都一样
        mov cx , 3               ;要显示3行,设置循环3次
        mov bx , 0              ;用来控制偏移,获取颜色,第一次循环为0,后面获取的是第一个颜色2h;第二次循环为1,获取第二个颜色24h ...
s:      mov es , ax                   ;用附加段寄存器存贮设置的显示缓冲区地址
        push ax                         ;进栈保存ax,也就是初始的显示缓冲区地址
        push cx                        ;后面还用到循环,只能先进栈保存最外层循环
        mov si , 0                      ;偏移读取字符
        mov di , 0                     ;偏移存贮读取到底字符
        mov cx , 16                  ;循环16次读取字符串
s0:   mov al , [si]                                       ;一个字符8位,用al暂存读到的字符
        mov es:[di] , al                                 ;把读到的数据存到显示缓冲区
        inc si                                                 ;偏移读取下一个字符
        add di , 2                                           ;存储下一个读到的字符,应为显示缓冲区每个字符后面要存放颜色属性,所以先空开来
        loop s0

        mov al , [bx+si]          ;获取第一个颜色,第一次循环后si=16,刚好指向数据段的2h
        mov cx , 16
        mov di , 1                   ;偶数偏移存放的是字符,对应的基数单元存放颜色属性,设置初试值1
s1:   mov es:[di] , al
        add di , 2
        loop s1                ;循环结束,第一行字符串的显示位置,颜色,内容设置完成

        pop cx                 ;取出最开始外层循环进行设置第二行
        pop ax                 ;取出初始显示缓冲区地址放入ax
        add ax , 000ah    ;一行160字节=40H,ax*16+40得到下一行显示起始的位置;节省寄存器,%16,当做SA
        inc bx                   ;bx+1,下次读取第二个颜色
        loop s                   ;执行最外层循环,cx=cx-1=2
        mov ax , 4c00h
        int 21h
codesg ends
end start
  //最终结果
知识背景:
    80*25彩色字符模式显示缓冲区结构,内存地址B8000H~BFFFFH,编程中要加上0在最开头,不然就错了。0B8000H~0BFFFFH;向这个地址空间写入数据,写入的内容将 立即出现在显示器。
   显示器可以显示25行,每行80个字符(00 00),每个字符有256中属性。(背景色、前景色、闪烁、高亮等组合信息)
   一个字符在显示缓冲区要占两个字节(00 00),分别存放字符ascii和属性。一屏的内容在显示缓冲区占4000个字节。
   显示缓冲区分8页,显示第0页的内容就是0B8000H~B8F9F

   在一页显示缓冲区中:  
偏移 000~09F 对应显示器上的第1行(80个字符占160个字节)
偏移 0A0~13F 对应显示器上的第2行(1*160=A0H)
偏移 140~1DF 对应显示器上的第3行(2*160=140H)
题目要在屏幕中间,就应该在第12行显示第一串字符,每行0~159个字符,11*160=1760(6E0H)刚好是第12行首地址;
F00~F9F 对应25行(24*160)
00~01 单元对应显示器第1列
02~03 单元对应显示器第2列
...
9E~9F 单元对应显示器第80列(79*2=9EH)

eg:显示器的第0行第0列显示红底绿色高亮闪烁字符串‘ABCDEF’
  //字符串一直在闪  

*用汇编语言编程中, 凡是4位16进制数据最高位为字母(ABCDEF),必须在前面加数字0,编译器好识别是一个数。


posted on 2017-08-06 00:55  正在加载……  阅读(4629)  评论(0编辑  收藏  举报