H_Prj06_03 8088单板机串口读取8088ROM复位内存

news2025/6/8 14:33:07

1.8088CPU复位时,CS=FFFFH,IP=0000H,因此在ROM的逻辑地址FFFF:0000(FFF0H)处一般要防止一个长跳转指令LJMP(机器码位EAH)

2.写一个完整的8086汇编程序,通过查询方式检测串口接收符串‘r’,然后从内存地址FFFF:0000H开始发送16字节数据。程序使用18.432MHz时钟的16550 UART,波特率9600

3.程序

; 串口查询接收'r'后发送内存数据程序
; 硬件配置:
;   PC16550 基地址: 100H
;   时钟频率: 18.432MHz
;   波特率: 9600 bps
;   数据源: FFFF:0000H 开始的16字节内存

ORG 100H
JMP START

; 数据段
WAIT_MSG DB 'Waiting for "r"...', 0Dh, 0Ah, 0
SENDING_MSG DB 'Sending 16 bytes...', 0Dh, 0Ah, 0
DONE_MSG DB 'Transfer complete!', 0Dh, 0Ah, 0

; 16550寄存器偏移地址
UART_BASE EQU 100H
RBR_THR EQU UART_BASE + 0  ; 接收/发送寄存器
LSR     EQU UART_BASE + 5  ; 线路状态寄存器
LCR     EQU UART_BASE + 3  ; 线路控制寄存器
DLL     EQU UART_BASE + 0  ; 除数锁存低字节 (DLAB=1)
DLM     EQU UART_BASE + 1  ; 除数锁存高字节 (DLAB=1)

; 初始化UART (波特率9600, 18.432MHz时钟)
INIT_UART:
    ; 设置波特率除数(9600 @ 18.432MHz)
    MOV DX, LCR
    MOV AL, 80H       ; 设置DLAB=1
    OUT DX, AL
    
    MOV DX, DLL       ; 除数锁存低字节
    MOV AL, 78H       ; 120 = 78H
    OUT DX, AL
    
    MOV DX, DLM       ; 除数锁存高字节
    MOV AL, 00H       ; 高位为0
    OUT DX, AL
    
    ; 设置线路参数: 8位数据, 1停止位, 无校验
    MOV DX, LCR
    MOV AL, 03H       ; 8N1, DLAB=0
    OUT DX, AL
    
    ; 禁用中断
    MOV DX, UART_BASE + 1 ; IER
    MOV AL, 00H
    OUT DX, AL
    RET

; 发送单个字符
; 输入: AL = 要发送的字符
SEND_CHAR:
    PUSH DX
    PUSH AX
    
    ; 保存字符
    MOV AH, AL
    
SEND_WAIT:
    ; 检查发送保持寄存器是否为空
    MOV DX, LSR
    IN AL, DX
    TEST AL, 20H      ; 检查THRE位(bit5)
    JZ SEND_WAIT      ; 不为空则等待
    
    ; 发送字符
    MOV DX, RBR_THR
    MOV AL, AH
    OUT DX, AL
    
    POP AX
    POP DX
    RET

; 接收单个字符
; 输出: AL = 接收到的字符
RECV_CHAR:
    PUSH DX
    
RECV_WAIT:
    ; 检查接收数据就绪
    MOV DX, LSR
    IN AL, DX
    TEST AL, 01H      ; 检查DR位(bit0)
    JZ RECV_WAIT      ; 无数据则等待
    
    ; 读取字符
    MOV DX, RBR_THR
    IN AL, DX
    
    POP DX
    RET

; 发送字符串
; 输入: DS:SI = 字符串地址(以0结尾)
SEND_STRING:
    PUSH SI
    PUSH AX
    
SEND_STR_LOOP:
    LODSB             ; 从[DS:SI]加载字符到AL, SI++
    OR AL, AL         ; 检查是否结束(AL=0)
    JZ SEND_STR_DONE  ; 是则结束
    
    CALL SEND_CHAR    ; 发送当前字符
    JMP SEND_STR_LOOP ; 继续发送
    
SEND_STR_DONE:
    POP AX
    POP SI
    RET

; 发送内存块
; 输入: ES:BX = 数据起始地址
;       CX = 数据长度(字节数)
SEND_MEMORY:
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DX
    
    ; 发送状态消息
    MOV SI, OFFSET SENDING_MSG
    CALL SEND_STRING
    
    ; 设置计数器
    MOV CX,16
    
SEND_MEM_LOOP:
    ; 读取内存字节
    MOV AL, ES:[BX]
    
    ; 发送字节
    CALL SEND_CHAR
    
    ; 更新指针和计数器
    INC BX
    LOOP SEND_MEM_LOOP
    
    ; 发送完成消息
    MOV SI, OFFSET DONE_MSG
    CALL SEND_STRING
    
    POP DX
    POP CX
    POP BX
    POP AX
    RET

; 主程序
START:
    ; 初始化UART
    CALL INIT_UART
 
AGAIN:   
    ; 显示等待消息
    MOV SI, OFFSET WAIT_MSG
    CALL SEND_STRING
    
    ; 等待接收字符'r'
WAIT_FOR_R:
    CALL RECV_CHAR
    CMP AL, 'r'       ; 检查是否收到'r'
    JNE WAIT_FOR_R    ; 不是则继续等待
    
    ; 收到'r'后发送内存数据
    MOV AX, 0ffffH     ; 设置段地址0000H
    MOV ES, AX
    MOV BX, 0000H     ; 设置偏移地址2000H
    
    CALL SEND_MEMORY  ; 发送512字节数据                
    
    JMP  AGAIN
    
    ; 程序结束
    MOV AH, 4CH
    INT 21H    
    
   DB  55H,55H,55H,55H,55H

END START

 4.验证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2404212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

构建 MCP 服务器:第 3 部分 — 添加提示

这是我们构建 MCP 服务器的四部分教程的第三部分。在第一部分中,我们使用基本资源创建了第一个MCP 服务器;在第二部分中,我们添加了资源模板并改进了代码组织。现在,我们将进一步重构代码并添加提示功能。 什么是 MCP 提示&#…

基于React + FastAPI + LangChain + 通义千问的智能医疗问答系统

📌 文章摘要: 本文详细介绍了如何在前端通过 Fetch 实现与 FastAPI 后端的 流式响应通信,并支持图文多模态数据上传。通过构建 multipart/form-data 请求,配合 ReadableStream 实时读取 AI 回复内容,实现类似 ChatGPT…

C# 中替换多层级数据的 Id 和 ParentId,保持主从或父子关系不变

在C#中替换多层级数据的Id和ParentId,同时保持父子关系不变,可以通过以下步骤实现: 创建旧Id到新Id的映射:遍历所有节点,为每个旧Id生成唯一的新Id,并存储在字典中。 替换节点的Id和ParentId:…

PG 分区表的缺陷

简介 好久没发文,是最近我实在不知道写点啥。随着国产化进程,很多 oracle 都在进行迁移,最近遇到了一个分区表迁移之后唯一性的问题。oracle 数据库中创建主键或者唯一索引,不需要引用分区键,但是 PG 就不行&#xff…

从Copilot到Agent,AI Coding是如何进化的?

编程原本是一项具有一定门槛的技能,但借助 AI Coding 产品,新手也能写出可运行的代码,非专业人员如业务分析师、产品经理,也能在 AI 帮助下直接生成简单应用。 这一演变对软件产业产生了深远影响。当 AI 逐步参与代码生成、调试乃…

Qt(part 2)1、Qwindow(菜单栏,工具栏,状态栏),铆接部件,核心部件 ,2、添加资源文件 3、对话框

1、Qwindow tips:1,首先为什么创建出的对象基本都是指针形式,个人觉得是对象树的原因(自动释放内存),指针来访问成员函数->的形式。2,菜单栏只能一个的,放窗口基本Set&#xff0c…

【图片识别Excel】批量提取图片中的文字,图片设置识别区域,识别后将文字提取并保存Excel表格,基于WPF和OCR识别的应用

应用场景 在办公自动化、文档处理、数据录入等场景中,经常需要从大量图片中提取文字信息。例如: 批量处理扫描的表单、合同、发票等文档从图片集中提取特定区域的文字数据将纸质资料快速转换为电子文本并整理归档 通过设置识别区域,可以精…

Qt/C++学习系列之Excel使用记录

Qt/C学习系列之Excel使用记录 前言The process was ended forcefully.解决方式断点查语句问题 总结 前言 在项目中解析条目达50多条,并且都需要将对应的结果进行显示。为了将结果显示的更加清晰,考虑采用QTableWidget进行表格设置,而在使用过…

跳转指令四维全解:从【call/jmp 】的时空法则到内存迷宫导航术

一、核心概念:代码世界的空间定位法则 在汇编世界里,我们可以把内存想象成一栋巨大的图书馆: CS(代码段寄存器) 楼层编号 IP(指令指针) 房间编号 当前执行位置 CS:IP(如3楼201…

LabVIEW实时系统数据监控与本地存储

基于LabVIEW Real-Time 模块,面向工业自动化、嵌入式测控等场景,提供实时数据采集、监控与本地存储的完整实现路径。通过分层任务调度、TDMS 文件格式应用及跨平台兼容性设计,确保系统在实时性、可靠性与数据管理效率间达到平衡。文中以 Comp…

从 Revit 到 3DTiles:GISBox RVT 切片器如何让建筑图元在 Web 端展示

在GIS(地理信息系统)行业蓬勃发展的当下,数据处理与展示的效率和精准度成为关键。GISBox作为一款功能强大的一站式三维GIS数据编辑、转换、发布平台,凭借其独特的“RVT切片器”功能,在RVT图元处理方面也有着不俗的表现…

Appium+python自动化(十二)- Android UIAutomator

Android团队在4.1版本(API 16)中推出了一款全新的UI自动化测试工具UiAutomator,用来帮助开发人员更有效率的完成App的Debug工作,同时对于测试人员也是一大福音,为什么这么说呢? UiAutomator提供了以下两种…

QQ邮箱发送验证码(Springboot)

一、邮箱发送服务准备 在qq邮箱的设置中选择账号下开启服务。 开启时可能会有短信验证,开启后显示验证码之类的一串英文,复制保存起来,在配置文件中会使用到。 二、后端依赖及配置 依赖 在pom.yml文件中添加相关依赖,redis的…

【EF Core】 EF Core并发控制:乐观锁与悲观锁的应用

文章目录 前言一、并发的风险二、EF Core中的并发控制方式2.1 开放式并发(乐观锁)2.1.1 应用程序管理的属性并发令牌2.1.2 数据库生成的并发令牌 2.2 悲观锁 总结 前言 实际的生产环境中,我们经常能遇到数据库由多个应用程序同时使用。每个程…

Harmony核心:动态方法修补与.NET游戏Mod开发

一、Harmony的核心定位与设计哲学 Harmony是一个运行时动态方法修补库,专为修改已编译的.NET/Mono应用程序而设计,尤其适用于游戏Mod开发。其核心创新在于: 非破坏性修改:保留原始方法完整性,避免直接替换或覆盖。多…

【Java开发日记】说一说 SpringBoot 中 CommandLineRunner

目录 1、CommandLineRunner SpringBoot中CommandLineRunner的作用 简单例子 多个类实现CommandLineRunner接口执行顺序的保证 通过实现Ordered接口实现控制执行顺序 通过Order注解实现控制执行顺序 Order 作用 2、ApplicationRunner 3、传递参数 4、源码跟踪 run()方…

全面理解 Linux 内核性能问题:分类、实战与调优策略

在 Linux 系统(特别是嵌入式或服务器环境)中,性能问题往往错综复杂、表象多变。只有对常见性能问题进行系统归类、理解其症状与根源,才能有效定位和解决。本文将围绕八大类核心性能问题,结合实战示例,逐类分…

算法-多条件排序

1、数对排序的使用 pair<ll,ll> a[31];//cmp为比较规则 ll cmp(pair<ll,ll>a,pair<ll,ll>b){if(a.first!b.first)return a.first>b.first;else return a.second<b.second; }//按照比较规则进行排序 sort(a1,a31,cmp); 2、具体例题 输入样例&#xff1…

固定ip和非固定ip的区别是什么?如何固定ip地址

在互联网中&#xff0c;我们常会接触到固定IP和非固定IP的概念。它们究竟有何不同&#xff1f;如何固定IP地址&#xff1f;让我们一起来探究这个问题。 一、固定IP和非固定IP的区别是什么 固定IP&#xff08;静态IP&#xff09;和非固定IP&#xff08;动态IP&#xff09;是两种…

使用矩阵乘法+线段树解决区间历史和问题的一种通用解法

文章目录 前言P8868 [NOIP2022] 比赛CF1824DP9990/2020 ICPC EcFinal G 前言 一般解决普通的区间历史和&#xff0c;只需要定义辅助 c h s − t ⋅ a chs-t\cdot a chs−t⋅a&#xff0c; h s hs hs是历史和&#xff0c; a a a是区间和&#xff0c; t t t是时间戳&#xff0c…