2019_7_03
3.硬盘和显卡访问和控制
1)用户程序的结构
分段,段的汇编地址和段内汇编地址
一个规范的程序,应包括代码段,数据段,附加段和堆栈段。
段的化分和段与段之间的界限在程序加载到内存之前就已经准备好了。
定义段的汇编指令
SECTION 段名称
SEGMENT 段名称
每个段要求给出名字,即段名称,用来引用一个段。可以为任意名字,只要不重复和混淆。
一旦定义段,后面的内容都属于该段,除非出现另一个段的定义
有时,程序不以段定义语句开始,这时,这些内容默认自成一个段。典型情况整个程序都没有段定义语句,这时,整个程序自成一个段。
section data1 align = 16
db 0x55
section data2 align = 16
db 0xaa
section data3 align = 16
db 0x99
一般情况:
section.段名称.start
2)用户程序头部
加载器的编写者及用户程序的编写者之间必须有一个协定,在用户程序内部的某固定位置包含一些基本结构信息,每个用户程序都必须把自己的情况放在这里,加载器也固定在这个位置读取。约定,这个协定的地点放在程序开头。即用户程序头部。
SECTION header vstart = 0
程序头部需包含以下信息:
-
用户程序尺寸,即以字节为单位的大小
- 程序的长度取自程序中的一个标号“program_end”,这是允许的。在编译阶段,编译器将该标号所代表的汇编地址填写在这里。该标号位于整个源程序的最后,从属于段"trail"
- program_end所代表的汇编地址,在数值上等于整个程序的长度
-
应用程序的入口点,包括段地址和偏移地址
- 代码段 code_1定义
SECTION code_1 align=16 vstart=0
包含了“vstart”子句,故标号start所代表的汇编地址是相对于当前代码段code_1的起始位置,从0开始计算的 -
段重定位表
- 段的重定位是加载器的工作,它需要知道每个段在用户程序的位置
- 段重定位表的大小,或着说表项数是不正确的。
- 因为段重定位表位于两个标号header_end和code_1_segment之间,而且每个表项占用4字节,故实际的表项数为
(header_end – code_1_segment) / 4
这个值是在程序编译阶段计算的,先用两个标号所代表的汇编地址相减,再除以每个表项的长度4。
紧接着表项数的,是实际的段重定位表,每个表项用伪指令dd声明并初始化为1个双字。
3.加载器的工作流程
1)初始化和决定加载位置
从大方面来说,加载器加在一个用户程序,需决定两件事:
- 内存什么地方是空闲的,即从哪个物理内存地址开始加载用户程序
- 用户程序位于硬盘上的什么位置,它的起始逻辑扇区号是多少
app-lba_start equ 100
常熟用伪指令equ声明的,意思是“等于”。本句意思是,用标号 app_lba_start 来代表数值100,今后,要用到100,不需要
mov al,100
而是
mov al,app_lba_start
常熟即程序运行期间不变的数
和其他伪指令 db,dw,dd不同,equ声明的数值不占用任何汇编地址,也不在运行时占用任何内存位置。仅仅代表一个数。
加载用户程序需确定一个内存物理地址,这是伪指令dd声明的,并初始化为 0x10000
phy_base dd 0x10000
要求:后边的地址的最低四位必须是 0即加载的起始地址必须时16字节对齐的。
网友评论