<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Babystep2</id>
	<title>Babystep2 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Babystep2"/>
	<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Babystep2&amp;action=history"/>
	<updated>2026-04-04T01:31:09Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.foofun.cn//index.php?title=Babystep2&amp;diff=102&amp;oldid=prev</id>
		<title>Zhang3：创建页面，内容为“__NOTOC__  {{Infobox Tutorial | name=Babystep2: 使用BIOS打印消息 | prev=Babystep1 | next=Babystep3 }}  === 使用BIOS打印消息 ===  快速回顾: # BIOS加载的引导扇区为512字节 # 磁盘引导扇区中的代码由BIOS在0000:7c00加载 # 机器开始于 [http://www.osdev.org/wiki/Real_Mode Real Mode 实模式] # 请注意，除非你发出 CLI 汇编命令，否则CPU仍可接受中断  许多 (但不是全部) BIOS中断需要在DS…”</title>
		<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Babystep2&amp;diff=102&amp;oldid=prev"/>
		<updated>2021-12-27T02:13:28Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“__NOTOC__  {{Infobox Tutorial | name=Babystep2: 使用BIOS打印消息 | prev=&lt;a href=&quot;/index.php?title=Babystep1&quot; title=&quot;Babystep1&quot;&gt;Babystep1&lt;/a&gt; | next=&lt;a href=&quot;/index.php?title=Babystep3&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Babystep3（页面不存在）&quot;&gt;Babystep3&lt;/a&gt; }}  === 使用BIOS打印消息 ===  快速回顾: # BIOS加载的引导扇区为512字节 # 磁盘引导扇区中的代码由BIOS在0000:7c00加载 # 机器开始于 [http://www.osdev.org/wiki/Real_Mode Real Mode 实模式] # 请注意，除非你发出 &lt;a href=&quot;/index.php?title=CLI&quot; title=&quot;CLI&quot;&gt;CLI&lt;/a&gt; 汇编命令，否则CPU仍可接受中断  许多 (但不是全部) BIOS中断需要在DS…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
{{Infobox Tutorial&lt;br /&gt;
| name=Babystep2: 使用BIOS打印消息&lt;br /&gt;
| prev=[[Babystep1]]&lt;br /&gt;
| next=[[Babystep3]]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== 使用BIOS打印消息 ===&lt;br /&gt;
&lt;br /&gt;
快速回顾:&lt;br /&gt;
# BIOS加载的引导扇区为512字节&lt;br /&gt;
# 磁盘引导扇区中的代码由BIOS在0000:7c00加载&lt;br /&gt;
# 机器开始于 [http://www.osdev.org/wiki/Real_Mode Real Mode 实模式]&lt;br /&gt;
# 请注意，除非你发出 [[CLI]] 汇编命令，否则CPU仍可接受中断&lt;br /&gt;
&lt;br /&gt;
许多 (但不是全部) BIOS中断需要在DS寄存器填充Real Mode（实模式）段值。（译者注：这里的'''BIOS中断'''是指调用BIOS功能的INT指令） 这就是许多BIOS中断在保护模式下不起作用的原因。 因此，如果你想使用int 10h/ah=0eh打印字符到屏幕上，那么你需要确保要打印的字符的seg:offset（段偏移）是正确的。&lt;br /&gt;
&lt;br /&gt;
在实模式下，地址计算为 segment段 * 16 + offset偏移量。 由于偏移量可以远大于16（译者注：而使计算后的内存地址偏移到其它段中去）， 所以可以有许多对的段和偏移量指向相同的地址。 例如，可以说引导加载程序在0000:7C00加载，而也可以说位置是在07C0:0000。 因为这两个实际上是同一个地址: 16 * 0x0000 + 0x7C00 = 16 * 0x07C0 + 0x0000 = 0x7C00。&lt;br /&gt;
&lt;br /&gt;
无论你使用0000:7c00还是07c0:0000都是一样的， 但是，如果你使用ORG指令（译者注：这是一条伪指令，若有ORG伪指令，编译器则把其后的指令代码放到ORG伪指令指定的偏移地址。），则需要了解正在发生的事情。 默认情况下，原始二进制文件的起始位置为偏移量0，但是如果需要，可以将偏移量更改为不同的内容并使其正常工作。 例如，以下代码段访问具有段0x7C0的变量msg。&lt;br /&gt;
&lt;br /&gt;
Asm示例:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
; boot.asm&lt;br /&gt;
   mov ax, 0x07c0&lt;br /&gt;
   mov ds, ax&lt;br /&gt;
&lt;br /&gt;
mov si, msg&lt;br /&gt;
cld&lt;br /&gt;
ch_loop:lodsb&lt;br /&gt;
or al, al ; zero=end of str&lt;br /&gt;
jz hang   ; get out&lt;br /&gt;
mov ah, 0x0E&lt;br /&gt;
mov bh, 0&lt;br /&gt;
int 0x10&lt;br /&gt;
jmp ch_loop&lt;br /&gt;
&lt;br /&gt;
hang:&lt;br /&gt;
jmp hang&lt;br /&gt;
&lt;br /&gt;
msg   db 'Hello World', 13, 10, 0&lt;br /&gt;
times 510-($-$$) db 0&lt;br /&gt;
db 0x55&lt;br /&gt;
db 0xAA&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
以下是用ORG伪指令的版本。 这次，使用segment段基址0访问msg。（译者注：因为机器指令被载入的位置已经被ORG指令改变了） 请注意，你仍然需要设置DS的值，因为它开始可能会被初始化为任何值。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
[ORG 0x7c00]&lt;br /&gt;
&lt;br /&gt;
xor ax, ax ; make it zero&lt;br /&gt;
mov ds, ax&lt;br /&gt;
&lt;br /&gt;
mov si, msg&lt;br /&gt;
cld&lt;br /&gt;
ch_loop:lodsb&lt;br /&gt;
or al, al  ; zero=end of string&lt;br /&gt;
jz hang    ; get out&lt;br /&gt;
mov ah, 0x0E&lt;br /&gt;
mov bh, 0&lt;br /&gt;
int 0x10&lt;br /&gt;
jmp ch_loop&lt;br /&gt;
&lt;br /&gt;
hang:&lt;br /&gt;
jmp hang&lt;br /&gt;
&lt;br /&gt;
msg   db 'Hello World', 13, 10, 0&lt;br /&gt;
&lt;br /&gt;
times 510-($-$$) db 0&lt;br /&gt;
db 0x55&lt;br /&gt;
db 0xAA&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Procedures过程 ===&lt;br /&gt;
&lt;br /&gt;
为了保护写入空间，通常使用CALL/RET将传统上的 “过程” 与代码分开，如下所示:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
[ORG 0x7c00]&lt;br /&gt;
   xor ax, ax  ;make it zero&lt;br /&gt;
   mov ds, ax&lt;br /&gt;
   cld&lt;br /&gt;
&lt;br /&gt;
mov si, msg&lt;br /&gt;
call bios_print&lt;br /&gt;
&lt;br /&gt;
hang:&lt;br /&gt;
jmp hang&lt;br /&gt;
&lt;br /&gt;
msg   db 'Hello World', 13, 10, 0&lt;br /&gt;
&lt;br /&gt;
bios_print:&lt;br /&gt;
lodsb&lt;br /&gt;
or al, al  ;zero=end of str&lt;br /&gt;
jz done    ;get out&lt;br /&gt;
mov ah, 0x0E&lt;br /&gt;
mov bh, 0&lt;br /&gt;
int 0x10&lt;br /&gt;
jmp bios_print&lt;br /&gt;
done:&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
times 510-($-$$) db 0&lt;br /&gt;
db 0x55&lt;br /&gt;
db 0xAA&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
出于某种莫名其妙的原因，加载SI（译者注：lodsb指令做的事情） '''然后''' 跳到过程总是困扰着我。 幸运的是，对于像我这样的精神病，NASM的宏让我可以使用一种假装正在传递参数的写法 (调用前必须先定义宏)。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
%macro BiosPrint 1&lt;br /&gt;
                mov si, word %1&lt;br /&gt;
ch_loop:lodsb&lt;br /&gt;
   or al, al&lt;br /&gt;
   jz done&lt;br /&gt;
   mov ah, 0x0E&lt;br /&gt;
   int 0x10&lt;br /&gt;
   jmp ch_loop&lt;br /&gt;
done:&lt;br /&gt;
%endmacro&lt;br /&gt;
&lt;br /&gt;
[ORG 0x7c00]&lt;br /&gt;
xor ax, ax&lt;br /&gt;
mov ds, ax&lt;br /&gt;
cld&lt;br /&gt;
&lt;br /&gt;
BiosPrint msg&lt;br /&gt;
&lt;br /&gt;
hang:&lt;br /&gt;
jmp hang&lt;br /&gt;
&lt;br /&gt;
msg   db 'Hello World', 13, 10, 0&lt;br /&gt;
&lt;br /&gt;
times 510-($-$$) db 0&lt;br /&gt;
db 0x55&lt;br /&gt;
db 0xAA&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果你的代码变得很长且不可读，则可以将其分解为多个文件， 然后在主代码的开头包含文件。就像这样:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
jmp main&lt;br /&gt;
&lt;br /&gt;
%include &amp;quot;othercode.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
main:&lt;br /&gt;
; ... rest of code here&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
不要忘记写开头的jmp main - 否则将调用一些包含的其他过程。&lt;br /&gt;
&lt;br /&gt;
[[Category:Babystep]]&lt;/div&gt;</summary>
		<author><name>Zhang3</name></author>
	</entry>
</feed>