[翻译]如何用汇编创建一个基础内核 (二)
2011-03-11 23:28
253 查看
原文是 OSDev Wiki上的一个 Tutorials 文章。
1,第一个启动扇区
2,使用BIOS写消息
3,看看机器码
4,不用BIOS向屏幕打印输出
5,中断
6,进入保护模式
7,非实模式
8,32 位打印输出
附录A,更多资讯
2,使用BIOS写消息
快速回顾:
(1)BIOS加载的启动扇区大小是512字节
(2)在磁盘中启动扇区中的代码被BIOS 加载的地址位于0000:7C00
(3)机器在实模式下启动
(4) 应该清楚:CPU是可以给中断的,除非你明确使用了cli的汇编指令
许多(不是所有)BIOS中断预期是会用实模式下的段值来填充DS。这就是为什么许多BIOS中断在保护模式下
不会起作用的原因。所以当你想使用 int 10h/ah=0eh 去几屏幕打印字符,你需要确保你为打印字符所设置的
seg:offset 的值是正确的。
在实模式下,地址如些计算: segment*16+offset。 由于偏移地址可以比16大,所以会有许多的 segment offset
对是指向同一地址的。例如:一些时候说加载器是从0000:7C00处开始加载,当然,也有人说是从 07C0:0000处开始
加载。事实上,这两个是同一个地址: 16*0x0000 + 0x7c00 = 16*0x7C0 + 0x0000 = 0x7C00。
无论你使用0000:7C00 还是 07C0:0000 都是可以的,但你当你使用 org 时,你得清楚发生了什么事情。默认地,
原始二进制代码在一开始的偏移是0。若当你需要时,你可以改变这个偏移值,并使它生效。例如,下面的代码段是
从0X7C0处开始
; boot.asm
2 mov ax, 0x07c0
3 mov ds, ax
4
5 mov si, msg
6 ch_loop:lodsb
7 or al, al
8 jz hang
9 mov ah, 0x0E
int 0x10
jmp ch_loop
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
下面是一个 ORG 版本。这次, 从段址0处访问消息 。请留意你仍需要告诉DS怎么设置值:
1
2 org 0x7c00
3 xor ax, ax ; make it zero
4 mov ds, ax
5
6 mov si, msg
7 ch_loop:lodsb
8 or al, al ; zero=end of string
9 jz hang ; get out
mov ah, 0x0E
int 0x10
jmp ch_loop
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
过程版本。为了节省空间,典型地使用过程,像下面,在代码中使用 call / ret
1 org 0x7c00
2 xor ax, ax ;make it zero
3 mov ds, ax
4
5 mov si, msg
6 call bios_print
7
8 hang:
9 jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
bios_print:
lodsb
or al, al ;zero=end of str
jz done ;get out
mov ah, 0x0E
int 0x10
jmp bios_print
done:
ret
times 510-($-$$) db 0
db 0x55
db 0xAA
由于一些无法解释的原因,在加载SI,然后跳到过程时,我总会遇到bug。幸运的是,可以像我这样在NASM中
使用宏来传递一个参数。
1 %macro BiosPrint 1
2 mov si, word %1
3 ch_loop:lodsb
4 or al, al
5 jz done
6 mov ah, 0x0E
7 int 0x10
8 jmp ch_loop
9 done:
%endmacro
org 0x7c00
xor ax, ax
mov ds, ax
BiosPrint msg
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
如果,你觉得代码过长而不好理解,你可以把它分到不同的文件中去,然后在文件中包含在代码开头:
jmp main
%include "othercode.inc"
main:
; ... rest of code here
不要忘记了在一开始就调用 jmp main,不然的话,会顺序启动其它一些随机代码了。
(第二篇END)
1,第一个启动扇区
2,使用BIOS写消息
3,看看机器码
4,不用BIOS向屏幕打印输出
5,中断
6,进入保护模式
7,非实模式
8,32 位打印输出
附录A,更多资讯
2,使用BIOS写消息
快速回顾:
(1)BIOS加载的启动扇区大小是512字节
(2)在磁盘中启动扇区中的代码被BIOS 加载的地址位于0000:7C00
(3)机器在实模式下启动
(4) 应该清楚:CPU是可以给中断的,除非你明确使用了cli的汇编指令
许多(不是所有)BIOS中断预期是会用实模式下的段值来填充DS。这就是为什么许多BIOS中断在保护模式下
不会起作用的原因。所以当你想使用 int 10h/ah=0eh 去几屏幕打印字符,你需要确保你为打印字符所设置的
seg:offset 的值是正确的。
在实模式下,地址如些计算: segment*16+offset。 由于偏移地址可以比16大,所以会有许多的 segment offset
对是指向同一地址的。例如:一些时候说加载器是从0000:7C00处开始加载,当然,也有人说是从 07C0:0000处开始
加载。事实上,这两个是同一个地址: 16*0x0000 + 0x7c00 = 16*0x7C0 + 0x0000 = 0x7C00。
无论你使用0000:7C00 还是 07C0:0000 都是可以的,但你当你使用 org 时,你得清楚发生了什么事情。默认地,
原始二进制代码在一开始的偏移是0。若当你需要时,你可以改变这个偏移值,并使它生效。例如,下面的代码段是
从0X7C0处开始
; boot.asm
2 mov ax, 0x07c0
3 mov ds, ax
4
5 mov si, msg
6 ch_loop:lodsb
7 or al, al
8 jz hang
9 mov ah, 0x0E
int 0x10
jmp ch_loop
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
下面是一个 ORG 版本。这次, 从段址0处访问消息 。请留意你仍需要告诉DS怎么设置值:
1
2 org 0x7c00
3 xor ax, ax ; make it zero
4 mov ds, ax
5
6 mov si, msg
7 ch_loop:lodsb
8 or al, al ; zero=end of string
9 jz hang ; get out
mov ah, 0x0E
int 0x10
jmp ch_loop
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
过程版本。为了节省空间,典型地使用过程,像下面,在代码中使用 call / ret
1 org 0x7c00
2 xor ax, ax ;make it zero
3 mov ds, ax
4
5 mov si, msg
6 call bios_print
7
8 hang:
9 jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
bios_print:
lodsb
or al, al ;zero=end of str
jz done ;get out
mov ah, 0x0E
int 0x10
jmp bios_print
done:
ret
times 510-($-$$) db 0
db 0x55
db 0xAA
由于一些无法解释的原因,在加载SI,然后跳到过程时,我总会遇到bug。幸运的是,可以像我这样在NASM中
使用宏来传递一个参数。
1 %macro BiosPrint 1
2 mov si, word %1
3 ch_loop:lodsb
4 or al, al
5 jz done
6 mov ah, 0x0E
7 int 0x10
8 jmp ch_loop
9 done:
%endmacro
org 0x7c00
xor ax, ax
mov ds, ax
BiosPrint msg
hang:
jmp hang
msg db 'Welcome to Macintosh', 13, 10, 0
times 510-($-$$) db 0
db 0x55
db 0xAA
如果,你觉得代码过长而不好理解,你可以把它分到不同的文件中去,然后在文件中包含在代码开头:
jmp main
%include "othercode.inc"
main:
; ... rest of code here
不要忘记了在一开始就调用 jmp main,不然的话,会顺序启动其它一些随机代码了。
(第二篇END)
相关文章推荐
- [翻译]如何用汇编创建一个基础内核
- [翻译]如何用汇编创建一个基础内核 (五)
- [翻译]如何用汇编创建一个基础内核 (三)
- [翻译]如何用汇编创建一个基础内核 (六)
- [翻译]如何用汇编创建一个基础内核 (七)
- [翻译]如何用汇编创建一个基础内核 (四)
- [翻译]如何用汇编创建一个基础内核 (八)
- 如何用汇编创建一个基础内核
- 【】如何有效的创建一个教程-- 翻译讨论
- 【翻译】在Visual C#中如何创建一个Windows服务的安装项目
- 如何创建一个安全的Docker基础镜像
- 如何创建一个基础jQuery插件
- 如何创建一个安全的Docker基础镜像
- 如何创建一个在任何进程任何帐户任何会话都能存取的内核对象
- 如何创建一个安全的Docker基础镜像
- Linux内核分析课程--通过反汇编一个简单的c程序,分析汇编代码并理解计算机如何工作的
- java基础--如何创建一个线程
- [翻译] - <Entity Framework> - 快速入门: 用 EMD 工具在已有数据库的基础上创建一个模型
- 一个小白从零基础自学Android编程笔记之如何创建菜单
- 基础教学——如何用maven工具创建一个springmvc+mybatis的项目