org 07c00h ; 告诉编译器程序加载到7c00处
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串长度
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 号中断
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志
个人的具体理解:
ORG: the function of the org directive is to specify the origin address which NASM will assume the program begins at when it is loaded into memory. Its sole function is to specify one offset which is added to all internal address referemces within the section.
mov ax, cs
mov ds, ax
mov es, ax
:这是对段寄存器赋值的经典格式,需了解其背后相关的知识,
8086中段寄存器是因为对内存的分段管理而设置的,每个段寄存器各有不同的含义。
1 代码段寄存器CS:存放当前正在运行的程序代码所在的段基址值,表示当前使用的指令代码可以从该段寄存器指定的段寄存器中取得,相应的偏移值由IP提供。cpu从 CS:IP所指向的内存地址单元中 取得指令并执行。由于 CS 和IP相当重要,8086没有提供直接修改这两个寄存器的指令。但是我们可以通过其他手段实现程序的跳转,比如jmp和call指令。
2 数据段寄存器DS:存放当前程序所使用数据的段基值。 8086不支持把数据直接送到段寄存器(SS、ES和DS), 给这些段寄存器赋值必须通过其他寄存器。比如通用寄存器(AX,BX,CX,DX),从名字可以看出,几乎任何操作都可以对这几个寄存器进行操作。其中,[BX]或者[BX+immdate](此时BX中的数据最可能被作为偏移地址和DS配合以给出物理内存地址),此外,CX寄存器也常用来控制循环等。
3, 堆栈段寄存器SS:存放堆栈段的段基值。SS:SP所给出的地址是当前栈顶地址,值得注意的一点是:8086CPU中对栈的操作都是以“字”为单位的!也就是说,出栈和入栈每次的处理单元都是“两个字节”!!
4, 附加段寄存器ES:指出当前程序使用附加数据段的段基址,该段是串操作指令中目的串所在的段。
SI、DI和BP这些寄存器的作用比较相似:辅助寻址,而且在8086中,只有在BX,SI,DI和BP这四个寄存器可以用在[]中,这四个寄存器可以单独出现在[...]中,也可以按照如下组合进行搭配:BX和SI;BX和DI;BP和SI;BP和DI。
call DispStr:
CALLcalls a subroutine, by means of pushing the current instruction pointer (IP) and optionally CSas well on the stack, and then jumping to a given address.(call命令 改变程序执行的位置即调用一个子程序,同时将当前地址入栈,如果是短调用就入IP就行,如果是长调用入CS和IP)
指令中的 DispStr是一个标号,表示要跳转所要执行指令的地址。
jmp $:
$evaluates to the assembly position at the beginning of the line containing the expression; so you can code an infinite loop using JMP $。($表示当前被汇编后的地址)
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串长度
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 号中断
:这个是一个中断调用,这个功能是由BIOS提供的。
功能描述:在Teletype模式下显示字符串,
其功能号位13H,用AH表示,即AH=13H
入口参数:ES:BP为所要显示字符串所存储的地址
CX表示所要显示字符串的长度
BH表示页号,BL表示属性
DH表示起始的行,DL表示起始的列
AL表示显示输出方式:0—— 字符串中只含显示字符,其显示属性在BL中。显示后,光标位置不变
1——字符串中只含显示字符,其显示属性在BL中。显示后,光标位置改变
2 ——字符串中含显示字符和显示属性。显示后,光标位置不变
3——字符串中含显示字符和显示属性。显示后,光标位置改变
出口参数:无
ret:RET, and its exact synonym RETN, pop IP or EIP from the stack and transfer control to the new address. Optionally, if a numeric second operand is provided, they increment the stack pointer by a further imm16 bytes after popping the return address.
BootMessage: db "Hello, OS world!" :表示程序所需的数据,其存储的数据位置
times 510-($-$$) db 0 :
The TIMESprefix causes the instruction to be assembled multiple times. This is partly present as NASM's equivalent of the DUPsyntax supported by MASM-compatible assemblers, in that you can code ( 510-($-$$)表示执行这条指令的次数)
$$evaluates to the beginning of the current section; so you can tell how far into the section you are by using ($-$$).
Remember:内存的地址是从0开始计的。
当按下电脑电源开关,计算机的启动步骤:
1.开关按下,发信号给bios
2.bios获得信号后,启动自检程序,检查周边设备是否通电完毕。
3.自检完毕后将控制权还给bios,bios读取引导启动器中的启动程序(引导启动器可以是光盘,软盘或者usb,设置是网络启动,装过系统的都应该有深入的理解)
系统的内存安排:
在系统加电最初的1M内存是bios为我们准备好的,他的分布情况为