深入了解C语言(函数的参数传递和函数使用参数的方法).doc_第1页
深入了解C语言(函数的参数传递和函数使用参数的方法).doc_第2页
深入了解C语言(函数的参数传递和函数使用参数的方法).doc_第3页
深入了解C语言(函数的参数传递和函数使用参数的方法).doc_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

深入了解C语言(函数的参数传递和函数使用参数的方法)C语言生成的代码在执行效率上比其它高级语言都高.现在让我们来看看C语言生成的代码具体是什么样子的.当你看完本文对于C语言的了解一定会更深一步了.本文通过一个个实际案例程序来讲解C语言.研究案例一工具: Turboc C v2.0,Debug,MASM v5.0,NASM实例C程序:/* example1.c */char ch;int e_main()e_putchar(ch);目标内容:C语言调用函数的方法与细节我们使用的C编译器是16位的Turboc C v2.0,它生成的是16位的代码,比较简单,方便我们来研究.同时我们也需要用到DOS下的DEBUG来进行反汇编.由于我们很多案例中的程序并不是完整的C程序,所以Turboc下的Tlink并不能为我们生成目标程序,所以我将使用MASM中的link.exe,同时里面的也可以为我们把exe文件转换成bin文件.这个程序没有main函数,我们用e_main来代替main函数.这样我们能避开C语言对main函数进行一系列处理的代码.同样,我们也用e_putchar()来代替我们平常使用的putchar().这里e的意思就是example.没有了main函数,我们的C程序就没有了入口,所以在开始编译这段C代码之前,我还得写几行简单的汇编代码,通过它来作为我们程序的入口.; C程序的入口 start.asmBITS 16global startextern _e_mainstart:call _e_main按照C语言的习惯,所以C总的名词都要自动在前面加一个_下划线.所以,我们在C中的e_main函数,如果要在汇编中调用,就变成了_e_main函数.这段汇编代码只有一句:call _e_main,就是调用我们在C中的e_main函数这段代码我将用nasm来进行编译.生成start.objnasmw -f obj -o start.obj start.asm下面我们用Turboc C来编译这段C代码:TCC -mt -oexample1.obj -c example1.clink start.obj example1.obj,example1.exe,exe2bin example1.exe这样,我们就得到了这段C代码编译出来的机器代码文件(example1.bin)了.下面我们用DEBUG这个老DOS的工具来对example1.bin进行反汇编.DEBUG-n example1.bin-l 0-u 0xxxx:0000 CALL 0003xxxx:0003 MOV AX,000Bxxxx:0006 PUSH AXxxxx:0007 CALL 0020xxxx:000A POP CX这里看到蓝色的代码就是我们整个C程序的所生成的代码了.最开始的第一句CALL 0003是我们用nasm编译的start.asm所生成的代码.我们主要目标是研究蓝色的C语言的代码,第一句start.asm所生成的代码太简单,就是调用e_main函数.而我们的e_main函数就是蓝色代码部分.从C源程序中我们看到,我们在e_main做的就是一件事情:调用e_putchar(ch);其中ch是传给出e_putchar的参数.MOV AX,000B000B就是我们的全局变量ch所在内存的地址.C语言会把所有的全局变量在另一块内存区.C代码先把ch的地址传给AX,然后通过PUSH AX把AX的值,也就是ch的地址压入堆栈.然后再CALL 0020而0020就是e_putchar代码的地址.通过这跳语句,计算机就跳到e_putchar的代码部分去执行了.我在这里并不给出e_putchar的代码,因为我们这个案例只是研究C语言中如何传递参数给其它函数的,并不管e_putchar如何取参数.下在一个案例中,我们将研究函数如何取参数.在这里我得把CALL指令解释清楚,因为在下个研究函数如何取参数的部分中大家可能会迷惑.CALL XXXX 指令简单地或就是PUSH IPJMP XXXX它首先把当前的执行地址IP压入堆栈,然后跳转到要CALL的地址去.CALL和RET指令是配套的.RET指令等同于POP IP也就是回复CALL前的执行地址IP.正因为这样,所以你一旦使用了CALL指令,你的堆栈指针SP就会自动减2.POP CX是每个函数调用完毕后都有的必备操作.在这里它不起任何作用.可能唯一的作用就是与CALL 0020前的PUSH AX像对应.这样堆栈指针SP才能回原.好了,简单的第一个案例研究结束了.虽然就这4跳指令,但是我们已经可以看出C语言传递参数方法了.总结起来就是通过MOV AX,参数地址把参数的地址传到AX,然后PUSH AX把参数的地址压入堆栈.最后CALL 函数地址转向执行要调用的函数.最后调用完后,POP CX,恢复堆栈指针SP.研究案例二工具: Turboc C v2.0,Debug,MASM v5.0,NASM,TASM实例C程序:/* example1.c */char ch;extern void e_putchar(char c);int e_main()ch=0x44;e_putchar(ch);实例汇编程序:; eio.asm_TEXT segment byte public CODEDGROUP group _TEXTassume cs:_TEXT,ds:DGROUP,ss:DGROUPpublic _k_putchar_k_putchar proc nearpush bpmov bp,spmov ah,0ehmov bx,7hmov al,byte ptr bp+4int 10hpop bpret_k_putchar endp目标内容:C语言中函数使用参数的方法这一节我们将使用TASM用汇编来写个标准的C函数.这一节的内容大家可能在很多汇编的书籍上都看到过.讲的是C语言和汇编语言的连接方法.可能你会奇怪,我们这里已经有了MASM,NASM两个汇编编译器了,为什么还要使用TASM另外一个汇编编译器.我不知道MASM是否可以和我们的Turboc C配合,但是TASM是肯定可以和Turboc C完全配合的.毕竟它们都是Borland公司的产品,而且Turboc C中用-S生成的汇编代码是完全按照TASM中的语法而定的.这足以见Turboc C和TASM之间亲密的关系了.这个案例中我们主要并不研究C代码了.而是研究那个用汇编写的C函数.push bpmov bp,spmov ah,0ehmov bx,7hmov al,byte ptr bp+4int 10hpop bpret其中byte ptrbp+4就是我们传给e_putchar()的参数值.前一个案例中我们一直知道了C语言是把参数的地址压入堆栈的方式传给函数.所以在标准的C函数中,都是通过取堆栈里的值来读参数.标准的C函数前两行都是push bpmov bp,sp首先保存BP的值,然后把当前的堆栈指针传递给BP,我们访问传递给该函数的参数就是通过BP.而第一个参数值就放在BP+4的地址中,第二个参数值就放在BP+6,.,这样依此对应每个参数的地址.BP就是CALL调用前的IP的值.因为CALL执行的时候,系统会自动把当前的IP压入堆栈.关于这个前面一个案例中已经给出介绍.别看这个C函数是用汇编语言写的,它可是个完完整整的C函数.好了,让我们编译出来看看.TASM eio.asm eio.objTCC -mt -oexample1.obj -c example1.clink start.obj eio.obj example1.obj,example1.exe,exe2bin example1.exe好了,该是我们总结的时候了.C语言中函数访问参数的方法就是先通过P

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论