痞者不惧 發表於 2021-4-1 09:31:00

39 C 语言与汇编语言混合编程

<h2>参考</h2>
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body blogpost-body-html">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body">
<p>https://blog.51cto.com/13475106/category6.html及狄泰软件相关课程</p>
<p>&nbsp;</p>
<p>从下图的编译过程就可以很明显的看出可执行文件的生成过程</p>
<p>&nbsp;</p>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401092450151-1548383518.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>编译小知识<br>1.源文件编译后得到目标文件-二进制文件<br>2.不同语言可编译相同格式的目标文件<br>3.链接器负责将目标文件组装得到可执行文件</p>
<p>在这里出现的一个问题-C语言中的函数调用是如何进行的?<br>在这里需要对函数调用时栈的变化进行解释</p>
<p>&nbsp;</p>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401092514966-1240734108.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>ebp指向关键位置上半部分-高地址位置,包含了函数调用之前的信息,下部分低地址处函数调用后所使用的信息。<br>汇编语言栈的变化-执行入栈出栈的操作<br>C语言函数调用(如上图所示)-ebp指向当前栈顶,esp指向的也是栈顶,当函数返回时,将函数所使用堆空间释放,将栈顶指针寄存器位置改变,做法是将esp移动到基准位置ebp位置,之后ebp恢复之前的值(将其弹出)</p>
<p>,此时esp指向的是返回地址,结束之后esp指向参数的位置,在这里需要介绍调用约定的概念</p>
<p>&nbsp;</p>
<h3 id="h0">调用约定</h3>
<p>1.参数从右到左入栈<br>2.函数调用者负责参数的入栈出栈<br>3.函数本身根据约定使用栈中参数</p>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401092600486-270229665.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 id="h1"><code>GCC编译器使用的栈帧布局</code></h3>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401092641221-1821282783.png"></p>
<p>&nbsp;</p>
<p>&nbsp;ebp是函数调用以及函数返回的核心寄存器<br>1.ebp寄存器位当前栈帧的基准<br>2.通过ebp能够获取返回值地址、参数、局部变量等</p>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401092659407-1827289215.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;在接下来的会用实验来进行验证</p>
<p>&nbsp;</p>
<h3 id="h1">使用汇编语言编写Linux可执行程序</h3>
<p>a.定义_start标签作为程序执行的起点<br>b.通过int 0x80使用内核服务(执行系统调用)</p>
<p>&nbsp;</p>
<div class="cnblogs_Highlighter">
<pre class="brush:cpp;gutter:true;">global _start ;标签 程序入口处


    vstr    db"D.T.Software",0x0A


_start:   ;app entry
    mov edx,13
    mov ecx,vstr   ;"D.T.Software\n"
    mov ebx,1
    mov eax,4    ;sys_write
    int 0x80   

    mov ebx,0
    mov eax,1;sys_exit
    int 0x80
</pre>
</div>
<p>交互关键字<br>1.global-从汇编语言中导出符号(变量或函数)<br>2.extern-使用外部文件中定义的符号(变量或函数)</p>
<p>示例分析</p>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401092806403-1038795075.png"></p>
<p>&nbsp;</p>
<p>&nbsp;实验运行结果-在linux下编程</p>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401092822689-38433060.png"></p>
<p>&nbsp;</p>
<p>&nbsp;混合编程注意事项<br>1.相同的目标文件格式--elf格式<br>2.相同的函数调用约定--cdecl调用约定<br>3.相同的活动记录(栈帧)结构-ebp基准</p>
<h3 id="h2">实验</h3>
<p>代码-新建entry.asm、main.c、test.c<br>代码分别为</p>
<div class="cnblogs_Highlighter">
<pre class="brush:cpp;gutter:true;">;entry.asm
global _start
global vstr
global vlen
global print

extern c_func


   vstr    db    "D.T.Software", 0x0A
   vlen    dd    $ - vstr


_start:
    mov ebp, 0

    call c_func

    call exit

print:
    push ebp
    mov ebp, esp

    mov edx,
    mov ecx,
    mov ebx, 1
    mov eax, 4
    int 0x80

    pop ebp
    ret

exit:
    mov ebx, 0
    mov eax, 1
    int 0x80

main.c      
extern void print(char*, int len);
extern char vstr[];
extern int vlen;

int c_func()
{
    char* delphi = "Delphi\n";

    print(vstr, vlen);

    return 0;
}

test.c

extern void print(char*, int len);
extern char vstr[];
extern int vlen;

int c_func()
{
    char* delphi = "Delphi\n";

    print(vstr, vlen);

    return 0;
}
</pre>
</div>
<p> 运行结果-c语言与汇编<br>在这里需要使用gcc将其编译成目标文件,最后进行链接</p>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401092948335-1517058600.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3 id="h3">小结</h3>
<p>C语言与汇编语言在满足以下条件时可以混合编程<br>1.遵循相同的函数调用约定<br>2.遵循相同的目标文件格式</p>
<p><img src="https://img2020.cnblogs.com/blog/331968/202104/331968-20210401093014697-67419279.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p> </p>
<p>  </p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div><br><br>
来源:https://www.cnblogs.com/lh03061238/p/14604838.html
頁: [1]
查看完整版本: 39 C 语言与汇编语言混合编程