📄 preparing-asm_4.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0058)http://www.huihoo.com/gnu_linux/own_os/preparing-asm_4.htm -->
<HTML><HEAD><TITLE></TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2800.1106" name=GENERATOR></HEAD>
<BODY>
<P><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN
lang=EN-US><FONT face="Times New Roman" size=6><SPAN
style="mso-tab-count: 1"><STRONG>0.4 AT&T ASM
Syntax</STRONG></SPAN></FONT></SPAN></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN
lang=EN-US><FONT face="Times New Roman" size=6><SPAN
style="mso-tab-count: 1"><STRONG></STRONG></SPAN></FONT></SPAN><SPAN
lang=EN-US><FONT face="Times New Roman" size=5><SPAN
style="mso-tab-count: 1"><FONT
size=3></FONT></SPAN></FONT></SPAN></SPAN> </P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN
lang=EN-US><FONT face="Times New Roman" size=5><SPAN
style="mso-tab-count: 1"><FONT size=3>[</FONT><A
href="index.htm"
tppabs="http://pagoda-ooos.51.net/os_book/index.htm"><FONT
size=3>Home</FONT></A><FONT size=3>] [</FONT><A
href="preparing.htm"
tppabs="http://pagoda-ooos.51.net/os_book/preparing.htm"><FONT
size=3>Top</FONT></A><FONT size=3>] [<A
href="preparing-lang_3.htm"
tppabs="http://pagoda-ooos.51.net/os_book/prepare/preparing-lang_3.htm">Previous</A><FONT
size=3>] </FONT></FONT><FONT size=3> [</FONT><FONT size=3><A
href="preparing-comp_5.htm"
tppabs="http://pagoda-ooos.51.net/os_book/prepare/preparing-comp_5.htm">Next</A></FONT><FONT
size=3>]</FONT></P>
<P><STRONG>
<P>
<HR width="100%" SIZE=2>
<P></P></STRONG></SPAN></FONT></SPAN>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><STRONG><FONT
face="Times New Roman TUR" size=5>0.4.1 Overview</FONT></STRONG></SPAN><FONT
face="Times New Roman"> </FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><FONT
face="Times New Roman"></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><FONT
face="Times New Roman">开发一个OS,尽管绝大部分代码只需要用C/C++等高级语言就可以了,但至少和硬件相关部分的代码需要使用汇编语言,另外,由于启动部分的代码有大小限制,使用精练的汇编可以缩小目标代码的Size。另外,对于某些需要被经常调用的代码,使用汇编来写可以提高性能。所以我们必须了解汇编语言,即使你有可能并不喜欢它。</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><FONT
face="Times New Roman"></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><FONT
face="Times New Roman">如果你是计算机专业的话,在大学里你应该学习过Intel格式的8086/80386汇编,这里就不再讨论。如果我们选择的OS开发工具是GCC以及GAS的话,就必须了解AT&T汇编语言语法,因为GCC/GAS只支持这种汇编语法。</FONT></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><FONT
face="Times New Roman"></FONT> </P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><FONT
face="Times New Roman">本书不会去讨论8086/80386的汇编编程,这类的书籍很多,你可以参考它们。这里只会讨论AT&T的汇编语法,以及GCC的内嵌汇编语法。</FONT></P>
<P><STRONG>
<HR width="100%" SIZE=2>
</STRONG>
<P></P>
<P></P>
<P class=MsoNormal
style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l5 level1 lfo3"><FONT
face="Times New Roman TUR" size=5><STRONG>0.4.2 Syntax</STRONG></FONT><FONT
face="Times New Roman"> </FONT></P>
<P><STRONG><FONT face="Times New Roman TUR">1.寄存器引用</FONT></STRONG></P>
<P><FONT face="Times New Roman TUR">引用寄存器要在寄存器号前加百分号%,如“</FONT><FONT
face="Times New Roman TUR">movl %eax, %ebx”。</FONT></P>
<P><FONT face="Times New Roman TUR">80386有如下寄存器:</FONT></P>
<UL>
<LI><FONT face="Times New Roman TUR">8个32-bit寄存器
%eax,%ebx,%ecx,%edx,%edi,%esi,%ebp,%esp;</FONT>
<LI><FONT
face="Times New Roman TUR">8个16-bit寄存器,它们事实上是上面8个32-bit寄存器的低16位:%ax,%bx,%cx,%dx,%di,%si,%bp,%sp;</FONT>
<LI><FONT
face="Times New Roman TUR">8个8-bit寄存器:%ah,%al,%bh,%bl,%ch,%cl,%dh,%dl。它们事实上是寄存器%ax,%bx,%cx,%dx的高8位和低8位;</FONT>
<LI><FONT face="Times New Roman TUR">6个段寄存器:%cs(code),%ds(data),%ss(stack),
%es,%fs,%gs;</FONT>
<LI><FONT face="Times New Roman TUR">3个控制寄存器:%cr0,%cr2,%cr3;</FONT>
<LI><FONT
face="Times New Roman TUR">6个debug寄存器:%db0,%db1,%db2,%db3,%db6,%db7;</FONT>
<LI><FONT face="Times New Roman TUR">2个测试寄存器:%tr6,%tr7;</FONT>
<LI><FONT
face="Times New Roman TUR">8个浮点寄存器栈:%st(0),%st(1),%st(2),%st(3),%st(4),%st(5),%st(6),%st(7)。</FONT></LI></UL>
<P><STRONG><FONT face="Times New Roman TUR">2. 操作数顺序</FONT></STRONG></P>
<P><FONT face="Times New Roman TUR">操作数排列是从源(左)到目的(右),如“</FONT><FONT
face="Times New Roman TUR">movl %eax(源), %ebx(目的)”</FONT></P>
<P><STRONG><FONT face="Times New Roman TUR">3. 立即数</FONT></STRONG></P>
<P><FONT face="Times New Roman TUR">使用立即数,要在数前面加符号$, 如“</FONT><FONT
face="Times New Roman TUR">movl $0x04, %ebx”</FONT></P>
<P><FONT face="Times New Roman TUR">或者:</FONT></P>
<P><FONT face="Times New Roman TUR">para = 0x04</FONT></P>
<P><FONT face="Times New Roman TUR">movl $para, %ebx</FONT></P>
<P><FONT face="Times New Roman TUR">指令执行的结果是将立即数04h装入寄存器ebx。</FONT></P>
<P><STRONG><FONT face="Times New Roman TUR">4. 符号常数</FONT></STRONG></P>
<P><FONT face="Times New Roman TUR">符号常数直接引用 如</FONT></P>
<P><FONT face="Times New Roman TUR">value: .long 0x12a3f2de</FONT></P>
<P><FONT face="Times New Roman TUR">movl value , %ebx</FONT></P>
<P><FONT face="Times New Roman TUR">指令执行的结果是将常数0x12a3f2de装入寄存器ebx。</FONT></P>
<P><FONT face="Times New Roman TUR">引用符号地址在符号前加符号$, 如“</FONT><FONT
face="Times New Roman TUR">movl $value, % ebx”</FONT><FONT
face="Times New Roman TUR">则是将符号value的地址装入寄存器ebx。</FONT></P>
<P><STRONG><FONT face="Times New Roman TUR">5. 操作数的长度</FONT></STRONG></P>
<P><FONT face="Times New Roman TUR">操作数的长度用加在指令后的符号表示b(byte, 8-bit), w(word,
16-bits), l(long, 32-bits),如</FONT><FONT face="Times New Roman TUR">“movb %al,
%bl”,“</FONT><FONT face="Times New Roman TUR">movw %ax, %bx”,“</FONT><FONT
face="Times New Roman TUR">movl %eax, %ebx</FONT> ”。</P>
<P><FONT face="Times New Roman TUR">如果没有指定操作数长度的话,编译器将按照目标操作数的长度来设置。比如指令“mov
%ax, %bx”,由于目标操作数bx的长度为word,那么编译器将把此指令等同于“movw %ax, %bx”。同样道理,指令“mov $4,
%ebx”等同于指令“movl $4, %ebx”,“push %al”等同于“pushb
%al”。对于没有指定操作数长度,但编译器又无法猜测的指令,编译器将会报错,比如指令“push $4”。</FONT></P>
<P><FONT face="Times New Roman TUR"><STRONG>6. 符号扩展和零扩展指令</STRONG></FONT></P>
<P><FONT
face="Times New Roman TUR">绝大多数面向80386的AT&T汇编指令与Intel格式的汇编指令都是相同的,符号扩展指令和零扩展指令则是仅有的不同格式指令。</FONT></P>
<P><FONT
face="Times New Roman TUR">符号扩展指令和零扩展指令需要指定源操作数长度和目的操作数长度,即使在某些指令中这些操作数是隐含的。</FONT></P>
<P><FONT
face="Times New Roman TUR">在AT&T语法中,符号扩展和零扩展指令的格式为,基本部分"movs"和"movz"(对应Intel语法的movsx和movzx),后面跟上源操作数长度和目的操作数长度。movsbl意味着movs
(from)byte (to)long;movbw意味着movs (from)byte (to)word;movswl意味着movs (from)word
(to)long。对于movz指令也一样。</FONT><FONT face="Times New Roman TUR">比如指令“movsbl %al,
%edx”意味着将al寄存器的内容进行符号扩展后放置到edx寄存器中。</FONT></P>
<P><FONT face="Times New Roman TUR">其它的Intel格式的符号扩展指令还有:</FONT></P>
<UL>
<LI><FONT face="Times New Roman TUR">cbw -- sign-extend byte in %al to word in
%ax;</FONT>
<LI><FONT face="Times New Roman TUR">cwde -- sign-extend word in %ax to long
in %eax;</FONT>
<LI><FONT face="Times New Roman TUR">cwd -- sign-extend word in %ax to long in
%dx:%ax;</FONT>
<LI><FONT face="Times New Roman TUR">cdq -- sign-extend dword in %eax to quad
in %edx:%eax;</FONT></LI></UL>
<P><FONT
face="Times New Roman TUR">对应的AT&T语法的指令为cbtw,cwtl,cwtd,cltd。</FONT></P>
<P><FONT face="Times New Roman TUR"><STRONG>7. 调用和跳转指令</STRONG></FONT></P>
<P><FONT
face="Times New Roman TUR">段内调用和跳转指令为"call","ret"和"jmp",段间调用和跳转指令为"lcall","lret"和"ljmp"。</FONT></P>
<P><FONT face="Times New Roman TUR">段间调用和跳转指令的格式为“lcall/ljmp $SECTION,
$OFFSET”,而段间返回指令则为“lret $STACK-ADJUST”。</FONT></P>
<P><FONT face="Times New Roman TUR"><STRONG>8. 前缀</STRONG></FONT></P>
<P><FONT face="Times New Roman TUR">操作码前缀被用在下列的情况:</FONT></P>
<UL>
<LI><FONT face="Times New Roman TUR">字符串重复操作指令(rep,repne);</FONT>
<LI><FONT face="Times New Roman TUR">指定被操作的段(cs,ds,ss,es,fs,gs);</FONT>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -