吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 50|回复: 0
收起左侧

[学习记录] (新手学习linux_kernal)1.汇编实现BOOT打印字符串

[复制链接]
TSA 发表于 2026-1-6 23:40
本帖最后由 TSA 于 2026-1-6 23:57 编辑

环境需求:
  • ubuntu16(任意版本都可,作者用的16)
  • nasm编译器
  • qemu或者bochs
  • clion或者其他c语言编程环境


BOOT基础结构:
在编写前我们需要了解BOOT汇编代码的基础结构以及它的一些伪指令:
ORG:ORG用来指定相对位置,后面的值要与程序在内存中的值一致,下图为程序固定分配图:
内核linux内核e3441d62d2b344202ed14bfee1b18755.png
用法:
[Asm] 纯文本查看 复制代码
[ORG 0x7c00]

section:用于定义段
用法:
[Asm] 纯文本查看 复制代码
[section .text] ;表示代码段
[section .data] ;表示数据段
[section .bss] ;表示栈段

bits : 用于向编译器说明编译位数,有16位和32位
用法:
[Asm] 纯文本查看 复制代码
[BITS 16]

global : 代码是用于定义入口点,主要将函数导出为编译器等可见,类似于extern,数据上用于定义全局变量
用法:
[Asm] 纯文本查看 复制代码
global _start

times : 定义一条指令或者一组指令重复次数
用法:
[Asm] 纯文本查看 复制代码
times 510 - ($ - $$ ) db 0
db 0x55,0xaa

上述代码中$表示整个1代码结尾位置,$$表示开始位置,减去就是整个代码的大小,510减去代码大小在db填充0,填充0x55与0xaa,0x55与0xaa的填充是硬性要求,应为内核会检查这俩位,如果不是就不会载入
equ : 定义常量
用法:
[Asm] 纯文本查看 复制代码
MAIN_SETUP equ 0x500

还有字符串定义:
[Asm] 纯文本查看 复制代码
msg:
      db "hello.world",10,13,0

10 和 13 ascii码表示回车和换行,0结尾
以上便是汇编编写BOOT的一些基础函数,接下来我们就可以进行正式的编写:
首先固定模式:
[Asm] 纯文本查看 复制代码
[ORG 0x7c00] ;定义入口地址,MBR载入BOOT的入口地址固定为0x7c00

[section .text] ;定义代码段
[Bits 16] ;定义16b编译

global _start ;入口函数定义

其次实现主函数,主函数实现比较简单:
[Asm] 纯文本查看 复制代码
_start:
    mov ax,3 ;传入参数3给屏幕中断
    int 0x10  ;屏幕中断调用,实现清屏

    mov si,msg ;将msg字符串地址传给si寄存器
    call print  ;调用定义的打印函数
    jmp $ ;跳回开头

msg字符串实现:
[Asm] 纯文本查看 复制代码
msg:
    db "hello,world",10,13,0

print函数实现,在print中打印字符,是通过int 0x10 屏幕中断实现,又int 0x10单次只能打印一个字符,所以需要通过循环进而打印整个字符串:
[Asm] 纯文本查看 复制代码
print:
    mov ah,0x0e  ; 设置int 0x10功能号 0x0e
    mov bh,0 ;设置显示页号,默认0,即当前页
    mov bl,0x01 ;设置前景色,可用可不用
.loop:
    mov al,[si] ;将字符传递给al寄存器
    cmp al,0 ;比较
    jz .done
    int 0x10  ;调用中断

    inc si
    jmp .loop
.done:
    ret

综上,我们可以得到完整代码:
[Asm] 纯文本查看 复制代码
[ORG 0x7c00]

[section .text]
[Bits 16]

global _start

_start:
    xchg bx,bx
    xchg bx,bx



    mov ax,3
    int 0x10

    mov si,msg
    call print
    jmp $


print:
    mov ah,0x0e
    mov bh,0
    mov bl,0x01
.loop:
    mov al,[si]
    cmp al,0
    jz .done
    int 0x10

    inc si
    jmp .loop
.done:
    ret


msg:
    db "hello,world",10,13,0

times 510 - ($ - $$ ) db 0
db 0x55,0xaa

我们要将其运行,首先进行编译,将其编译为二进制文件:
[Asm] 纯文本查看 复制代码
nasm boot.asm

创建硬盘文件:
[Asm] 纯文本查看 复制代码
bximage -q -hd=16 -func=create -sectsize=512 -imgmode=flat hd.img

-q  表示不进行交互-hd 表示创建硬盘大小为16M-func 功能是创建-section 扇区大小-imgmode 存储格式 flat表示扁平二进制,没有元数据,头部,压缩hd.img 表示输出名字
将编译的二进制文件copy到创建的硬盘文件:
[Asm] 纯文本查看 复制代码
dd if=boot of=hd.img bs=512 seek=0 count=1 conv=notrunc

dd 拷贝工具if input file 输入文件of output file 输出文件bs 块大小为512seek 表示从第几块扇区开始写count 写几块conv=notrunc 表示写完后不截断,且只覆盖前512
qemu运行:
[Asm] 纯文本查看 复制代码
qemu-system-x86_64 -hda hd.img

屏幕截图 2026-01-06 233437.png
可以看到我们成功的通过BOOT,打印字符串

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-1-13 15:36

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表