c09 用户程序 — 主逻辑框图
c09.asm · SECTION code_1 / code_2 · 段间控制转移
《x86汇编语言:从实模式到保护模式》· 李忠
第9章 · 用户程序 (第1页 / 共2页)
code_1 段执行流程
code_2 段执行流程
子程序调用
段间跳转(retf)
顺序执行
跨段控制转移
SECTION code_1
vstart=0 · align=16
进入 start 时寄存器状态
CS→code_1 DS=ES→header SS→加载器栈
由加载器 jmp far [0x04] 跳入
start(入口点)
① SS ← [stack_segment](header[0x1c])
SP ← stack_end(= 0x100)
② DS ← [data_1_segment](header[0x14])
显示 msg0
BX ← msg0 偏移
call put_string(DS:BX)
远跳转到 code_2:begin
push [es:code_2_segment] → CS
push begin(偏移) → IP
retf → 跳入 code_2:begin
continue(code_2 远跳回此处)
DS ← [es:data_2_segment](header[0x18])
ES 仍指向 header
显示 msg1
BX ← msg1 偏移
call put_string(DS:BX)
jmp $(原地循环,程序结束)
SECTION code_2
vstart=0 · align=16
begin
push [es:code_1_segment] → CS
push continue(偏移) → IP
retf → 跳回 code_1:continue
(ES 始终保留 header 指针)
retf 远跳
retf 远跳回
put_string
输入:DS:BX = 字符串首地址
逐字节读取,遇0终止
每字符 call put_char 显示
call
call
ES 始终保留 header 指针
进入时 ES = header 段(加载器设置)
start 只改 SS、DS,ES 保持不动
通过 es: 前缀访问 header 各段地址字段
[es:code_2_segment] [es:data_2_segment]
c09 用户程序 — 打印字符逻辑框图
c09.asm · put_string / put_char · VGA文本模式字符输出
《x86汇编语言:从实模式到保护模式》· 李忠
第9章 · 用户程序 (第2页 / 共2页)
put_string
put_char 主流程
滚屏处理
判断分支
put_string
输入:DS:BX=字符串首地址
CL ← [DS:BX]
从字符串取一个字节
CL == 0?
字符串结尾?
是
ret(返回调用者)
否
call put_char(CL)
显示当前字符
BX++ → 下一个字符
循环
call
put_char
输入:CL = 字符 ASCII 码
push ax bx cx dx ds es(保存寄存器)
读取光标位置 → BX
0x3D4←0x0E, 0x3D5→AH(高8位)
0x3D4←0x0F, 0x3D5→AL(低8位) BX=AX
CL == 0x0D?
回车符 CR?
是
回车处理
BX÷80×80
→行首位置
直接→set_cursor
否
CL == 0x0A?
换行符 LF?
是
换行处理
BX += 80
否
普通字符写入显存
ES=0xB800,[ES:BX×2] ← CL
BX++(光标前进一格)
BX ≥ 2000?
光标超出屏幕?
否
是
滚屏处理
DS=ES=0xB800
rep movsw:0xA0→0x00,搬移1920字
清末行:[ES:3840~] ← 0x0720 ×80次
BX -= 80(光标上移一行)
设置光标位置(set_cursor)
0x3D4←0x0E,0x3D5←BH(高8位)
0x3D4←0x0F,0x3D5←BL(低8位)
pop es ds dx cx bx ax
ret(返回 put_string)