You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86 16位汇编无BIOS中断14h初始化COM1串口报错求助

问题根因分析

你代码的核心错误是端口地址的定义和引用方式完全错误,其余为次要的隐患问题:

  1. 端口地址引用错误
    你用com1: dw 0x3f8的方式定义串口端口,是将0x3f8作为数据存储在内存的com1地址处;而你调用outb宏时传入的[com1+1]是读取com1偏移1的内存地址里的随机值作为端口号,完全不是你预期的0x3f8+1=0x3f9串口寄存器端口。
    这直接导致你之前outb [com1+3], 0x80根本没有正确设置DLAB位,后续往数据端口写值时操作的是错误的寄存器,自然会触发线路状态错误。
  2. 实模式运行环境初始化不完善
    你开头只初始化了部分段寄存器,没有配置栈段和栈指针,16位实模式下运行时很容易出现不可预知的内存覆盖问题,属于潜在隐患。
  3. 笔误小问题
    注释里的38440是笔误,正确波特率是38400。

修复方案

核心修改点

  • 将com1从内存变量改为编译期常量,用equ定义,调用outb时直接传常量表达式,不需要加内存引用的方括号
  • 补全栈段、栈指针的初始化
  • 修正端口引用的写法

修复后的完整代码

%macro outb 2
    mov dx, %1
    mov al, %2
    out dx, al
%endmacro

%macro inb 1
    mov dx, %1
    in al, dx
%endmacro

    bits 16
    org 0x7c00 ;; 引导扇区加载地址

    xor ax, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax    ; 初始化栈段
    mov sp, 0x7c00; 栈指针指向引导扇区开头,向下增长不会覆盖代码

serial_init:
    outb com1+1, 0x00 ;; 关闭所有串口中断
    outb com1+3, 0x80 ;; 开启DLAB,设置波特率除数
    outb com1+0, 0x03 ;; 除数低字节为3,对应38400波特
    outb com1+1, 0x00 ;; 除数高字节为0
    outb com1+3, 0x03 ;; 8数据位、无校验、1停止位
    outb com1+2, 0xc7 ;; 开启FIFO、清空FIFO、设置14字节阈值
    outb com1+4, 0x0b ;; 开启IRQ、设置RTS/DSR
    outb com1+4, 0x1e ;; 开启环回模式测试串口芯片
    outb com1+0, 0xae ;; 写入测试字节

    ;; 可选:添加测试逻辑,读回数据判断是否等于0xae确认硬件正常
    ; inb com1+0
    ; cmp al, 0xae
    ; jne serial_error

hang:
    jmp hang

com1 equ 0x3f8 ; 定义COM1端口为编译期常量

    times 510-($-$$) db 0
    dw 0xaa55

内容的提问来源于stack exchange,提问作者永劫回帰

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 11:57:05