交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
8 屏幕输出
分享
未结
0
2744
李延
LV6
2022-06-30
悬赏:20积分
# 1 在屏幕上显示文字 在 8086 cpu中,其中内存地址0x0b8000 -0x0bffff被映射到了显卡区域,我们可以通过这部分的内存地址,直接向显示器输出内容。 在cpu刚启动时,显卡进入文本模式,屏幕一共可以显示80*25 个字符,80列 25行的模式。其中一个字节为展示内容,一个字符为显示颜色。 所以我们可以通过向0x0b8000后的4000个字节写入内容,让显示器展示内容。 # 2 打印hello word!! ```asm .code16 .global _start .equ BOOTSEG, 0x07c0 # original address of boot-sector _start: mov $BOOTSEG,%ax mov %ax,%ss mov %ax,%ds ## 设置 显示区域的段地址。 movw $0xb800,%ax movw %ax,%es movb $'h',%es:(0x00) movb $0x07,%es:(0x01) movb $'e',%es:(0x02) movb $0x07,%es:(0x03) movb $'l',%es:(0x04) movb $0x07,%es:(0x05) movb $'l',%es:(0x06) movb $0x07,%es:(0x07) movb $'o',%es:(0x08) movb $0x07,%es:(0x09) movb $' ',%es:(0x0a) movb $0x07,%es:(0x0b) movb $'w',%es:(0x0c) movb $0x07,%es:(0x0d) movb $'o',%es:(0x0e) movb $0x07,%es:(0x0f) movb $'r',%es:(0x10) movb $0x07,%es:(0x11) movb $'d',%es:(0x12) movb $0x07,%es:(0x13) movb $'!',%es:(0x14) movb $0x07,%es:(0x15) movb $'!',%es:(0x16) movb $0x07,%es:(0x17) .org 510 boot_flag: .word 0xAA55 ```  ## 3 通过循环打印 前面我们是直接在代码里枚举所有字符进行打印的内容。 当然我们也可以通过循环来打印字符串,与C语言相同我们以\0来判断字符串是否结束。 下面就是打印msg1 的示例: ```asm .code16 .global _start .equ BOOTSEG, 0x07c0 # original address of boot-sector _start: mov $BOOTSEG,%ax mov %ax,%ss mov %ax,%ds mov $0x400,%sp movw $msg1,%ax call print print: movw %ax,%bx movw $0,%bp ## 设置 显示区域的段地址。 movw $0xb810,%ax movw %ax,%es .print_loop: ## 传输打印的字符 movb (%bx),%al movb %al,%es:(%bp) inc %bp movb $0x07,%es:(%bp) inc %bp inc %bx ## 当字符位\0的时候跳出循环 cmp $0,(%bx) jne .print_loop ret msg1: .string "hello word!!!!!!!!!!!\0" .org 510 boot_flag: .word 0xAA55 ``` # 4 控制光标 前面我们打印的字符串都是在显示器的最开始地方,但在日常时,我们常常是在光标位置进行输出的,所以我们这里就需要控制: - 查询光标位置。 - 在光标的位置输出内容。 - 将光标向后移动一格。 这里我们额外多了两个步骤,获取光标位置和修改光标位置。 对于光标的操作需要通过IO接口来进行操作,对于IO接口的操作通过两个特别的指令 - out 输入信息 - in 加载形象 对于光标的操作是通过两个特定的端口 - 0x03d4 向显示器输出信息 - 0x03d5 获取显示器的形象 这里我们通过向0x03d4 端口发送 0x0e指令 告诉显示器我们需要获取高8位的光标位置,之后我们就可以通过0x03d5 得到我们需要的信息 同样低8位是通过0x0f指令进行。 如下为在光标位置打印信息的代码: ``` .code16 .global _start .equ BOOTSEG, 0x07c0 # original address of boot-sector .equ GRAPHICS_INDEX, 0x3d4 # original address of boot-sector .equ GRAPHICS_READ, 0x3d5 # original address of boot-sector _start: mov $BOOTSEG,%ax mov %ax,%ss mov %ax,%ds mov $0x9000,%sp movw $msg1,%bx .print_loop: ## 传输打印的字符 movw (%bx),%cx call put_char inc %bx ## 当字符位\0的时候跳出循环 cmp $0,(%bx) jne .print_loop load_cursor: pushw %bx pushw %dx movw $GRAPHICS_INDEX,%dx movb $0x0e,%al out %al,%dx movw $GRAPHICS_READ,%dx in %dx,%al mov %al,%ah movw $GRAPHICS_INDEX,%dx movb $0x0f,%al out %al,%dx movw $GRAPHICS_READ,%dx in %dx,%al popw %dx popw %bx ret set_cursor: pushw %ax pushw %bx pushw %dx movw %ax,%bx movw $GRAPHICS_INDEX,%dx movb $0x0e,%al out %al,%dx movw $GRAPHICS_READ,%dx movb %bh,%al out %al,%dx mov %al,%ah movw $GRAPHICS_INDEX,%dx movb $0x0f,%al out %al,%dx movw $GRAPHICS_READ,%dx movb %bl,%al out %al,%dx popw %dx popw %bx popw %ax ret # 打印一个字符 # ax 光标位置 , cl 需要打印的字符 put_char: pushw %ax pushw %bp pushw %es call load_cursor movw %ax,%bp movw $0xb800,%ax movw %ax,%es shl $1,%bp movb %cl,%es:(%bp) shr $1,%bp inc %bp movw %bp,%ax call set_cursor popw %es popw %bp popw %ax ret msg1: .string "hello word!!!!!!!!!!!\0" .org 510 boot_flag: .word 0xAA55 ``` 结果:  索引寄存器端口号 0x3d4 从0x3d5 读取数据 0x0e 高8位 0x0f 低8位
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号