<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>fleurer &#187; MIPS</title>
	<atom:link href="http://www.fleurer-lee.com/tag/mips/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.fleurer-lee.com</link>
	<description>rage and love, story of my life.</description>
	<lastBuildDate>Thu, 02 Sep 2010 11:07:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>mips汇编入门</title>
		<link>http://www.fleurer-lee.com/2009/11/03/645538/</link>
		<comments>http://www.fleurer-lee.com/2009/11/03/645538/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 05:35:15 +0000</pubDate>
		<dc:creator>ssword</dc:creator>
				<category><![CDATA[笔记]]></category>
		<category><![CDATA[ASM]]></category>
		<category><![CDATA[MIPS]]></category>
		<category><![CDATA[trick]]></category>

		<guid isPermaLink="false">http://swdpress.cn/?p=645538</guid>
		<description><![CDATA[据说若要深入学习MIPS开发的话，《MIPS处理器设计透视》这书是必不可少的。不过若只是学习MIPS汇编，这书可能就不大合适了。汇编语言还是隐藏了CPU的很多细节，而这本书里讲的貌似就是这部分，在对汇编有所了解之后再来阅读可能要更好。
学习函数式语言的时候总是满足于看书，理解下语法语义即可，真正写的代码则少的可怜，不过确实“改变了编程的看法”，目的也算达到了。汇编就不行了，看书不够，一定得动手。所以学MIPS需要一个模拟器。pcspim应该是比较标准的了，不过感觉Mars可能要更好用（准确地说，Mars非常非常好用）。
MIPS是以优雅著称，据说即使是其竞争对手也如此认为。RISC么，32个寄存器，指令长度都一样。其中的指令大约这么三种形式：

j 1000
li $1, 10
add $1, $2,$3

差异就是各个参数的长度不同。如add指令的三个参数都只有两个位宽（0~255），每个参数表示一个寄存器。如果把指令看作函数，那参数就可以看作是有类型的。而MIPS的汇编器是很强大的（听说可以进行窥孔优化），像add $t0, $0, 10这样的指令会被汇编器翻译成addi $t0,$0,10。汇编器处理前后指令的对比可以在Mars中显示出来。
记几个helloworld吧，
求3的阶乘：

li $t0, 0
li $t1, 1
if_1:
add $t0, $t0, 1
mul $t1, $t1, $t0
bne $t0, 3, if_1

在Mars下可以看到寄存器的变化，最后$t1寄存器的值是6。
mips汇编的分支（branch）指令分b系（bne，beq，bgt等等）和j系（j, jr等），差别就是b系指令的跳转都是有条件的，而且地址在参数中指明，而j系的跳转都是无条件的。j系指令的地址长度更长，寻址范围要更大，所以远程跳转都是j。
输出Helloworld：

.text
.globl main
&#160;
main:
li $v0, 4                     # just the print syscall in SPIM
la $a0, [...]]]></description>
			<content:encoded><![CDATA[<p>据说若要深入学习MIPS开发的话，《MIPS处理器设计透视》这书是必不可少的。不过若只是学习MIPS汇编，这书可能就不大合适了。汇编语言还是隐藏了CPU的很多细节，而这本书里讲的貌似就是这部分，在对汇编有所了解之后再来阅读可能要更好。</p>
<p>学习函数式语言的时候总是满足于看书，理解下语法语义即可，真正写的代码则少的可怜，不过确实“改变了编程的看法”，目的也算达到了。汇编就不行了，看书不够，一定得动手。所以学MIPS需要一个模拟器。<a href="http://pages.cs.wisc.edu/~larus/spim.html">pcspim</a>应该是比较标准的了，不过感觉<a href="http://courses.missouristate.edu/KenVollmar/MARS/">Mars</a>可能要更好用（准确地说，Mars非常非常好用）。</p>
<p>MIPS是以优雅著称，据说即使是其竞争对手也如此认为。RISC么，32个寄存器，指令长度都一样。其中的指令大约这么三种形式：</p>

<div class="wp_syntax"><div class="code"><pre class="asm" style="font-family:monospace;">j <span style="color: #0000ff;">1000</span>
li $<span style="color: #0000ff;">1</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">10</span>
<span style="color: #00007f; font-weight: bold;">add</span> $<span style="color: #0000ff;">1</span><span style="color: #339933;">,</span> $<span style="color: #0000ff;">2</span><span style="color: #339933;">,</span>$<span style="color: #0000ff;">3</span></pre></div></div>

<p>差异就是各个参数的长度不同。如add指令的三个参数都只有两个位宽（0~255），每个参数表示一个寄存器。如果把指令看作函数，那参数就可以看作是有类型的。而MIPS的汇编器是很强大的（听说可以进行窥孔优化），像add $t0, $0, 10这样的指令会被汇编器翻译成addi $t0,$0,10。汇编器处理前后指令的对比可以在Mars中显示出来。</p>
<p>记几个helloworld吧，</p>
<p>求3的阶乘：</p>

<div class="wp_syntax"><div class="code"><pre class="asm" style="font-family:monospace;">li $t0<span style="color: #339933;">,</span> <span style="color: #0000ff;">0</span>
li $t1<span style="color: #339933;">,</span> <span style="color: #0000ff;">1</span>
if_1<span style="color: #339933;">:</span>
<span style="color: #00007f; font-weight: bold;">add</span> $t0<span style="color: #339933;">,</span> $t0<span style="color: #339933;">,</span> <span style="color: #0000ff;">1</span>
<span style="color: #00007f; font-weight: bold;">mul</span> $t1<span style="color: #339933;">,</span> $t1<span style="color: #339933;">,</span> $t0
bne $t0<span style="color: #339933;">,</span> <span style="color: #0000ff;">3</span><span style="color: #339933;">,</span> if_1</pre></div></div>

<p>在Mars下可以看到寄存器的变化，最后$t1寄存器的值是6。</p>
<p>mips汇编的分支（branch）指令分b系（bne，beq，bgt等等）和j系（j, jr等），差别就是b系指令的跳转都是有条件的，而且地址在参数中指明，而j系的跳转都是无条件的。j系指令的地址长度更长，寻址范围要更大，所以远程跳转都是j。</p>
<p>输出Helloworld：</p>

<div class="wp_syntax"><div class="code"><pre class="asm" style="font-family:monospace;"><span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl main
&nbsp;
main<span style="color: #339933;">:</span>
li $v0<span style="color: #339933;">,</span> <span style="color: #0000ff;">4</span>                     # just the print <span style="color: #000000; font-weight: bold;">syscall</span> <span style="color: #00007f; font-weight: bold;">in</span> SPIM
la $a0<span style="color: #339933;">,</span> <span style="color: #00007f; font-weight: bold;">str</span>
<span style="color: #000000; font-weight: bold;">syscall</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">.data</span>
<span style="color: #00007f; font-weight: bold;">str</span><span style="color: #339933;">:</span>
<span style="color: #339933;">.</span>asciiz <span style="color: #7f007f;">&quot;hello world&quot;</span></pre></div></div>

<p>这应该算个比较完整的汇编程序了。程序的可执行代码都是在.text段，数据在.data段。.globl指明程序的入口地址，那个:str指代的就是这段字符串的地址。字符串么，就是数组。数组不就是指针么。</p>
<p>其中这个syscall会与操作系统的不同而有差异。系统调用的号码由$v0指明，参数在$a系的寄存器中传递，返回值放回到$v0。这里调用的是spim实现的4号系统调用，即print string。</p>
<p>定义一个函数f_add，它可以将两个数相加：</p>

<div class="wp_syntax"><div class="code"><pre class="asm" style="font-family:monospace;"><span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl main
&nbsp;
f_add<span style="color: #339933;">:</span>
<span style="color: #00007f; font-weight: bold;">add</span> $v0<span style="color: #339933;">,</span> $a0<span style="color: #339933;">,</span> $a1
jr $ra
&nbsp;
main<span style="color: #339933;">:</span>
li $a0<span style="color: #339933;">,</span> <span style="color: #0000ff;">1</span>
li $a1<span style="color: #339933;">,</span> <span style="color: #0000ff;">2</span>
jal f_add
&nbsp;
<span style="color: #00007f; font-weight: bold;">add</span> $t0<span style="color: #339933;">,</span> $v0<span style="color: #339933;">,</span> $<span style="color: #0000ff;">0</span>
&nbsp;
li $v0<span style="color: #339933;">,</span> <span style="color: #0000ff;">1</span>
<span style="color: #00007f; font-weight: bold;">add</span> $a0<span style="color: #339933;">,</span> $<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> $t0
<span style="color: #000000; font-weight: bold;">syscall</span></pre></div></div>

<p>在使用jal指令的时候，它会把发生跳转的地址记录在$ra寄存器中。这样函数在结尾的时候就可以用jr返回原先的位置了。</p>
<p>使用寄存器传递参数的好处貌似就是约定了函数的调用规范，兼容性要更好。例如x86下的BASIC和C在参数传递时压栈的顺序貌似就是相反的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fleurer-lee.com/2009/11/03/645538/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>
