收藏 分享(赏)

GCC使用教程.doc

上传人:HR专家 文档编号:7542737 上传时间:2019-05-21 格式:DOC 页数:59 大小:212KB
下载 相关 举报
GCC使用教程.doc_第1页
第1页 / 共59页
GCC使用教程.doc_第2页
第2页 / 共59页
GCC使用教程.doc_第3页
第3页 / 共59页
GCC使用教程.doc_第4页
第4页 / 共59页
GCC使用教程.doc_第5页
第5页 / 共59页
点击查看更多>>
资源描述

1、GCC 使用教程目 录gcc makefile 写法 gcc_egcs 使用 gdb 使用gcc 常用选项对代码的影响 一般情况 -O 编译选项 -O2 编译选项 -fomit-frame-pointer 编译选项 -fomit-frame-pointer return 0;接下来就要用 Autoconf 及 Automake 来帮我们产生 Makefile 档了,1. 用 autoscan 产生一个 configure.in 的雏型,执行 autoscan 後会产生一个 configure.scan 的档案,我们可以用它做为 configure.in 档的蓝本。% autoscan% lsc

2、onfigure.scan hello.c2. 编辑 configure.scan 档,如下所示,并且把它的档名改成 configure.indnl Process this file with autoconf to produce a con figure script.AC_INIT(hello.c)AM_INIT_AUTOMAKE(hello, 1.0)dnl Checks for programs.AC_PROG_CCdnl Checks for libraries.dnl Checks for header files.dnl Checks for typedefs, struct

3、ures, and compiler ch aracteristics.dnl Checks for library functions.AC_OUTPUT(Makefile)3. 执行 aclocal 和 autoconf ,分别会产生 aclocal.m4 及 configure 两个档案% aclocal% autoconf% lsaclocal.m4 configure configure.in hello.c4. 编辑 Makefile.am 档,内容如下AUTOMAKE_OPTIONS= foreignbin_PROGRAMS= hellohello_SOURCES= hello.

4、c5. 执行 automake -add-missing ,Automake 会根据 Makefile.am 档产生一些档案,包含最重要的 Makefile.in% automake -add-missingautomake: configure.in: installing ./install-shautomake: configure.in: installing ./mkinstalldirsautomake: configure.in: installing ./missing6. 最後执行 ./configure ,% ./configurecreating cache ./conf

5、ig.cachechecking for a BSD compatible install. /usr/bin/in stall -cchecking whether build environment is sane. yeschecking whether make sets $MAKE. yeschecking for working aclocal. foundchecking for working autoconf. foundchecking for working automake. foundchecking for working autoheader. foundchec

6、king for working makeinfo. foundchecking for gcc. gccchecking whether the C compiler (gcc ) works. yeschecking whether the C compiler (gcc ) is a cross-co mpiler. nochecking whether we are using GNU C. yeschecking whether gcc accepts -g. yesupdating cache ./config.cachecreating ./config.statuscreati

7、ng Makefile现在你的目录下已经产生了一个 Makefile 档,下个 make 指令就可以开始编译 hello.c 成执行档,执行 ./hello 和 GNU 打声招呼吧!% makegcc -DPACKAGE=“hello“ -DVERSION=“1.0“ -I. -I. -g -O2 -c he llo.cgcc -g -O2 -o hello hello.o% ./helloHello! GNU!你还可以试试 make clean,make install,make dist 看看会有什麽结果。你也可以把产生出来的 Makefile 秀给你的老板,让他从此对你刮目相看 :-)4

8、. 一探究竟上述产生 Makefile 的过程和以往自行编写的方式非常不一样,舍弃传统自行定义 make 的规则,使用 Automake 只需用到一些已经定义好的巨集即可。我们把巨集及目标 (target)写在 Makefile.am 档内, Automake 读入 Makefile.am 档後会把这一串已经定义好的巨集展开并且产生对应的 Makefile.in 档, 然後再由 configure 这个 shell script 根据 Makefile.in 产生适合的 Makefile。在此范例中可藉由 Autoconf 及 Automake 工具所产生的档案有 configure.scan

9、、aclocal.m4 、configure 、Makefile.in,需要我们加入设定者为 configure.in 及 Makefile.am。4.1 编辑 configure.in 档Autoconf 是用来产生 configure 档的工具。configure 是一个 shell script,它可以自动设定原始程式以符合各种不同平台上 Unix 系统的特性,并且根据系统叁数及环境产生合适的 Makefile 档或是 C 的标头档 (header file),让原始程式可以很方便地在这些不同的平台上被编译出来。Autoconf 会读取 configure.in 档然後产生 config

10、ure 这个 shell script。configure.in 档的内容是一连串 GNU m4 的巨集,这些巨集经过 autoconf 处理後会变成检查系统特徵的 shell script。configure.in 内巨集的顺序并没有特别的规定,但是每一个 configure.in 档必须在所有巨集前加入 AC_INIT 巨集,然後在所有巨集的最後面加上 AC_OUTPUT 巨集。我们可先用 autoscan 扫描原始档以产生一个 configure.scan 档,再对 configure.scan 做些修改成 configure.in 档。在范例中所用到的巨集如下:dnl这个巨集後面的字不

11、会被处理,可视为注解。AC_INIT(FILE)这个巨集用来检查原始码所在的路径,autoscan 会自动产生,我们不必修改它。AM_INIT_AUTOMAKE(PACKAGE,VERSION)这是使用 Automake 所必备的巨集,PACKAGE 是我们所要产生软体套件的名称,VERSION 是版本编号。AC_PROG_CC检查系统可用的 C 编译器,如果原始程式是用 C 写的就需要这个巨集。AC_OUTPUT(FILE)设定 configure 所要产生的档案,如果是 Makefile 的话,configure 便会把它检查出来的结果带入 Makefile.in 档然後产生合适的 Mak

12、efile。实际上,我们使用 Automake 时,还须要一些其它的巨集,这些额外的巨集我们用 aclocal 来帮我们产生。执行 aclocal 会产生 aclocal.m4档,如果没有特别的用途,我们可以不必修改它,用 aclocal 所产生的巨集会告诉 Automake 怎麽做。有了 configure.in 及 aclocal.m4 两个档案後,便可以执行 autoconf 来产生 configure 档了。4.2 编辑 Makefile.am 档接下来我们要编辑 Makefile.am 档,Automake 会根据 configure.in 中的巨集把Makefile.am 转成 M

13、akefile.in 档。Makefile.am 档定义我们所要产的目标:AUTOMAKE_OPTIONS设定 automake 的选项。Automake 主要是帮助开发 GNU 软体的人员维护软体套件,所以在执行 automake 时,会检查目录下是否存在标准 GNU 软体套件中应具备的文件档案,例如 NEWS、AUTHOR 、ChangeLog 等文件档。设成 foreign 时,automake 会改用一般软体套件的标准来检查。bin_PROGRAMS定义我们所要产生的执行档档名。如果要产生多个执行档,每个档名用空白字元隔开。hello_SOURCES定义 hello 这个执行档所需要的

14、原始档。如果 hello 这个程式是由多个原始档所产生,必须把它所用到的原始档都列出来,以空白字元隔开。假设 hello 这个程式需要 hello.c、main.c、hello.h三个档案的话,则定义hello_SOURCES= hello.c main.c hello.h如果我们定义多个执行档,则对每个执行档都要定义相对的 filename_SOURCES。编辑好 Makefile.am 档,就可以用 automake -add-missing 来产生 Makefile.in。加上 -add-missing 选项是告诉 automake 顺便帮我们加入包装一个软体套件所必备的档案。Autom

15、ake 产生出来的 Makefile.in 档是完全符合 GNU Makefile 的惯例,我们只要执行 configure 这个 shell script 便可以产生合适的 Makefile 档了。4.3 使用 Makefile利用 configure 所产生的 Makefile 档有几个预设的目标可供使用,我们只拿其中几个简述如下:make all产生我们设定的目标,即此范例中的执行档。只打 make 也可以,此时会开始编译原始码,然後连结,并且产生执行档。make clean清除之前所编译的执行档及目的档 (object file, *.o)。make distclean除了清除执行档和

16、目的档外,也把 configure 所产生的 Makefile 也清除掉。make install将程式安装至系统中。如果原始码编译无误,且执行结果正确,便可以把程式安装至系统预设的执行档存放路径。如果我们用 bin_PROGRAMS 巨集的话,程式会被安装至 /usr/local/bin 这个目录。make dist将程式和相关的档案包装成一个压缩档以供散播 (distribution) 。执行完在目录下会产生一个以 PACKAGE-VERSION.tar.gz 为名称的档案。PACKAGE 和 VERSION 这两个变数是根据 configure.in 档中 AM_INIT_AUTOMAK

17、E(PACKAGE, VERSION) 的定义。在此范例中会产生hello-1.0.tar.gz 的档案。make distcheck和 make dist 类似,但是加入检查包装後的压缩档是否正常。这个目标除了把程式和相关档案包装成 tar.gz 档外,还会自动把这个压缩档解开,执行 configure,并且进行 make all 的动作,确认编译无误後,会显示这个 tar.gz 档已经准备好可供散播了。这个检查非常有用,检查过关的套件,基本上可以给任何一个具备 GNU 发展境的人去重新编译。就 hello-1.tar.gz 这个范例而言,除了在 RedHat Linux 上,在 FreeB

18、SD 2.2.x 版也可以正确地重新编译。要注意的是,利用 Autoconf 及 Automake 所产生出来的软体套件是可以在没有安装 Autoconf 及 Automake 的环境上使用的,因为 configure 是一个 shell script,它己被设计可以在一般 Unix 的 sh 这个 shell 下执行。但是如果要修改 configure.in 及 Makefile.am 档再产生新的 configure 及 Makefile.in 档时就一定要有 Autoconf 及 Automake 了。5. 相关讯息Autoconf 和 Automake 功能十分强大,你可以从它们所附的

19、 info 档找到详细的用法。你也可以从许多现存的 GNU 软体或 Open Source 软体中找到相关的 configure.in 或 Makefile.am 档,它们是学习 Autoconf 及 Automake 更多技巧的最佳范例。这篇简介只用到了 Autoconf 及 Automake 的皮毛罢了,如果你有心加入 Open Source 软体开发的行列,希望这篇文件能帮助你对产生 Makefile 有个简单的依据。其它有关开发 GNU 程式或 C 程式设计及 Makefile 的详细运用及技巧,我建议你从 GNU Coding Standards3(GNU 编码标准规定) 读起,里面

20、包含了 GNU Makefile 惯例,还有发展 GNU 软体套件的标准程序和惯例。这些 GNU 软体的线上说明文件可以在 http:/www.gnu.org/ 这个网站上找到。6. 结语经由 Autoconf 及 Automake 的辅助,产生一个 Makefile 似乎不再像以前那麽困难了,而使用 Autoconf 也使得我们在不同平台上或各家 Unix 之间散播及编译程式变得简单,这对於在 Unix 系统上开发程式的人员来说减轻了许多负担。妥善运用这些 GNU 的工具软体,可以帮助我们更容易去发展程式,而且更容易维护原始程式码。一九九八年是 Open Source 运动风起云涌的一年,许

21、多 Open Source 的软体普遍受到网路上大众的欢迎和使用。感谢所有为 Open Source 奉献的人们,也希望藉由本文能吸引更多的人加入自由 、 开放的 OpenSource 行列。About this document .轻轻松松产生 Makefile1This document was generated using the LaTeX2HTML translator Version 98.2 beta6 (August 14th, 1998) Copyright (C) 1993, 1994, 1995, 1996, Nikos Drakos, ComputerBased Le

22、arning Unit, University of Leeds.Copyright (C) 1997, 1998, Ross Moore, Mathematics Department,Macquarie University, Sydney.The command line arguments were:latex2html -split 0 -show_section_numbers automake.texThe translation was initiated by on 1999-02-11Footnotes. itle1本文件使用 ChiLaTeX 制作。. CLE2CLE (

23、Chinese Linux Extension,Linux 中文延伸套件),http:/cle.linux.org.tw/. Standards3GNU Coding Standards, Richard Stallman.gcc_egcs 使用1.使用 egcsLinux 中最重要的软件开发工具是 GCC。GCC 是 GNU 的 C 和 C+ 编译器。实际上,GCC 能够编译三种语言:C 、C+ 和 Object C(C 语言的一种面向对象扩展) 。利用 gcc 命令可同时编译并连接 C 和 C+ 源程序。#DEMO#: hello.c如果你有两个或少数几个 C 源文件,也可以方便地利用 G

24、CC 编译、连接并生成可执行文件。例如,假设你有两个源文件 main.c 和 factorial.c 两个源文件,现在要编译生成一个计算阶乘的程序。-清单 factorial.c-#include #include int factorial (int n)if (n #include int factorial (int n);int main (int argc, char *argv)int n;if (argc void main (void)cout #include static char buff 256;static char* string;int main ()printf

25、 (“Please input a string: “);gets (string);printf (“nYour string is: %sn“, string);-上面这个程序非常简单,其目的是接受用户的输入,然后将用户的输入打印出来。该程序使用了一个未经过初始化的字符串地址 string,因此,编译并运行之后,将出现 Segment Fault 错误:$ gcc -o test -g test.c$ ./testPlease input a string: asfdSegmentation fault (core dumped)为了查找该程序中出现的问题,我们利用 gdb,并按如下的步骤

26、进行:1运行 gdb bugging 命令,装入 bugging 可执行文件;2执行装入的 bugging 命令;3使用 where 命令查看程序出错的地方;4利用 list 命令查看调用 gets 函数附近的代码;5唯一能够导致 gets 函数出错的因素就是变量 string。用 print 命令查看 string 的值;6在 gdb 中,我们可以直接修改变量的值,只要将 string 取一个合法的指针值就可以了,为此,我们在第 11 行处设置断点;7程序重新运行到第 11 行处停止,这时,我们可以用 set variable 命令修改 string 的取值;8然后继续运行,将看到正确的程序

27、运行结果。gcc 常用选项对代码的影响by alert72001-12-21测试环境 redhat 6.2 前言本文讨论 gcc 的一些常用编译选项对代码的影响。当然代码变了,它的内存布局也就会变了,随之 exploit 也就要做相应的变动。gcc 的编译选项实在太多,本文检了几个最常用的选项。 演示程序alert7redhat62 alert7$ cat test.c#includevoid hi(void)printf(“hi“);int main(int argc, char *argv)hi();return 0;一般情况 一般情况alert7redhat62 alert7$ gcc

28、-o test test.calert7redhat62 alert7$ wc -c test11773 testalert7redhat62 alert7$ gdb -q test(gdb) disass mainDump of assembler code for function main:0x80483e4 : push %ebp0x80483e5 : mov %esp,%ebp0x80483e7 : call 0x80483d00x80483ec : xor %eax,%eax0x80483ee : jmp 0x80483f00x80483f0 : leave0x80483f1 :

29、retEnd of assembler dump.(gdb) disass hiDump of assembler code for function hi:0x80483d0 : push %ebp0x80483d1 : mov %esp,%ebp0x80483d3 : push $0x80484500x80483d8 : call 0x80483080x80483dd : add $0x4,%esp0x80483e0 : leave0x80483e1 : ret0x80483e2 : mov %esi,%esiEnd of assembler dump.来看看部分的内存映象(内存高址 )+

30、-+|bffffbc4| argv 的地址( 即 argv0的地址)0xbffffb84 +-+|00000001| argc 的值0xbffffb80 +-+|400309cb|main 的返回地址0xbffffb7c +-+ esp,再 pop ebp,这样即使在过程内堆栈的 esp,ebp 是不平衡的,但只要返回时候碰到 leave 指令就会平衡了,所以把 add $0x4,%esp 优化掉也是没有问题的。-O2 编译选项 -O2 编译选项-O2Optimize even more. Nearly all supported optimizations that donot involv

31、e a space-speed tradeoff are performed. Loop unrollingand function inlining are not done, for example. As compared to -O,this option increases both compilation time and the performance ofthe generated code.alert7redhat62 alert7$ gcc -O2 -o test test.calert7redhat62 alert7$ wc -c test11757 testalert7

32、redhat62 alert7$ gdb -q test(gdb) disass mainDump of assembler code for function main:0x80483d8 : push %ebp0x80483d9 : mov %esp,%ebp0x80483db : call 0x80483c80x80483e0 : xor %eax,%eax0x80483e2 : leave0x80483e3 : ret.0x80483ef : nopEnd of assembler dump.(gdb) disass hiDump of assembler code for funct

33、ion hi:0x80483c8 : push %ebp0x80483c9 : mov %esp,%ebp0x80483cb : push $0x80484400x80483d0 : call 0x80483080x80483d5 : leave0x80483d6 : ret0x80483d7 : nopEnd of assembler dump.由于程序比较简单,再优化也没有好优化的了,所以跟-O 出来的一样。-fomit-frame-pointer 编译选项 -fomit-frame-pointer 编译选项-fomit-frame-pointerDont keep the frame p

34、ointer in a register for functionsthat dont need one. This avoids the instructions to save,set up and restore frame pointers; it also makes an extraregister available in many functions. It also makesdebugging impossible on most machines.忽略帧指针。这样在程序就不需要保存,安装,和恢复 ebp 了。这样 ebp 也就是一个free 的 register 了,在函

35、数中就可以随便使用了。alert7redhat62 alert7$ gcc -fomit-frame-pointer -o test test.calert7redhat62 alert7$ wc -c test11773 testalert7redhat62 alert7$ gdb -q test(gdb) disass mainDump of assembler code for function main:0x80483e0 : call 0x80483d00x80483e5 : xor %eax,%eax0x80483e7 : jmp 0x80483f00x80483e9 : lea

36、0x0(%esi,1),%esi0x80483f0 : retEnd of assembler dump.(gdb) disass hiDump of assembler code for function hi:0x80483d0 : push $0x80484500x80483d5 : call 0x80483080x80483da : add $0x4,%esp0x80483dd : ret0x80483de : mov %esi,%esiEnd of assembler dump.在 main()和 hi()中都去掉了以下指令push %ebpmov %esp,%ebp/这两条指令安装

37、leave/这条指令恢复来看看部分的内存映象(内存高址 )+-+|bffffbc4| argv 的地址( 即 argv0的地址)0xbffffb84 +-+|00000001| argc 的值0xbffffb80 +-+|400309cb|main 的返回地址0xbffffb7c +-+|080483e5| hi()的返回地址0xbffffb78 +-+|08048450| “hi“字符串的地址0xbffffb74 +-+| |(内存低址 )没有保存上层执行环境的 ebp.-fomit-frame-pointer errno = -_res; return -1; x86内联汇编本文提供了在

38、Linux 平台上使用和构造 x86 内联汇编的概括性介绍。他介绍了内联汇编及其各种用法的基础知识,提供了一些基本的内联汇编编码指导,并解释了在 Linux 内核中内联汇编代码的一些实例。如果您是 Linux 内核的开发人员,您会发现自己经常要对与体系结构高度相关的功能进行编码或优化代码路径。您很可能是通过将汇编语言指令插入到 C 语句的中间(又称为内联汇编的一种方法)来执行这些任务的。让我们看一下 Linux 中内联汇编的特定用法。(我们将讨论限制在 IA32 汇编。 ) 简述GNU 汇编程序简述让我们首先看一下 Linux 中使用的基本汇编程序语法。GCC(用于 Linux 的 GNU C

39、 编译器)使用 AT本例中,汇编程序模板由汇编指令组成。输入操作数是充当指令输入操作数使用的 C 表达式。输出操作数是将对其执行汇编指令输出的 C 表达式。内联汇编的重要性体现在它能够灵活操作,而且可以使其输出通过 C 变量显示出来。因为它具有这种能力,所以 “asm“ 可以用作汇编指令和包含它的 C 程序之间的接口。一个非常基本但很重要的区别在于简单内联汇编只包括指令,而扩展内联汇编包括操作数。要说明这一点,考虑以下示例:内联汇编的基本要素int a=10, b;asm (“movl %1, %eax;movl %eax, %0;“:“=r“(b) /* output */:“r“(a) /

40、* input */:“%eax“); /* clobbered register */在上例中,我们使用汇编指令使 “b“ 的值等于 “a“。请注意以下几点:“b“ 是输出操作数,由 %0 引用,“a“ 是输入操作数,由 %1 引用。“r“ 是操作数的约束,它指定将变量 “a“ 和 “b“ 存储在寄存器中。请注意,输出操作数约束应该带有一个约束修饰符 “=“,指定它是输出操作数。要在 “asm“ 内使用寄存器 %eax,%eax 的前面应该再加一个 %,换句话说就是 %eax,因为 “asm“ 使用 %0、%1 等来标识变量。任何带有一个 % 的数都看作是输入输出操作数,而不认为是寄存器。第

41、三个冒号后的修饰寄存器 %eax 告诉将在 “asm“ 中修改 GCC %eax 的值,这样 GCC 就不使用该寄存器存储任何其它的值。movl %1, %eax 将 “a“ 的值移到 %eax 中,movl %eax, %0 将 %eax 的内容移到 “b“ 中。因为 “b“ 被指定成输出操作数,因此当 “asm“ 的执行完成后,它将反映出更新的值。换句话说,对 “asm“ 内 “b“ 所做的更改将在 “asm“ 外反映出来。程序模板汇编程序模板是一组插入到 C 程序中的汇编指令(可以是单个指令,也可以是一组指令) 。每条指令都应该由双引号括起,或者整组指令应该由双引号括起。每条指令还应该用

42、一个定界符结尾。 有效的定界符为新行 (n) 和分号 (;)。 n 后可以跟一个 tab(t) 作为格式化符号,增加 GCC 在汇编文件中生成的指令的可读性。 指令通过数 %0、%1 等来引用 C 表达式(指定为操作数) 。如果希望确保编译器不会在 “asm“ 内部优化指令,可以在 “asm“ 后使用关键字 “volatile“。如果程序必须与 ANSI C 兼容,则应该使用 _asm_ 和 _volatile_,而不是 asm 和 volatile。操作数C 表达式用作 “asm“ 内的汇编指令操作数。在汇编指令通过对 C 程序的 C 表达式进行操作来执行有意义的作业的情况下,操作数是内联汇

43、编的主要特性。每个操作数都由操作数约束字符串指定,后面跟用括弧括起的 C 表达式,例如:“constraint“ (C expression)。操作数约束的主要功能是确定操作数的寻址方式。可以在输入和输出部分中同时使用多个操作数。每个操作数由逗号分隔开。在汇编程序模板内部,操作数由数字引用。如果总共有 n 个操作数(包括输入和输出) ,那么第一个输出操作数的编号为 0,逐项递增,最后那个输入操作数的编号为 n-1。总操作数的数目限制在 10,如果机器描述中任何指令模式中的最大操作数数目大于 10,则使用后者作为限制。修饰寄存器列表如果 “asm“ 中的指令指的是硬件寄存器,可以告诉 GCC 我

44、们将自己使用和修改它们。这样,GCC 就不会假设它装入到这些寄存器中的值是有效值。通常不需要将输入和输出寄存器列为 clobbered,因为 GCC 知道 “asm“ 使用它们(因为它们被明确指定为约束) 。不过,如果指令使用任何其它的寄存器,无论是明确的还是隐含的(寄存器不在输入约束列表中出现,也不在输出约束列 表中出现) ,寄存器都必须被指定为修饰列表。修饰寄存器列在第三个冒号之后,其名称被指定为字符串。至于关键字,如果指令以某些不可预知且不明确的方式修改了内存,则可能将 “memory“ 关键字添加到修饰寄存器列表中。这样就告诉 GCC 不要在不同指令之间将内存值高速缓存在寄存器中。操作

45、数约束前面提到过,“asm“ 中的每个操作数都应该由操作数约束字符串描述,后面跟用括弧括起的 C 表达式。操作数约束主要是确定指令中操作数的寻址方式。约束也可以指定:是否允许操作数位于寄存器中,以及它可以包括在哪些种类的寄存器中操作数是否可以是内存引用,以及在这种情况下使用哪些种类的地址操作数是否可以是立即数约束还要求两个操作数匹配。常用约束在可用的操作数约束中,只有一小部分是常用的;下面列出了这些约束以及简要描述。有关操作数约束的完整列表,请参考 GCC 和 GAS 手册。寄存器操作数约束 (r)使用这种约束指定操作数时,它们存储在通用寄存器中。请看下例:asm (“movl %cr3, %

46、0n“ :“=r“(cr3val);这里,变量 cr3val 保存在寄存器中, %cr3 的值复制到寄存器上,cr3val 的值从该寄存器更新到内存中。指定 “r“ 约束时,GCC 可以将变量 cr3val 保存在任何可用的 GPR 中。要指定寄存器,必须通过使用特定的寄存器约束直接指定寄存器名。a %eaxb %ebxc %ecxd %edxS %esiD %edi内存操作数约束 (m)当操作数位于内存中时,任何对它们执行的操作都将在内存位置中直接发生,这与寄存器约束正好相反,后者先将值存储在要修改的寄存器中,然后将它写回内存位 置中。但寄存器约束通常只在对于指令来说它们是绝对必需的,或者它

47、们可以大大提高进程速度时使用。当需要在 “asm“ 内部更新 C 变量,而您又确实不希望使用寄存器来保存其值时,使用内存约束最为有效。例如,idtr 的值存储在内存位置 loc 中:(“sidt %0n“ : :“m“(loc);匹配(数字)约束在某些情况下,一个变量既要充当输入操作数,也要充当输出操作数。可以通过使用匹配约束在 “asm“ 中指定这种情况。asm (“incl %0“ :“=a“(var):“0“(var);在匹配约束的示例中,寄存器 %eax 既用作输入变量,也用作输出变量。将 var 输入读取到 %eax,增加后将更新的 %eax 再次存储在 var 中。这里的 “0“

48、指定第 0 个输出变量相同的约束。即,它指定 var 的输出实例只应该存储在 %eax 中。该约束可以用于以下情况:输入从变量中读取,或者变量被修改后,修改写回到同一变量中不需要将输入操作数和输出操作数的实例分开使用匹配约束最重要的意义在于它们可以导致有效地使用可用寄存器。示例一般内联汇编用法示例以下示例通过各种不同的操作数约束说明了用法。有如此多的约束以至于无法将它们一一列出,这里只列出了最经常使用的那些约束类型。寄存器约束“asm“ 和寄存器约束 “r“让我们先看一下使用寄存器约束 r 的 “asm“。我们的示例显示了 GCC 如何分配寄存器,以及它如何更新输出变量的值。int main(void)int x = 10, y;asm (“movl %1, %eax;“movl %eax, %0;“:“=r“(y) /* y is output operand */:“r“(x) /* x is input operand */:“%eax“); /* %eax is clobbered register */在该例中,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报