<?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>Computer, Electron and Technology &#187; 汇编</title>
	<atom:link href="http://www.donevii.com/post/tag/%e6%b1%87%e7%bc%96/feed" rel="self" type="application/rss+xml" />
	<link>http://www.donevii.com</link>
	<description>DoneVII CET &#38; CPPLITE</description>
	<lastBuildDate>Wed, 02 Jun 2010 10:45:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>ARM在汇编代码中调用C函数</title>
		<link>http://www.donevii.com/post/828.html</link>
		<comments>http://www.donevii.com/post/828.html#comments</comments>
		<pubDate>Wed, 27 May 2009 14:38:25 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[life]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[汇编]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=828</guid>
		<description><![CDATA[对于ARM体系来说，不同语言撰写的函数之间相互调用（mix calls）遵循的是 ATPCS（ARM-Thumb Procedure Call Standard），ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回，关于ATPCS的详细... ]]></description>
			<content:encoded><![CDATA[<div style="font-size: 14px; filter: none; visibility: visible! important; word-break: break-all; line-height: normal; font-family: Arial; word-wrap: break-word;"><span style="font-size: x-small; line-height: normal;">对于<a href="http://www.donevii.com/post/tag/arm" class="st_tag internal_tag" rel="tag" title="Posts tagged with arm">ARM</a>体系来说，不同语言撰写的函数之间相互调用（mix calls）遵循的是 ATPCS（<a href="http://www.donevii.com/post/tag/arm" class="st_tag internal_tag" rel="tag" title="Posts tagged with arm">ARM</a>-Thumb Procedure Call Standard），ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回，关于ATPCS的详细内容可以查看ADS1.2 Online Books ——Developer Guide的2.1节。这篇文档要讲的是 汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回<br style="line-height: normal;" /><br style="line-height: normal;" />不同于x86的参数传递规则，ATPCS建议函数的形参不超过4个，如果形参个数少于或等于4，则形参由R0,R1,R2,R3四个寄存器进行传递；若形参个数大于4，大于4的部分必须通过堆栈进行传递。<br style="line-height: normal;" /><br style="line-height: normal;" />我们先讨论一下形参个数为4的情况.<br style="line-height: normal;" />实例1：<br style="line-height: normal;" />test_asm_args.asm<br style="line-height: normal;" />//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br style="line-height: normal;" />        IMPORT test_c_args<span class="Apple-converted-space"> </span><span style="color: #708090; line-height: normal;">;声明test_c_args函数</span><br style="line-height: normal;" />        AREA TEST_ASM, CODE, READONLY<br style="line-height: normal;" />        EXPORT test_asm_args<br style="line-height: normal;" />test_asm_args<br style="line-height: normal;" />      <span class="Apple-converted-space"> </span><span style="color: #ff0000; line-height: normal;">STR lr, [sp, #-4]!</span><span class="Apple-converted-space"> </span></span><span style="font-size: x-small; line-height: normal;"><span style="color: #708090; line-height: normal;">;保存当前lr<br style="line-height: normal;" /></span>        ldr r0,=0&#215;10      <span class="Apple-converted-space"> </span></span><span style="font-size: x-small; line-height: normal;"><span style="color: #2f4f4f; line-height: normal;"><span style="color: #708090; line-height: normal;">;参数 1</span><br style="line-height: normal;" /></span>        ldr r1,=0&#215;20        </span><span style="font-size: x-small; line-height: normal;"><span style="color: #708090; line-height: normal;">;参数 2<br style="line-height: normal;" /></span>        ldr r2,=0&#215;30        </span><span style="font-size: x-small; line-height: normal;"><span style="color: #708090; line-height: normal;">;参数 3<br style="line-height: normal;" /></span>        ldr r3,=0&#215;40      <span class="Apple-converted-space"> </span><span style="color: #708090; line-height: normal;">;参数 4</span><br style="line-height: normal;" />        bl test_c_args      </span><span style="font-size: x-small; line-height: normal;"><span style="color: #708090; line-height: normal;">;调用C函数<br style="line-height: normal;" /></span>        <span style="color: #ff0000; line-height: normal;">LDR pc, [sp], #4</span>  </span><span style="font-size: x-small; line-height: normal;"><span style="color: #708090; line-height: normal;">;将lr装进pc(返回main函数)<span class="Apple-converted-space"> </span><br style="line-height: normal;" /></span>        END<br style="line-height: normal;" />test_c_args.c<br style="line-height: normal;" />//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br style="line-height: normal;" />void test_c_args(int a,int b,int c,int d)<br style="line-height: normal;" />{<br style="line-height: normal;" />        printk(&#8220;test_c_args:\n&#8221;);<br style="line-height: normal;" />        printk(&#8220;%0x %0x %0x %0x\n&#8221;,a,b,c,d);<br style="line-height: normal;" />}<br style="line-height: normal;" />main.c<br style="line-height: normal;" />//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br style="line-height: normal;" />int main()<br style="line-height: normal;" />{<br style="line-height: normal;" />     test_asm_args();<br style="line-height: normal;" />     for(;;);<br style="line-height: normal;" />}<br style="line-height: normal;" /><br style="line-height: normal;" />程序从main函数开始执行,main调用了test_asm_args,test_asm_args调用了test_c_args,最后从test_asm_args返回main.<br style="line-height: normal;" />代码分别使用了汇编和C定义了两个函数,test_asm_args 和 test_c_args,test_asm_args调用了test_c_args,其参数的传递方式就是向R0~R3分别写入参数值，之后使用bl语句对test_c_args进行调用。其中值得注意的地方是用红色标记的语句，test_asm_args在调用test_c_args之前必须把当前的lr入栈，调用完test_c_args之后再把刚才保存在栈中的lr写回pc,这样才能返回到main函数中。<br style="line-height: normal;" /><br style="line-height: normal;" /><br style="line-height: normal;" />如果test_c_args的参数是8个呢？这种情况test_asm_args应该怎样传递参数呢？<br style="line-height: normal;" />实例2：<br style="line-height: normal;" />test_asm_args.asm<br style="line-height: normal;" />//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br style="line-height: normal;" />        IMPORT test_c_args<span class="Apple-converted-space"> </span><span style="color: #708090; line-height: normal;">;声明test_c_args函数</span><br style="line-height: normal;" />        AREA TEST_ASM, CODE, READONLY<br style="line-height: normal;" />        EXPORT test_asm_args<br style="line-height: normal;" />test_asm_args<br style="line-height: normal;" />      <span class="Apple-converted-space"> </span><span style="color: #000000; line-height: normal;">STR lr, [sp, #-4]!</span><span class="Apple-converted-space"> </span></span><span style="font-size: x-small; line-height: normal;"><span style="color: #708090; line-height: normal;">;保存当前lr<br style="line-height: normal;" /></span>       ldr r0,=0&#215;1<span class="Apple-converted-space"> </span><span style="color: #708090; line-height: normal;">;参数 1</span><br style="line-height: normal;" />       ldr r1,=0&#215;2<span class="Apple-converted-space"> </span><span style="color: #708090; line-height: normal;">;参数 2</span><br style="line-height: normal;" />       ldr r2,=0&#215;3<span class="Apple-converted-space"> </span><span style="color: #708090; line-height: normal;">;参数 3</span><br style="line-height: normal;" />       ldr r3,=0&#215;4<span class="Apple-converted-space"> </span><span style="color: #708090; line-height: normal;">;参数 4</span><br style="line-height: normal;" />      </span><span style="font-size: x-small; line-height: normal;"><span style="color: #ff0000; line-height: normal;"><span class="Apple-converted-space"> </span>ldr r4,=0&#215;8<br style="line-height: normal;" />       str r4,[sp,#-4]! ;参数 8 入栈<br style="line-height: normal;" />       ldr r4,=0&#215;7<br style="line-height: normal;" />       str r4,[sp,#-4]! ;参数 7 入栈<br style="line-height: normal;" />       ldr r4,=0&#215;6<br style="line-height: normal;" />       str r4,[sp,#-4]! ;参数 6 入栈<br style="line-height: normal;" />       ldr r4,=0&#215;5<br style="line-height: normal;" />       str r4,[sp,#-4]! ;参数 5 入栈<br style="line-height: normal;" /></span>       bl test_c_args_lots<br style="line-height: normal;" />       ADD sp, sp, #4     <span style="color: #708090; line-height: normal;">;</span><span style="color: #708090; line-height: normal;">清除栈中</span><span style="color: #708090; line-height: normal;">参数 5,本语句执行完后sp指向 参数6<span class="Apple-converted-space"> </span></span><br style="line-height: normal;" />       ADD sp, sp, #4     <span style="color: #708090; line-height: normal;">;</span><span style="color: #708090; line-height: normal;">清除栈中</span><span style="color: #708090; line-height: normal;">参数 6,本语句执行完后sp指向 参数7</span><br style="line-height: normal;" />       ADD sp, sp, #4     <span style="color: #708090; line-height: normal;">;</span><span style="color: #708090; line-height: normal;">清除栈中</span><span style="color: #708090; line-height: normal;">参数 7,本语句执行完后sp指向 参数8</span><br style="line-height: normal;" />       ADD sp, sp, #4     <span style="color: #708090; line-height: normal;">;</span><span style="color: #708090; line-height: normal;">清除栈中</span><span style="color: #708090; line-height: normal;">参数 8,本语句执行完后sp指向 lr</span><br style="line-height: normal;" />      <span class="Apple-converted-space"> </span><span style="color: #000000; line-height: normal;">LDR pc, [sp],#4</span>   <span class="Apple-converted-space"> </span></span><span style="font-size: x-small; line-height: normal;"><span style="color: #708090; line-height: normal;">;将lr装进pc(返回main函数)<span class="Apple-converted-space"> </span><br style="line-height: normal;" /></span>        END<br style="line-height: normal;" />test_c_args.c<br style="line-height: normal;" />//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br style="line-height: normal;" />void test_c_args(int a,int b,int c,int d,int e,int f,int g,int h)<br style="line-height: normal;" />{<br style="line-height: normal;" />       printk(&#8220;test_c_args_lots:\n&#8221;);<br style="line-height: normal;" />       printk(&#8220;%0x %0x %0x %0x %0x %0x %0x %0x\n&#8221;,<br style="line-height: normal;" />      <span class="Apple-converted-space"> </span><span style="color: #ff00ff; line-height: normal;"><span style="color: #333333; line-height: normal;">      <span class="Apple-converted-space"> </span></span></span>a,b,c,d,e,f,g,h);<br style="line-height: normal;" />}<br style="line-height: normal;" />main.c<br style="line-height: normal;" />//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br style="line-height: normal;" />int main()<br style="line-height: normal;" />{<br style="line-height: normal;" />     test_asm_args();<br style="line-height: normal;" />     for(;;);<br style="line-height: normal;" />}<br style="line-height: normal;" /><br style="line-height: normal;" />这部分的代码和实例1的代码大部分是相同的，不同的地方是test_c_args的参数个数和test_asm_args的参数传递方式。<br style="line-height: normal;" />在test_asm_args中，参数1～参数4还是通过R0~R3进行传递，而参数5～参数8则是通过把其压入堆栈的方式进行传递，不过要注意这四个入栈参数的入栈顺序，是以参数8-&gt;参数7-&gt;参数6-&gt;参数5的顺序入栈的。<br style="line-height: normal;" />直到调用test_c_args之前，堆栈内容如下：<br style="line-height: normal;" />sp-&gt;+&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |  参数5  |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |  参数6  |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |  参数7  |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |  参数8  |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |     lr      |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />test_c_args执行返回后，则设置sp,对之前入栈的参数进行清除，最后将lr装入pc返回main函数，在执行<span class="Apple-converted-space"> </span><span style="color: #000000; line-height: normal;">LDR pc, [sp],#4 指令之前堆栈内容如下：</span><br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |  参数5  |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |  参数6  |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |  参数7  |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |  参数8  |<br style="line-height: normal;" />sp-&gt;+&#8212;&#8212;&#8212;-+<br style="line-height: normal;" />        |     lr      |<br style="line-height: normal;" />       +&#8212;&#8212;&#8212;-+</span></div>

	<h4>相关文章</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.donevii.com/post/325.html" title="字节对齐详解(x86 + ARM) (2007-05-18)">字节对齐详解(x86 + ARM)</a> (0)</li>
	<li><a href="http://www.donevii.com/post/475.html" title="[转] 嵌入式系统中的模块动态加载技术 (2008-09-11)">[转] 嵌入式系统中的模块动态加载技术</a> (0)</li>
	<li><a href="http://www.donevii.com/post/479.html" title="[转] 嵌入式单地址空间中实现动态加载的过程 (2008-09-11)">[转] 嵌入式单地址空间中实现动态加载的过程</a> (0)</li>
	<li><a href="http://www.donevii.com/post/477.html" title="[转] 在嵌入式单地址空间OS中实现动态加载的问题 (2008-09-11)">[转] 在嵌入式单地址空间OS中实现动态加载的问题</a> (0)</li>
	<li><a href="http://www.donevii.com/post/638.html" title="RO段、RW段和ZI段 (2008-11-28)">RO段、RW段和ZI段</a> (2)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/828.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
