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

内核终端光标支持与逐行滚动功能实现咨询

内核终端滚动与光标功能实现修改方案

前置修正(原有代码Bug修复)

  • 删除重复定义的VGA_WIDTH、VGA_HEIGHT全局常量
  • 修正terminal_putchar中换行判断的逻辑位置,避免换行仅在列未溢出时生效
  • 删除terminal_putentryat中错误的行数越界判断逻辑

一、实现自动逐行滚动功能

新增滚动辅助函数

当输出行数超过25行时,将显存内容整体上移一行,清空最后一行容纳新内容:

void terminal_scroll() {
    // 第1~24行内容整体上移覆盖第0~23行
    for (size_t y = 1; y < VGA_HEIGHT; y++) {
        for (size_t x = 0; x < VGA_WIDTH; x++) {
            const size_t dest_idx = (y - 1) * VGA_WIDTH + x;
            const size_t src_idx = y * VGA_WIDTH + x;
            terminal_buffer[dest_idx] = terminal_buffer[src_idx];
        }
    }
    // 清空最后一行
    const size_t last_line_idx = (VGA_HEIGHT - 1) * VGA_WIDTH;
    for (size_t x = 0; x < VGA_WIDTH; x++) {
        terminal_buffer[last_line_idx + x] = make_vgaentry(' ', terminal_color);
    }
}

重写terminal_putchar逻辑

void terminal_putchar(char c) {
    // 优先处理换行符
    if (c == '\n') {
        terminal_row++;
        terminal_column = 0;
    } else {
        terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
        terminal_column++;
        // 列满自动换行
        if (terminal_column == VGA_WIDTH) {
            terminal_column = 0;
            terminal_row++;
        }
    }

    // 行溢出触发滚动
    if (terminal_row >= VGA_HEIGHT) {
        terminal_scroll();
        terminal_row = VGA_HEIGHT - 1;
    }
    // 同步更新光标位置
    terminal_update_cursor(terminal_row, terminal_column);
}

修正后的terminal_putentryat

void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
    const size_t index = y * VGA_WIDTH + x;
    terminal_buffer[index] = make_vgaentry(c, color);
}

二、实现VGA硬件光标支持

x86架构下通过操作VGA控制端口实现光标显示与位置更新,先补充端口操作函数:

// x86 端口输出字节内联汇编实现
static inline void outb(uint16_t port, uint8_t val) {
    __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
}

// 更新光标位置
void terminal_update_cursor(size_t row, size_t col) {
    uint16_t cursor_pos = row * VGA_WIDTH + col;
    // 写入光标位置高8位
    outb(0x3D4, 0x0E);
    outb(0x3D5, (uint8_t)(cursor_pos >> 8));
    // 写入光标位置低8位
    outb(0x3D4, 0x0F);
    outb(0x3D5, (uint8_t)(cursor_pos & 0xFF));
}

在terminal_initialize函数末尾添加初始化光标的调用:

terminal_update_cursor(0, 0);

三、可选:支持手动上下滚动查看历史内容

如果需要保留历史输出、支持手动翻页查看,可额外维护独立于显存的历史缓冲区:

  • 定义历史缓冲区参数:#define MAX_HISTORY_LINES 100(可自定义保存的历史行数)
  • 新增全局变量:uint16_t history_buffer[MAX_HISTORY_LINES][VGA_WIDTH];、size_t view_offset = 0;
  • 每次输出新行时同步写入历史缓冲区,手动翻页时调整view_offset,将对应区间的历史内容复制到显存即可实现上下滚动查看历史。

内容的提问来源于stack exchange,提问作者Mohammad Khaddam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:54:05