本文将实现一个简单的程序加载器,首先要先了解一下实模式下的内存空间分配,这是固定好的
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SMxMTOyMGO5czYjJmYldzYyYzXwAzMzYTM4AzLcdDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
要实现一个程序加载器,需要实现下面4个步骤
1.将用户程序从硬盘中读取到10000处(当然,放到10000-9FFFF任意位置都可以)
2.设置段地址(段的重定位,注意段地址最低位必须是0)
3.找到用户的程序的入口(从哪开始执行)
4.跳转到程序入口执行
关于NASM的vstart关键字
由于本文使用NASM实现,所以有必要了解vstart关键字,如果一个段声明了vstart子句,则段内所有的汇编地址,编译之后,都等于vstart+偏移量
vstart示例1:下面代码vstart=0,jmp指令所在的汇编地址是3
Segment code1 vstart=0
mov ax,0x001 ;这条指令占3个字节
jmp bx
下图中最上面的绿色位置(vstart=0处)表示第1个开始计数的位置,这个位置=0,所以到jmp指令,正好是3
vstart示例2:下面代码vstart=2,mov指令所在的汇编地址是5
Segment code1 vstart=2
mov ax,0x001 ;这条指令占3个字节
jmp bx
下图中最上面的绿色位置(vstart=2处)表示第1个开始计数的位置,这个位置=0,所以到jmp指令,正好是5
日记:关于这个vstart,可以理解成将起始位置向上拓展延伸
关于标号
标号是相对于当前段的偏移量(字节数),而不是相对于程序的偏移量,不管NASM还是MASM,都是这样的
segment code vstart=0x7c00
;设置空栈
xor ax,ax
mov ss,ax
mov sp,ax
;设置用户程序的段地址
mov eax,[cs:app_address]
shr eax,4
mov ds,ax
mov es,ax
;设置用户程序要加载到0x10000位置
app_address dd 0x10000
;设置55AA
times 510-($-$$) db 00
dw 0xAA55