注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

编程学习

我的网上家园

 
 
 

日志

 
 

13章练习: put_string子程序练习  

2013-03-04 10:45:00|  分类: 《x86汇编语言: |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
; 13章练习
; 保护模式下的 put_string子程序 (复习以前的内容)
; 入口 DS:EBX指向字符串起始位置 
; 常量: video_ram_seg_sel 显示缓冲区的选择子
; 光标寄存器存放光标的当前位置 每行80列,一共25行 行列从0开始,0表示第0行第0列,1表示第0行第1列
; 第一行第0列是1*80=80 最后一行结尾是 24*80+79 也就是 25*80-1

; 限于MBR 只有512字节,测试子程序时,可以替换 书中核心代码中的子程序

; 13章练习
; 保护模式下的 put_string子程序 (复习以前的内容)
; 入口 DS:EBX指向字符串起始位置 
; 常量: video_ram_seg_sel 显示缓冲区的选择子


video_ram_seg_sel equ 0x20

mov ax,cs
mov ss,ax
mov sp,0x7c00

mov ax,[cs:pgdt+0x7c00+0x2]
mov dx,[cs:pgdt+0x7c00+0x4]
mov bx,16
div bx
mov ds,ax
mov bx,dx
mov dword [bx+0x0],0
mov dword [bx+0x4],0
;代码段
mov dword [bx+0x8],0x7c0001ff
mov dword [bx+0xc],0x00409800
;4GB数据段
mov dword [bx+0x10],0x0000ffff
mov dword [bx+0x14],0x00cf9200
;栈段
mov dword [bx+0x18],0x7c00fffe
mov dword [bx+0x1c],0x00cf9600
;显示缓冲区
mov dword [bx+0x20],0x80007fff
mov dword [bx+0x24],0x0040920b
mov word [cs:pgdt+0x7c00],39
lgdt [cs:pgdt+0x7c00]

in al,0x92
or al,2
out 0x92,al

cli

mov eax,cr0
or eax,1
mov cr0,eax

jmp 0x8:flush

[bits 32]

flush:
mov eax,0x18
mov ss,eax
mov esp,0

mov eax,0x10
mov ds,eax


lea ebx,[message+0x7c00]
call 0x8:put_string
lea ebx,[message2+0x7c00]
call 0x8:put_string
lea ebx,[message3+0x7c00]
call 0x8:put_string
lea ebx,[message4+0x7c00]
call 0x8:put_string

hlt


; put_string 子程序
;========================================================
put_string:
push ecx
.show:
mov cl,[ebx]
or cl,cl
jz .ret
call put_char
inc ebx
jmp .show
.ret:
pop ecx
retf

put_char:
pushad
xor eax,eax  ;清EAX
mov dx,0x3d4 ;0x3d4索引寄存器
mov al,0xe ;0xe是光标位置高8位寄存器端口号
out dx,al
inc dx
in al,dx
mov ah,al
dec dx
mov al,0xf
out dx,al
inc dx       
in al,dx     ;AX=光标当前位置
cmp cl,0xd   ;0xd回车符
jnz .0xa
mov bl,80
div bl
mul bl
jmp .setcursor

.0xa:
cmp cl,0xa
jnz .put_ch
add ax,80
cmp ax,80*25
jb .setcursor ;小于等于屏幕最后一行一列,更新光标位置.
sub ax,80
jmp .roll_screen ;备注: 为了程序简洁起见,滚动屏幕以后又刷新了一下光标的位置,其实是不必要的.


.put_ch:
push es
mov ebx,video_ram_seg_sel
mov es,ebx
shl eax,1 ;EAX左移一位相当于乘以2  EAX高16位是0,这里用EAX是为了使用32位寻址.
mov [es:eax],cl
pop es
shr eax,1 ;恢复原值
inc eax
cmp eax,80*25
jb .setcursor
mov ax,80*24 

.roll_screen:
push ds
push es
mov ebx,video_ram_seg_sel
mov ds,ebx
mov es,ebx
mov esi,80*2
xor edi,edi
mov ecx,80*24*2/4
cld
rep movsd
mov edi,80*24*2
mov ecx,80*2/4
.show_clr:
mov dword [es:edi],0x07200720
add edi,4
loop .show_clr
pop es
pop ds

.setcursor:
mov bx,ax
mov dx,0x3d4
mov al,0xe
out dx,al
inc dx
mov al,bh
out dx,al
dec dx
mov al,0xf
out dx,al
inc dx
mov al,bl
out dx,al

popad 
ret



message:
db 'Hello,world!',0xa,0xd,0
message2:
db 'Hello.',0xa,0xa,'Hello.     ','Hello.',0xa,0
message3:
db 'Hello',0xd,0
message4:
times 19 db 0xa 
times 20 db  's'
db 0



pgdt dw 0
dd 0x7e00
times 510-($-$$) db 0
db 0x55,0xaa
  评论这张
 
阅读(18)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017