学习笔记
《x86汇编语言:从实模式到保护模式》
https://www.jianshu.com/p/d481cb547e9f
第十三章的 代码
- 用户程序
c13.asm
代码行数81行 - 内核程序
c13_core.asm
代码行数601行 - 加载程序
c13_mbr.asm
代码行数221行
加载程序 c13_mbr.asm
调用过程
- 1、内核程序 分配内存
- 2、内核程序 读取、加载用户程序
- 3、内核程序 转移CPU控制权给用户程序
- 4、用户程序 执行
- 5、用户程序 返回到 内核程序
- 6、内核程序 执行,最终进入停机状态
内存布局示意图
内存布局示意图.png运行结果
运行结果 标注各部分显示信息来源.png代码使用
配书工具 :
编译工具nasmide.exe
写扇区工具fixvhdwr.exe
- 1、编译加载程序
c13_mbr.asm
,生成二进制文件c13_mbr.bin
,将c13_mbr.bin
文件写入虚拟硬盘的LBA逻辑扇区0号; - 2、编译内核程序
c13_core.asm
,生成二进制文件c13_core.bin
,将c13_core.bin
文件写入虚拟硬盘的LBA逻辑扇区1号; - 3、编译用户程序
c13.asm
,生成二进制文件c13.bin
,将c13.bin
文件写入虚拟硬盘的LBA逻辑扇区50号; - 4、将数据文件
diskdata.txt
写入虚拟硬盘LBA逻辑扇区100号;
完整源码(用户程序,增加注释)
;代码清单13-3
;文件名:code_13.asm
;文件说明:用户程序
;创建日期:18:23 2018/6/3
;===========================================================
SECTION header vstart=0
program_length dd program_end ;程序总长度#0x00
head_len dd header_end ;程序头部的长度#0x04
stack_seg dd 0 ;用于接收堆栈段选择子#0x08
stack_len dd 1 ;程序建议的堆栈大小#0xc
prgentry dd start ;程序入口地址#0x10
code_seg dd section.code.start ;代码段位置#0x14
code_len dd code_end ;代码段长度#0x18
data_seg dd section.data.start ;数据段位置#0x1c
data_len dd data_end ;数据段长度#0x20
;------------------------------------------------------------
;符号地址检索表
salt_items dd (header_end - salt)/256 ;#0x24
salt:
PrintString db '@PrintString'
times 256-($-PrintString) db 0
TerminateProgram db '@TerminateProgram'
times 256-($-TerminateProgram) db 0
ReadDiskData db '@ReadDiskData'
times 256-($-ReadDiskData) db 0
header_end:
;===========================================================
SECTION data vstart=0
buffer times 1024 db 0 ;缓冲区
message_1 db 0x0d,0x0a,0x0d,0x0a
db '**********User program is runing**********'
db 0x0d,0x0a,0
message_2 db 'Disk data:',0x0d,0x0a,0
data_end:
;===========================================================
[bits 32]
;===========================================================
SECTION code vstart=0
start:
mov eax,ds ;ds此时指向用户程序头部段
mov fs,eax
mov eax,[stack_seg]
mov ss,eax
mov esp,0
mov eax,[data_seg]
mov ds,eax
mov ebx,message_1
call far [fs:PrintString]
mov eax,100 ;源地址:数据文件放在硬盘LBA逻辑扇区号100处
mov ebx,buffer ;目的地址:缓冲区偏移地址
call far [fs:ReadDiskData] ;段间调用:读扇区
mov ebx,message_2
call far [fs:PrintString]
mov ebx,buffer
call far [fs:PrintString]
jmp far [fs:TerminateProgram] ;将CPU控制权返回到内核程序
code_end:
;===========================================================
SECTION trail
;-----------------------------------------------------------
program_end:
代码说明
4-3 将描述符的选择子回写到用户程序头部段
内核程序回写 用户程序各个段的段选择子.png6 重定位用户程序的SALT表
将内核程序C-SALT表中的6字节入口地址 回写到 用户程度U-SALT表中.png当CPU转到用户程序代码段开始执行时,DS寄存器指向的是用户程序头部段
这是由于 内核程序 调用 load_relocate_program 的最后
会传递一个返回参数到寄存器AX mov ax,[es:0x04]
此时的 [es:0x04]指向的正是 用户程序的head_len 标号处
在经历过 步骤 4-3 的段选择子回写之后,这个标号现在存的就是 指向用户程序头部段的段选择子
借由AX寄存器做一个返回参数
之后,内核程序又通过 mov ds,ax 将这个值传递给ds
紧随其后的是 一条跳转指令 转移CPU控制权给 用户程序
mov ds,ax
jmp far [0x10]
因此,在用户程序真正开始执行的时候,DS寄存器 恰恰指向用户程序的头部段。
DS寄存器指向的是用户程序头部段
网友评论