Ted's Blog

Happy coding

gdb使用指南(2)

thbreak ARGS'
     设置只有一次作用的硬件支持断点。ARGS用法同'hbreak'命令。这个命令
和'tbreak'命令相似,它所设置的断点只起一次作用,然后就被自动的删除。这
个命令所设置的断点需要有硬件支持。

`rbreak REGEX'
     在所有满足表达式REGEX的函数上设置断点。这个命令在所有相匹配的函数
上设置无条件断点,当这个命令完成时显示所有被设置的断点信息。这个命令设
置的断点和'break'命令设置的没有什么不同。这样你可以象操作一般的断点一
样对这个命令设置的断点进行删除,使能,使不能等操作。当调试C++程序时这
个命令在重载函数上设置断点时非常有用。

`info breakpoints [N]'
`info break [N]'
`info watchpoints [N]'
     显示所有的断点和观察点的设置表,有下列一些列

    *Breakpoint Numbers*----断点号
    *Type*----断点类型(断点或是观察点)
    *Disposition*---显示断点的状态。

    *Enabled or Disabled*---使能或不使能。'y'表示使能,'n'表示不使能。

    *Address*----地址,断点在你程序中的地址(内存地址)
    *What*---地址,断点在你程序中的行号。
     如果断点是条件断点,此命令还显示断点所需要的条件。
     带参数N的'info break'命令只显示由N指定的断点的信息。
     此命令还显示断点的运行信息(被执行过几次),这个功能在使用'ignore'
命令时很有用。你可以'ignore'一个断点许多次。使用这个命令可以查看断点
被执行了多少次。这样可以更快的找到错误。
    gdb允许你在一个地方设置多个断点。但设置相同的断点无疑是弱智的。不过
你可以使用条件断点,这样就非常有用。
   gdb有时会自动在你的程序中加入断点。这主要是gdb自己的需要。比如为了正
确的处理C语言中的'longjmp'。这些内部断点都是负值,以'-1'开始。'info
breakpoints'不会显示它们。
   不过你可以使用命令’maint info breakpoints'来查看这些断点。

`maint info breakpoints'
     使用格式和'info breakpoints'相同,显示所有的断点,无论是你设置的还是
gdb自动设置的。
     以下列的含义:

    `breakpoint'
          断点,普通断点。
    `watchpoint'
          普通观察点。

    `longjmp'
          内部断点,用于处理'longjmp'调用。

    `longjmp resume'
          内部断点,设置在'longjmp'调用的目标上。

    `until'
          'until'命令所使用的内部断点。

    `finish'
          'finish'命令所使用的内部断点。

设置观察点
==============
   你可以使用观察点来停止一个程序,当某个表达式的值改变时,观察点会将程序
停止。而不需要先指定在某个地方设置一个断点。
   由于观察点的这个特性,使观察点的使用时开销比较大,但在捕捉错误时非常有
用。特别是你不知道你的程序什么地方出了问题时。

`watch EXPR'
     这个命令使用EXPR作为表达式设置一个观察点。GDB将把表达式加入到程序中
并监视程序的运行,当表达式的值被改变时GDB就使程序停止。这个也可以被用在
SPARClite DSU提供的新的自陷工具中。当程序存取某个地址或某条指令时(这个地
址在调试寄存器中指定),DSU将产生自陷。对于数据地址DSU支持'watch'命令,然而
硬件断点寄存器只能存储两个断点地址,而且断点的类型必须相同。就是两个
'rwatch'型断点,或是两个'awatch'型断点。

`rwatch EXPR'
     设置一个观察点,当EXPR被程序读时,程序被暂停。

`awatch EXPR'
     设置一个观察点,当EXPR被读出然后被写入时程序被暂停。这个命令和'awatch'
命令合用。

`info watchpoints'
     显示所设置的观察点的列表,和'info break'命令相似。
     *注意:*在多线程的程序中,观察点的作用很有限,GDB只能观察在一个线程中
的表达式的值如果你确信表达式只被当前线程所存取,那么使用观察点才有效。GDB
不能注意一个非当前线程对表达式值的改变。

断点和异常
==============
   在一些语言中比如象GNU C++,实现了异常处理。你可以使用GDB来检查异常发生的
原因。而且GDB还可以列出在某个点上异常处理的所有过程。

`catch EXCEPTIONS'
     你可以使用这个命令来在一个被激活的异常处理句柄中设置断点。EXCEPTIONS是
一个你要抓住的异常。
     你一样可以使用'info catch'命令来列出活跃的异常处理句柄。
     现在GDB中对于异常处理由以下情况不能处理。
   * 如果你使用一个交互的函数,当函数运行结束时,GDB将象普通情况一样把控制返
回给你。如果在调用中发生了异常,这个函数将继续运行直到遇到一个断点,一个信号
或是退出运行。
   * 你不能手工产生一个异常( 即异常只能由程序运行中产生 )
   * 你不能手工设置一个异常处理句柄。
   有时'catch'命令不一定是调试异常处理的最好的方法。如果你需要知道异常产生的
确切位置,最好在异常处理句柄被调用以前设置一个断点,这样你可以检查栈的内容。
如果你在一个异常处理句柄上设置断点,那么你就不容易知道异常发生的位置和原因。
   要仅仅只在异常处理句柄被唤醒之前设置断点,你必须了解一些语言的实现细节。
比如在GNU C++中异常被一个叫'__raise_exception'的库函数所调用。这个函数的原
型是:

         /* ADDR is where the exception identifier is stored.
            ID is the exception identifier.  */
         void __raise_exception (void **ADDR, void *ID);
要使GDB在栈展开之前抓住所有的句柄,你可以在函数'__raise_exception'上设置断点。
   对于一个条件断点,由于它取决于ID的值,你可以在你程序中设置断点,当某个特
别的异常被唤醒。当有一系列异常被唤醒时,你可以使用多重条件断点来停止你的程序。

删除断点
===================
   很自然当一个断点或是一个观察点完成了它的使命后,你需要把它从程序中删去。
不然你的程序还会在相同的地方停主,给你造成干扰。使用'clear'命令来从程序中删去
一个断点。
   使用'clear'命令你可以删除指定位置的断点。使用'delete'命令你可以使用断点号
来指定要删去的断点或观察点。
   在删除断点时不需要先运行过它,GDB会忽略你刚才删去的断点。所以你可以继续运行
你的程序而不必管断点。

`clear'
     在当前选择的栈帧上清除下一个所要执行到的断点(指令级)。当你当前选择帧是栈中
最内层时使用这个命令可以很方便的删去刚才程序停止处的断点。

`clear FUNCTION'
`clear FILENAME:FUNCTION'
     删除名为FUNCITON的函数上的断点。

`clear LINENUM'
`clear FILENAME:LINENUM'
     删除以LINENUM为行号上的断点。

`delete [breakpoints] [BNUMS...]'
     删除参数所指定的断点,如果没有指定参数则删去程序中所有的断点。这个命令可以
缩写成为'd'

使断点暂时不起作用。
========================
   如果你只是想让断点一时失去作用以方便调试的话,你可以先使断点不起作用。
当你以后又想使用时可以用'enable'命令激活它们。
   你使用'enable'命令来激活断点或是观察点,使用'disable'命令来使断点或观察点
不起作用。使用'info break'或'info watch'来查看那些断点是活跃的。
   断点或观察点有四种状态:
   * 使能。当程序运行到断点处时,程序停止。使用'break'命令设置的断点一开始缺省
是使能的。
   *不使能。断点对你程序的运行没有什么影响。
   *使能一次后变为不使能。断点对你的程序运行只有一次影响,然后就自动变成不使能
状态。使用'tbreak'设置的断点一开始缺省是这个状态。
   * 使能一次自动删除。断点在起了一次作用后自动被删除。
   你可以使用以下的命令来使能或使不能一个断点或观察点。

`disable [breakpoints] [BNUMS...]'
     使由参数指定的断点或观察点变为不使能,如果没有参数的话缺省使所有断点和观察
点变为不使能。当一个断点或观察点被不使能后在被不使能前的状态被记录下来,在断点或
观察点再次被激活时,原来的状态得到继续。比如一个条件断点或一个设置了
'ignore-counts'的断点在被使不能后记录活跃时断点被执行的次数,在不使能状态下,断
点的执行次数(ignore-counts)不增加,直到断点再次被激活时,再继续计算条件
(ignore-counts)。你可以使用'disable'命令的缩写'dis'

`enable [breakpoints] [BNUMS...]'
     使能由参数指定的断点或全部断点。

`enable [breakpoints] once BNUMS...'
     功能同上条命令,只是这条命令使断点只使能一次。

`enable [breakpoints] delete BNUMS...'
     功能同上条命令,只是这条命令使被使能的断点起作用一次然后自动被删除。
     除了使用'tbreak'命令所设置的断点以外,断点被设置时都是使能的。

断点条件
===========
   最简单的断点就是当你的程序每次执行到的时候就简单将程序挂起。你也可以为断点
设置“条件”。条件只是你所使用的编程语言的一个布尔表达式,带有条件表达式的断点
在每次执行时判断计算表达式的值,当表达式值为真时才挂起程序。
   这是使用“断言”的一中形式,在这种形式中你只有在断言为真时才挂起程序。如果
在C语言中你要使断言为假时挂起程序则使用:“!表达式”。
   条件表达式对观察点也同样有效,但你并不需要它,因为观察点本身就计算一个表达式?
?
但它也许会简单一些。比如只在一个变量名上设置观察点然后设置一个条件来测试新的赋
值。
  断点条件可能有副作用(side effects)会影响程序的运行。这一点有时也是很有用的
比如来激活一个显示程序完成情况的的函数,或使用你自己的打印函数来格式化特殊的
数据结构。当在同一位置没有另一个断点设置时,结果是可预见的。(在gdb中如果在同一
个地方使用了一个断点和一个条件断点则普通断点可能先被激活。)在条件断点的应用上
有很多技巧。
   断点条件可以在设置断点的同时被设置。使用'if'命令作为'break'命令的参数。断点
条件也可以在任何时候使用'condition'命令来设置。'watch'命令不能以'if'作为参数

所以使用'condition'命令是在观察点上设置条件的唯一方法。

`condition BNUM EXPRESSION'
     把'EXPRESSIN'作为断点条件。断点用'BNUM'来指定。在你为BNUM号断点设置了条件
后,只有在条件为真时程序才被暂停。当你使用'condition'命令GDB马上同步的检查
'EXPRESSION'的值判断表达式中的符号在断点处是否有效,但GDB并不真正计算表达式
的值。

`condition BNUM'
     删除在'BNUM'号断点处的条件。使之成为一个普通断点。
   一个条件断点的特殊例子是时一个程序在执行了某句语句若干次后停止。由于这
个功能非常常用,你可以使用一个命令来直接设置它那就是'ignore count'。每个
断点都有'ignore count',缺省是零。如果'ignore count'是正的那么你的程序在
运行过断点处'count'次后被暂停。

`ignore BNUM COUNT'
     设置第BNUM号断点的'ignore count'为'COUNT'。
     如果要让断点在下次执行到时就暂停程序,那么把'COUNT'设为0.
     当你使用'continue'命令来继续你程序的执行时,你可以直接把'ignore count'
作为'continue'的参数使用。你只要直接在'continue'命令后直接跟要"ignore"的
次数就行。
     如果一个断点同时有一个ignore count和一个条件时,条件不被检查。只有当
'ignore count'为零时GDB才开始检查条件的真假。
     另外你可以用'condition'命令来获得与用‘ignore count'同样效果的断点。用法
是用类似于'$foo--<=0'的参量作为'condition'命令的参数(使用一个不停减量的变量
作为条件表达式的成员)。

断点命令列表
==================
   你可以为任一个断点或观察点指定一系列命令,当你程序执行到断点时,GDB自动执行
这些命令。例如:你可以打印一些表达式的值,或使能其他的断点。

`commands [BNUM]'
`... COMMAND-LIST ...'
`end'
     为断点号为BNUM的断点设置一个命令列表。这些命令在'...COMMAND-LIST...'中列
出使用'end'命令来表示列表的结束。
    要删除断点上设置的命令序列,你只需在'command'命令后直接跟'end'命令就可以
了。
    当不指定BNUM时,GDB缺省为最近遇到的断点或是观察点设置命令列表。
    使用回车来表示重复使用命令的特性在'...command list...'中不能使用。
    你可以使用命令列表中的命令来再次使你的程序进入运行状态。简单的在命令列表
中使用'continue'命令,或'step'命令。
    在使程序恢复执行的命令后的命令都被忽略。这是因为一旦你的程序重新运行就可
能遇到新的命令列表,那么就应该执行新的命令。防止了二义。
    如果你在命令列表中使用了'silent'命令,那么你程序在断点处停止的信息将不被
显示。这对于用一个断点然后显示一些信息,接着再继续执行很有用。但'silent'命令
只有在命令列表的开头有效。
    命令'echo','output'和'printf'允许你精确的控制显示信息,这些命令在"silent"
断点中很有用。
   例如:这个例子演示了使用断点命令列表来打印'x'的值.

     break foo if x>0
     commands
     silent
     printf "x is %d\n",x
     cont
     end
   断点命令列表的一个应用是在遇到一个buf之后改正数据然后继续调试的过程。
使用命令来修改含有错误值的变量,然后使用'continue'命令继续程序的运行。
  使用'silent'命令屏蔽输出:

     break 403
     commands
     silent
     set x = y + 4
     cont
     end

断点菜单
==============
   一些编程语言(比如象C++)允许一个函数名被多次使用(重载),以方便应用的使用。
当一个函数名被重载时,'break FUNCITON'命令向GDB提供的信息不够GDB了解你要设置
断点的确切位置。如果你了解到这个问题,你可以使用'break FUNCITONS(TYPES)'命令
来指定断点的确切位置。否则GDB会提供一个函数的选择的菜单供你选择。使用提示符
'>'来等待你的输入。开始的两个选择一般是'[0] cancel'和'[1] all'输入1则在所有
同名函数上加入断点。输入0则退出选择。
   下例为企图在重载的函数符号'String::after'上设置断点。
     (gdb) b String::after
     [0] cancel
     [1] all
     [2] file:String.cc; line number:867
     [3] file:String.cc; line number:860
     [4] file:String.cc; line number:875
     [5] file:String.cc; line number:853
     [6] file:String.cc; line number:846
     [7] file:String.cc; line number:735
     > 2 4 6
     Breakpoint 1 at 0xb26c: file String.cc, line 867.
     Breakpoint 2 at 0xb344: file String.cc, line 875.
     Breakpoint 3 at 0xafcc: file String.cc, line 846.
     Multiple breakpoints were set.
     Use the "delete" command to delete unwanted
      breakpoints.
     (gdb)

gdb使用指南(2)

程序环境
==========================
   “环境”包括了一系列的环境变量和它们的值。环境变量一般记录了一些常用的信息,
比如你的用户名,主目录,你的终端型号和你的运行程序的搜索路径。一般你可以在shell
下设置环境变量,然后这些变量被所有你所运行的程序所共享。在调试中,可以设置恰当
的环境变量而不用退出gdb.

`path DIRECTORY'
     在'PATH'环境变量前加入新的内容('PATH'提供了搜索执行文件的路径)。对于gdb和
你的程序来说你也许要设置一些专门的路径。使用':'或空格来分隔。如果DIRECTORY已经
在路径中了,这个操作将会把它移到前面。
     你可以使用串'$cmd'来代表当前路径,如果你用'.'的话,它代表你使用'path'命令
时的路径,gdb将在把DIRECTORY加入搜索路径前用'.'代替当前路径

`show paths'
     显示当前路径变量的设置情况。

`show environment [VARNAME]'
     显示某个环境变量的值。如果你不指明变量名,则gdb会显示所有的变量名和它们的
内容。environment可以被缩写成'env'

`set environment VARNAME [=] VALUE'
     设置某个环境变量的值。不过只对你所调试的程序有效。对gdb本身是不起作用的。
值可以是任何串。如果未指定值,则该变量值将被设为NULL.
看一个例子:
          set env USER = foo
     告诉一个linux程序,当它下一次运行是用户名将是'foo'

`unset environment VARNAME'
     删除某环境变量。

   注意:gdb使用'shell'环境变量所指定的shell来运行你的程序。

工作路径
================================
   当你每次用'run'命令来运行你的程序时,你的程序将继承gdb的
当前工作目录。而gdb的工作目录是从它的父进程继承而来的(一般是
shell)。但你可以自己使用'cd'命令指定工作目录。
   gdb的工作目录就是它去寻找某些文件或信息的途径。
`cd DIRECTORY'
     把gdb的工作目录设为DIRECTORY
`pwd'
     打印输出当前目录。
你程序的输入/输出
===============================
   缺省时,你的程序的输入/输出和gdb的输入/输出使用同一个终端。
gdb在它自己和你的程序之间切换来和你交互,但这会引起混乱。
`info terminal'
     显示你当前所使用的终端的类型信息。
     你可以把你程序的输入/输出重定向。
例如:
     run > outfile
运行你的程序并把你程序的标准输出写入文件outfile中。
   另一个为你程序指定输入/输出的方法是使用'tty'命令,这个命令
接受一个文件名作为参量把这个文件作为以后使用'run'命令的缺省命
令文件。它还重新为子进程设置控制终端。
例如:
     tty /dev/ttyb
指定以后用'run'命令启动的进程使用终端'/dev/ttyb'作为程序的输入
/输出,而且把这个终端设为你进程的控制终端。
   一个清楚的使用'run'命令的重定向将重新设置'tty'所设置的内容
,但不影响控制终端。   当你使用'tty'命令或在'run'命令中对输入
/输出进行重定向时,只有你当前调试的程序的输入/输出被改变了,
并不会影响到别的程序。
调试一个已经运行的程序:
====================================

`attach PROCESS-ID'
     这个命令把一个已经运行的进程(在gdb外启动)连接入gdb,以便
调试。PROCESS-ID是进程号。(UNIX中使用'ps'或'jobs -l'来查看进程)
     'attach'一般不重复。(当你打了一个以上的回车时)
   当然要使用'attach'命令的话,你的操作系统环境必须支持进程。
另外你还要有向此进程发信号的权力。
   当使用'attach'命令时,你应该先使用'file'命令来指定进程所
联系的程序源代码和符号表。   当gdb接到'attach'命令后第一件
事就是停止进程的运行,你可以使用所有gdb的命令来调试一个“连接”
的进程,就象你用'run'命令在gdb中启动它一样。如果你要进程继续运
行,使用'continue'或'c'命令就行了。
`detach'
   当你结束调试后可以使用此命令来断开进程和gdb的连接。(解除gdb
对它的控制)在这个命令执行后进程将继续执行。
   如果你在用'attach'连接一个进程后退出了gdb,或使用'run'命令执
行了另一个进程,这个被'attach'的进程将被kill掉。但缺省时,gdb会
要求你确认你是否要退出或执行一个新的进程。

结束子进程
=========================
`kill'
     Kill命令结束你程序在gdb下开的子进程
     这个命令当你想要调试(检查)一个core dump文件时更有用。gdb在调试过程中
会忽略所有的core dump。
   在一些操作系统上,一个程序当你在上面加了断点以后就不能离开gdb独立运行。
你可以用kill命令来解决这个问题。
   'kill'命令当你想重新编译和连接你的程序时也很有用。因为有些系统不允许修改
正在执行的可执行程序。这样当你再一次使用'run'命令时gdb会知道你的程序已经被改
变了,那么gdb会重新load新的符号。(而且尽量保持你当前的断点设置。
附加的进程信息
==============================
   一些操作系统提供了一个设备目录叫做'/proc'的,供检查进程映象。如果gdb被在这
样的操作系统下运行,你可以使用命令'info proc'来查询进程的信息。('info proc'命
令只在支持'procfs'的SVR4系统上有用。
`info proc'
     显示进程的概要信息。
`info proc mappings'
     报告你进程所能访问的地址范围。
`info proc times'
     你进程和子进程的开始时间,用户时间(user CPU time),和系统CPU时间。
`info proc id'
     报告有关进程id的信息。
`info proc status'
     报告你进程的一般状态信息。如果进程停止了。这个报告还包括停止的原因和收到的
信号。
`info proc all'
     显示上面这些命令返回的所有信息。
对多线程程序的调试
========================================
   一些操作系统中,一个单独的程序可以有一个以上的线程在运行。线程和进程精确的定?
?

?
?
有自己的寄存器,运行时堆栈或许还会有私有内存。
   gdb提供了以下供调试多线程的进程的功能:
   * 自动通告新线程。
   * 'thread THREADNO',一个用来在线程之间切换的命令。
   * 'info threads',一个用来查询现存线程的命令。
   * 'thread apply [THREADNO] [ALL] ARGS',一个用来向线程提供命令的命令。
   * 线程有关的断点设置。
   注意:这些特性不是在所有gdb版本都能使用,归根结底要看操作系统是否支持。
   如果你的gdb不支持这些命令,会显示出错信息:
          (gdb) info threads
          (gdb) thread 1
          Thread ID 1 not known.  Use the "info threads" command to
          see the IDs of currently known threads.
   gdb的线程级调试功能允许你观察你程序运行中所有的线程,但无论什么时候
gdb控制,总有一个“当前”线程。调试命令对“当前”进程起作用。
   一旦gdb发现了你程序中的一个新的线程,它会自动显示有关此线程的系统信
息。比如:
     [New process 35 thread 27]
不过格式和操作系统有关。
   为了调试的目的,gdb自己设置线程号。
`info threads'
     显示进程中所有的线程的概要信息。gdb按顺序显示:
       1.线程号(gdb设置)
       2.目标系统的线程标识。
       3.此线程的当前堆栈。
       一前面打'*'的线程表示是当前线程。
     例如:
     (gdb) info threads
       3 process 35 thread 27  0x34e5 in sigpause ()
       2 process 35 thread 23  0x34e5 in sigpause ()
     * 1 process 35 thread 13  main (argc=1, argv=0x7ffffff8)
         at threadtest.c:68

`thread THREADNO'
     把线程号为THREADNO的线程设为当前线程。命令行参数THREADNO是gdb内定的
线程号。你可以用'info threads'命令来查看gdb内设置的线程号。gdb显示该线程
的系统定义的标识号和线程对应的堆栈。比如:

          (gdb) thread 2
          [Switching to process 35 thread 23]
          0x34e5 in sigpause ()
     "Switching后的内容取决于你的操作系统对线程标识的定义。

`thread apply [THREADNO] [ALL]  ARGS'
     此命令让你对一个以上的线程发出相同的命令"ARGS",[THREADNO]的含义同上。
如果你要向你进程中的所有的线程发出命令使用[ALL]选项。
   无论gdb何时中断了你的程序(因为一个断点或是一个信号),它自动选择信号或
断点发生的线程为当前线程。gdb将用一个格式为'[Switching to SYSTAG]'的消息
来向你报告。
   *参见:运行和停止多线程程序。
   *参见:设置观察点

调试多进程的程序
==========================================
   gdb对调试使用'fork'系统调用产生新进程的程序没有很多支持。当一个程序开始
一个新进程时,gdb将继续对父进程进行调试,子进程将不受影响的运行。如果你在子
进程可能会执行到的地方设了断点,那么子进程将收到'SIGTRAP'信号,如果子进程没
有对这个信号进行处理的话那么缺省的处理就是使子进程终止。
   然而,如果你要一定要调试子进程的话,这儿有一个不是很麻烦的折衷的办法。在
子进程被运行起来的开头几句语句前加上一个'sleep'命令。这在调试过程中并不会引
起程序中很大的麻烦(不过你要自己注意例外的情况幺:-))。然后再使用'ps'命令列出
新开的子进程号,最后使用'attach'命令。这样就没有问题了。
  关于这一段,本人觉得实际使用上并不全是这样。我在调试程中就试过,好象不一定
能起作用,要看gdb的版本和你所使用的操作系统了。

停止和继续
***********************
   调试器的基本功能就是让你能够在程序运行时在终止之前在某些条件下停止下来,然
后再继续运行,这样的话你就可以检查当你的程序出错时你的程序究竟做了些什么。
   在gdb内部,你的程序会由于各种原因而暂时停止,比如一个信号,一个断点,或是
由于你用了'step'命令。在程序停止的时候你就可以检查和改变变量的值,设置或去掉
断点,然后继续你程序的运行。一般当程序停下来时gdb都会显示一些有关程序状态的信
息。比如象程序停止的原因,堆栈等等。如果你要了解更详细的信息,你可以使用'info
program'命令。另外,在任何时候你输入这条命令,gdb都会显示当前程序运行的状态信
息。

`info program'
     显示有关你程序状态的信息:你的程序是在运行还是停止,是什么进程,为什么停
止。

断点,观察点和异常
========================================
   断点的作用是当你程序运行到断点时,无论它在做什么都会被停止下来。对于每个断点
你都可以设置一些更高级的信息以决定断点在什么时候起作用。你可以使用'break’命令
来在你的程序中设置断点,在前面的例子中我们已经提到过一些这个命令的使用方法了。
你可以在行上,函数上,甚至在确切的地址上设置断点。在含有异常处理的语言(比如象
c++)中,你还可以在异常发生的地方设置断点。
   在SunOS 4.x,SVR4和Alpha OSF/1的设置中,你还可以在共享库中设置断点。
   观察点是一种特殊的断点。它们在你程序中某个表达式的值发生变化时起作用。你必
须使用另外一些命令来设置观察点。除了这个特性以外,你可以象对普通断点一样对观察
点进行操作--使用和普通断点操作一样的命令来对观察点使能,使不能,删除。
   你可以安排当你程序被中断时显示的程序变量。
   当你在程序中设置断点或观察点时gdb为每个断点或观察点赋一个数值.在许多对断点
操作的命令中都要使用这个数值。

设置断点
=============
   使用'break'或简写成'b'来设置断点。gdb使用环境变量$bpnum来记录你最新设置的
断点。
   你有不少方法来设置断点。
 

`break FUNCTION'
     此命令用来在某个函数上设置断点。当你使用允许函数重载的语言比如C++时,有可
能同时在几个重载的函数上设置了断点。

`break +OFFSET'
`break -OFFSET'
     在当前程序运行到的前几行或后几行设置断点。OFFSET为行号。

`break LINENUM'
     在行号为LINENUM的行上设置断点。程序在运行到此行之前停止。

`break FILENAME:LINENUM'
     在文件名为FILENAME的原文件的第LINENUM行设置断点。

`break FILENAME:FUNCTION'
     在文件名为FILENAME的原文件的名为FUNCTION的函数上设置断点。
当你的多个文件中可能含有相同的函数名时必须给出文件名。

`break *ADDRESS'
     在地址ADDRESS上设置断点,这个命令允许你在没有调试信息的程
序中设置断点。
`break'
     当'break'命令不包含任何参数时,'break'命令在当前执行到的程
序运行栈中的下一条指令上设置一个断点。除了栈底以外,这个命令使
程序在一旦从当前函数返回时停止。相似的命令是'finish',但'finish'
并不设置断点。这一点在循环语句中很有用。
     gdb在恢复执行时,至少执行一条指令。

`break ... if COND'
     这个命令设置一个条件断点,条件由COND指定;在gdb每次执行到此
断点时COND都被计算当COND的值为非零时,程序在断点处停止。这意味着
COND的值为真时程序停止。...可以为下面所说的一些参量。

`tbreak ARGS'
     设置断点为只有效一次。ARGS的使用同'break'中的参量的使用。

`hbreak ARGS'
     设置一个由硬件支持的断点。ARGS同'break'命令,设置方法也和
'break'相同。但这种断点需要由硬件支持,所以不是所有的系统上这个
命令都有效。这个命令的主要目的是用于对EPROM/ROM程序的调试。因为
这条命令可以在不改变代码的情况下设置断点。这可以同SPARCLite DSU
一起使用。当程序访问某些变量和代码时,DSU将设置“陷井”。注意:
你只能一次使用一个断点,在新设置断点时,先删除原断点。

gdb使用指南(1)

使用GDB:
   本文描述GDB,GNU的原代码调试器。(这是4.12版1994年一月,GDB版本4。16)
* 目录:
* 摘要:                        GDB的摘要
* 实例:                          一个使用实例
* 入门:                        进入和退出GDB
* 命令:                        GDB 的命令
* 运行:                        在GDB下运行程序
* 停止:                        暂停和继续执行
* 栈:                          检查堆栈
* 原文件:                      检查原文件
* 数据:                        检查数据
* 语言:                        用不同的语言来使用GDB
* 符号:                         检查符号表
* 更改:                         更改执行
* GDB的文件                     文件
* 对象                          指定调试对象
* 控制GDB                       控制
* 执行序列:                    执行一序列命令
* Emacs:                        使GDB和Emacs一起工作
* GDB的bug:
* 命令行编辑:                  行编辑
* 使用历史记录交互:
* 格式化文档:                  如何格式化和打印GDB文档
* 安装GDB :

* 索引:

GDB简介:
**************

   调试器(比如象GDB)能让你观察另一个程序在执行时的内部活动,或程序出错时
发生了什么。
   GDB主要能为你做四件事(包括为了完成这些事而附加的功能),帮助你找出程序
中的错误。
   * 运行你的程序,设置所有的能影响程序运行的东西。

   * 保证你的程序在指定的条件下停止。

   * 当你程序停止时,让你检查发生了什么。

   * 改变你的程序。那样你可以试着修正某个bug引起的问题,然后继续查找另一
     个bug.

   你可以用GDB来调试C和C++写的程序。(参考 *C 和C++)

   部分支持Modula-2和chill,但现在还没有这方面的文档。

   调试Pascal程序时,有一些功能还不能使用。

  GDB还可以用来调试FORTRAN程序,尽管现在还不支持表达式的输入,输出变量,
或类FORTRAN的词法。
* GDB是"free software",大家都可以免费拷贝。也可以为GDB增加新的功能,不
过可要遵守GNU的许可协议幺。反正我认为GNU还是比较不错的:-)
就这句话:
   Fundamentally, the General Public License is a license which says
that you have these freedoms and that you cannot take these freedoms
away from anyone else.
GDB的作者:
   Richard Stallman是GDB的始作俑者,另外还有许多别的GNU的成员。许多人
为此作出了贡献。(都是老外不提也罢,但愿他们不要来找我麻烦:-))

这里是GDB的一个例子:
        原文中是使用一个叫m4的程序。但很遗憾我找不到这个程序的原代码,
所以没有办法来按照原文来说明。不过反正是个例子,我就拿一个操作系统的
进程调度原码来说明把,原代码我会附在后面。
        首先这个程序叫os.c是一个模拟进程调度的原程序(也许是个老古董了:-))。
先说明一下如何取得包括原代码符号的可执行代码。大家有心的话可以去看一下gcc的
man文件(在shell下打man gcc)。gcc -g <原文件.c> -o <要生成的文件名>
-g 的意思是生成带原代码调试符号的可执行文件。
-o 的意思是指定可执行文件名。
(gcc 的命令行参数有一大堆,有兴趣可以自己去看看。)
(忍不住要加个注,现在应该用gcc -ggdb指定吧!因为有很多人都在问,因为除了gdb还有别的工具:-)
反正在linux下把os.c用以上方法编译连接以后就产生了可供gdb使用的可执行文件。
我用gcc -g os.c -o os,产生的可执行文档叫os.
然后打gdb os,就可进入gdb,屏幕提示:
     GDB is free software and you are welcome to distribute copies
      of it under certain conditions; type "show copying" to see
      the conditions.
     There is absolutely no warranty for GDB; type "show warranty"
      for details.

     GDB 4.16, Copyright 1995 Free Software Foundation, Inc...
 (gdb)
  (gdb)是提示符,在这提示符下可以输入命令,直到退出。(退出命令是q/Q)
为了尽量和原文档说明的命令相符,即使在本例子中没用的命令我也将演示。
首先我们可以设置gdb的屏幕大小。键入:
 (gdb)set width 70
就是把标准屏幕设为70列。
  然后让我们来设置断点。设置方法很简单:break或简单打b后面加行号或函数名
比如我们可以在main 函数上设断点:
 (gdb)break main
或(gdb)b main
 系统提示:Breakpoint 1 at 0x8049552: file os.c, line 455.
 然后我们可以运行这个程序,当程序运行到main函数时程序就会停止返回到gdb的
提示符下。运行的命令是run或r(gdb中有不少alias,可以看一下help,在gdb下打help)
run 后面可以跟参数,就是为程序指定命令行参数。
比如r abcd,则程序就会abcd以作为参数。(这里要说明的是可以用set args来指定参
数)。打入r或run后,程序就开始运行直到进入main的入口停止,显示:
Starting program: <路径>/os

Breakpoint 1, main () at os.c:455
455            Initial();
这里455 Initial();是将要执行的命令或函数。
gdb提供两种方式:1.单步进入,step into就是跟踪到函数内啦。命令是step或s
                 2.单步,next,就是简单的单步,不会进入函数。命令是next或n
这两个命令还有别的用法以后再说。
我们用n命令,键入:
(gdb)n
Success forking process# 1 ,pid is 31474

Success forking process# 2 ,pid is 31475

Success forking process# 3 ,pid is 31476

Success forking process# 4 ,pid is 31477

Success forking process# 5 ,pid is 31478

Success forking process# 6 ,pid is 31479

                Dispatching Algorithm : FIFO
********************************************************************************

            PCB#        PID     Priority        PC      State
            1           31474      24            0      WAITING
            2           31475      19            0      WAITING
            3           31476      16            0      WAITING
            4           31477      23            0      WAITING
            5           31478      22            0      WAITING
            6           31479      20            0      WAITING

******************************************************************************

CPU  :  NO process running
IO :  No process
Waiting CPU!!!  31474   31475   31476   31477   31478   31479
Waiting  IO    NONE
456            State=WAITING;
最后的一行就是下一句要执行的命令。我们现在在另一个函数上加断点。注意我们
可以用l/list命令来显示原代码。这里我们键入
(gdb)l
451     main()
452     {
453             int message;
454
455            Initial();
456            State=WAITING;
457            printf("Use Control-C to halt \n");
458            signal(SIGALRM,AlarmMessage);
459            signal(SIGINT,InteruptMessage);
460            signal(SIGUSR2,IoMessage);
(gdb) l
461            alarm(TimeSlot);
462            for(;;)
463             {
464             message=GetMessage();
465                   switch(message)
466                     {
467                             case INTERRUPT :        printf("Use Control-C t;

468                                                     break;
469                             case CHILD_IO:          WaitingIo();
470                                                     break;
显示了原代码,现在在AlarmMessage上加断点。
(gdb) b AlarmMessage
Breakpoint 2 at 0x8048ee3: file os.c, line 259.
(gdb)
然后我们继续运行程序。
(gdb)c
c或continue命令让我们继续被中断的程序。 显示:
Continuing.
Use Control-C to halt

Breakpoint 2, AlarmMessage () at os.c:259
259             ClearSignal();
注意我们下一句语句就是ClearSignal();
我们用s/step跟踪进入这个函数看看它是干什么的。
(gdb) s
ClearSignal () at os.c:227
227             signal(SIGINT,SIG_IGN);
用l命令列出原代码:
(gdb) l
222     }
223
224
225     void ClearSignal()    /* Clear other signals */
226     {
227             signal(SIGINT,SIG_IGN);
228             signal(SIGALRM,SIG_IGN);
229             signal(SIGUSR2,SIG_IGN);
230     }
231
(gdb)
我们可以用s命令继续跟踪。现在让我们来试试bt或backtrace命令。这个命令可以
显示栈中的内容。
(gdb) bt
#0  ClearSignal () at os.c:227
#1  0x8048ee8 in AlarmMessage () at os.c:259
#2  0xbffffaec in ?? ()
#3  0x80486ae in ___crt_dummy__ ()
(gdb)
大家一定能看懂显示的意思。栈顶是AlarmMessage,接下来的函数没有名字--就是
没有原代码符号。这显示了函数调用的嵌套。
好了,我们跟踪了半天还没有检查过变量的值呢。检查表达式的值的命令是p或print
格式是p <表达式>
444444让我们来找一个变量来看看。:-)
(gdb)l 1
还记得l的作用吗?l或list显示原代码符号,l或list加<行号>就显示从<行号>开始的
原代码。好了找到一个让我们来看看WaitingQueue的内容
(gdb) p WaitingQueue
$1 = {1, 2, 3, 4, 5, 6, 0}
(gdb)
WaitingQueue是一个数组,gdb还支持结构的显示,
(gdb) p Pcb
$2 = {{Pid = 0, State = 0, Prior = 0, pc = 0}, {Pid = 31474, State = 2,
    Prior = 24, pc = 0}, {Pid = 31475, State = 2, Prior = 19, pc = 0}, {
    Pid = 31476, State = 2, Prior = 16, pc = 0}, {Pid = 31477, State = 2,
    Prior = 23, pc = 0}, {Pid = 31478, State = 2, Prior = 22, pc = 0}, {
    Pid = 31479, State = 2, Prior = 20, pc = 0}}
(gdb)
这里可以对照原程序看看。
原文档里是一个调试过程,不过我想这里我已经把gdb的常用功能介绍了一遍,基本上
可以用来调试程序了。:-)

运行GDB(一些详细的说明): 
 
  前面已经提到过如何运行GDB了,现在让我们来看一些更有趣的东西。你可以在运行 
GDB时通过许多命令行参数指定大量的参数和选项,通过这个你可以在一开始就设置好 
程序运行的环境。 
  这里将要描述的命令行参数覆盖了大多数的情况,事实上在一定环境下有的并没有 
什么大用处。最通常的命令就是使用一个参数: 
 $gdb <可执行文档名> 
你还可以同时为你的执行文件指定一个core文件: 
 $gdb <可执行文件名> core 
你也可以为你要执行的文件指定一个进程号: 
 $gdb <可执行文件名> <进程号> 如:&gdb os 1234将使gdb与进程1234相联系(attach) 
除非你还有一个文件叫1234的。gdb首先检查一个core文件。 
如果你是使用一个远程终端进行远程调试的话,那如果你的终端不支持的话,你将无法 
使用第二个参数甚至没有core dump。如果你觉得开头的提示信息比较碍眼的话,你可以 
用gdb -silent。你还可以用命令行参数更加详细的控制GDB的行为。 
打入gdb -help或-h 可以得到这方面的提示。所有的参数都被按照排列的顺序传给gdb 
除非你用了-x参数。 
  当gdb开始运行时,它把任何一个不带选项前缀的参数都当作为一个可执行文件或core 
文件(或进程号)。就象在前面加了-se或-c选项。gdb把第一个前面没有选项说明的参数 
看作前面加了-se 选项,而第二个(如果有的话)看作是跟着-c选项后面的。 
  许多选项有缩写,用gdb -h可以看到。在gdb中你也可以任意的把选项名掐头去尾,只 
要保证gdb能判断唯一的一个参数就行。 
在这里我们说明一些最常用的参数选项 
-symbols <文件名>(-s <文件名>)------从<文件名>中读去符号。 
-exec <文件名>(-e <文件名>)----在合适的时候执行<文件名>来做用正确的数据与core 
 dump的作比较。 
-se <文件名>------从<文件名>中读取符号并把它作为可执行文件。 
-core <文件名>(-c <文件名>)--指定<文件名>为一个core dump 文件。 
-c <数字>----连接到进程号为<数字>,与attach命令相似。 
-command <文件名> 
-x <文件名>-----执行gdb命令,在<文件名>指定的文件中存放着一序列的gdb命令,就 
象一个批处理。 
-directory(-d) <路径>---指定路径。把<路径>加入到搜索原文件的路径中。 
-m 
-mapped---- 
   注意这个命令不是在所有的系统上都能用。如果你可以通过mmap系统调用来获得内存 
映象文件,你可以用这个命令来使gdb把你当前文件里的符号写入一个文件中,这个文件 
将存放在你的当前路径中。如果你调试的程序叫/temp/fred那么map文件就叫 
./fred.syms这样当你以后再调试这个程序时,gdb会认识到这个文件的存在,从而从这 
个文件中读取符号,而不是从可执行文件中读取。.syms与主机有关不能共享。 
-r 
-readnow---马上从符号文件中读取整个符号表,而不是使用缺省的。缺省的符号表是 
调入一部分符号,当需要时再读入一部分。这会使开始进入gdb慢一些,但可以加快以后 
的调试速度。 
 
 -m和-r一般在一起使用来建立.syms文件 
 
 
接下来再谈谈模式的设置(请听下回分解 :-)) 
附:在gdb文档里使用的调试例子我找到了在minix下有这个程序,叫m4有兴趣的 
可以自己去看看 
 

模式的选择
--------------
现在我们来聊聊gdb运行模式的选择。我们可以用许多模式来运行gdb,例如在“批模式”
或“安静模式”。这些模式都是在gdb运行时在命令行作为选项指定的。
`-nx'
`-n'
     不执行任何初始化文件中的命令。(一般初始化文件叫做`.gdbinit').一般情况下在
这些文件中的命令会在所有的命令行参数都被传给gdb后执行。

`-quiet'
`-q'
     “安静模式”。不输出介绍和版权信息。这些信息在“批模式”中也被跳过。

`-batch'
     “批模式”。在“批模式”下运行。当在命令文件中的所有命令都被成功的执行后
     gdb返回状态“0”,如果在执行过程中出错,gdb返回一个非零值。
     “批模式”在把gdb作为一个过滤器运行时很有用。比如在一台远程计算机上下载且
     执行一个程序。信息“ Program exited normally”(一般是当运行的程序正常结束
     时出现)不会在这种模式中出现。
`-cd DIRECTORY'
     把DIRECTORY作为gdb的工作目录,而非当前目录(一般gdb缺省把当前目录作为工作目
     录)。
`-fullname'
`-f'
     GNU Emacs 设置这个选项,当我们在Emacs下,把gdb作为它的一个子进程来运行时,
     Emacs告诉gdb按标准输出完整的文件名和行号,一个可视的栈内容。这个格式跟在
     文件名的后面。行号和字符重新按列排,Emacs-to-GDB界面使用\032字符作为一个
     显示一页原文件的信号。
`-b BPS'
     为远程调试设置波特率。

`-tty DEVICE'
     使用DEVICE来作为你程序的标准输入输出

`quit'
     使用'quit'命令来退出gdb,或打一个文件结束符(通常是' CTROL-D')。如果
     你没有使用表达式,gdb会正常退出,否则它会把表达式的至作为error code
     返回。

     一个中断(通常是'CTROL-c)不会导致从gdb中退出,而是结束任何一个gdb的命
     令,返回gdb的命令输入模式。一般在任何时候使用'CTROL-C'是安全的,因为
     gdb会截获它,只有当安全时,中断才会起作用。
     如果你正在用gdb控制一个被连接的进程或设备,你可以用'detach'命令来释放
     它。

Shell命令
==============
    当你偶尔要运行一些shell命令时,你不必退出调试过程,也不需要挂起它;你
    可以使用'shell'命令。

`shell COMMAND STRING'
     调用标准shell来执行'COMMAND STRING'.环境变量'SHELL'决定了那个shell被
     运行。否则gdb使用'/bin/sh'.
     'make'工具经常在开发环境中使用,所以你可以不用'shell'命令而直接打'make'

`make MAKE-ARGS'
     用指定的命令行变量来运行'make'程序,这等于使用'shell make MAKE-ARGS'
GDB 命令
************
   我们可以把一个gdb命令缩写成开头几个字母,如果这没有二意性你可以直接回车来
   运行。你还可以使用TAB键让gdb给你完成接下来的键入,或向你显示可选择的命令,
   如果有不止一个选择的话。

Command语法
==============

   一个gdb命令是一个单行的输入。长度没有限制。它一个命令开头,后面可以跟参量。
   比如命令'step'接受一个参量表示单步执行多少步。你也可以不用参量。有的命令
   不接受任何参量。

   gdb命令只要没有二意性的话就可以被缩写。另外一些缩写作为一个命令列出。在某些
   情况下二意也是允许的。比如's'是指定'step'的缩写,但还有命令'start'。你可以把
   这些缩写作为'help'命令的参量来测试它们。
   空行(直接回车)表示重复上一个命令。但有些命令不能重复比如象'run',就不会以这
   种方式重复,另外一些当不小心重复会产生严重后果的命令也不能用这种方法重复。
   'list'和'x'命令当你简单的打回车时,会建立新的变量,而不是简单的重复上一个命
   令。这样你可以方便的浏览原代码和内存。
   gdb还有一种解释RET的方法:分割长输出。这种方法就和'more'命令相似。由于这时经
   常会不小心多打回车,gdb将禁止重复当一个命令产生很长的输出时。
   任何用'#'开头一直到行尾的命令行被看作是注释。主要在命令文件中使用。

输入命令的技巧
==================
   前面已经提到过TAB键的使用。使用TAB键能让你方便的得到所要的命令。比如
在gdb中:
   (gdb)info bre <TAB>(键入info bre,后按TAB键)
   gdb能为你完成剩下的输入。它还能萎蔫提供选择的可能性。如果有两个以上可
能的话,第一次按<TAB>键,gdb会响铃提示,第二次则显示可能的选择。同样gdb
也可以为一些子命令提供快速的访问。用法与上相同。
  上例中显示
   (gdb)info breakepoints
   你也可以直接打回车,gdb就将你输入的作为命令的可能的缩写。来判断执行。
如果你打入的缩写不足以判断,那么gdb会显示一个列表,列出可能的命令。同样的
情况对于命令的参数。在显示完后gdb把你的输入拷贝到当前行以便让你继续输入。
   如果你只想看看命令的列表或选项,你可以在命令行下打M-?(就是按着ESC键
同时按SHIFT和?键)。你可以直接在命令行下打试试。
  (gdb)<M-?>
   gdb会响铃并显示所有的命令。不过这种方式好象在远程调试是不行。当有的命令
使用一个字符串时,你可以用" ' "将其括起来。这种方法在调试C++程序时特别有用。
因为C++支持函数的重载。当你要在某个有重载函数上设断点时,不得不给出函数参数
以区分不同的重载函数。这时你就应该把整个函数用" ' "括起来。比如,你要在一个
叫name的函数上设断点,而这个函数被重载了(name(int)和name(float))。你将不得
不给出参变量以区分不同的函数。使用'name(int)'和'name(float)'。这里有个技巧,
你可以在函数名前加一个" ' "符号。然后打M-?.

你可以使用help命令来得到gdb的在线帮助。

`help'
`h'
      你可以使用help或h后面不加任何参数来得到一个gdb命令类的列表。

          (gdb) help
          List of classes of commands:

          running -- Running the program
          stack -- Examining the stack
          data -- Examining data
          breakpoints -- Making program stop at certain points
          files -- Specifying and examining files
          status -- Status inquiries
          support -- Support facilities
          user-defined -- User-defined commands
          aliases -- Aliases of other commands
          obscure -- Obscure features

          Type "help" followed by a class name for a list of
          commands in that class.
          Type "help" followed by command name for full
          documentation.
          Command name abbreviations are allowed if unambiguous.
          (gdb)

`help CLASS'
     使用上面列出的help class作为help或h的参量,你可以得到单一的命令列表。
     例如显示一个'status'类的列表。

          (gdb) help status
          Status inquiries.

          List of commands:

          show -- Generic command for showing things set
           with "set"
          info -- Generic command for printing status

          Type "help" followed by command name for full
          documentation.
          Command name abbreviations are allowed if unambiguous.
          (gdb)

`help COMMAND'
     详细列出单个命令的资料。

`complete ARGS'
     列出所有以ARGS开头的命令。例如:

          complete i

     results in:

          info
          inspect
          ignore

     This is intended for use by GNU Emacs.

   除了使用'help'你还可以使用gdb的命令'info'和'show'来查询你程序的
状态,每个命令可以查询一系列的状态。这些命令以恰当的方式显示所有的
子命令。

`info'
     此命令(可以缩写为'i')用来显示你程序的状态。比如,你可以使用info
args 列出你程序所接受的命令行参数。使用info registers列出寄存器的状态。
或用info breakpoint列出在程序中设的断点。要获得详细的关于info的信息打
help info.
`set'
     这个命令用来为你的程序设置一个运行环境(使用一个表达式)。比如你
可以用set prompt $来把gdb的提示符设为$.

`show'
     与'info'相反,'show'命令用来显示gdb自身的状态。你使用'set'命令来
可以改变绝大多数由'show'显示的信息。比如使用show radix命令来显示基数。
用不带任何参变量的'set'命令你可以显示所有你可以设置的变量的值。
有三个变量是不可以用'set'命令来设置的。
`show version'
     显示gdb的版本号。如果你发现gdb有bug的话你应该在bug-reports里加
入gdb的版本号。

`show copying'
显示版权信息。

`show warranty'
显示担保信息。
在gdb下运行你的程序
**************************
   当你在gdb下运行程序时,你必须先为gdb准备好带有调试信息的可执行文档。
还可以在gdb中为你的程序设置参变量,重定向你程序的输入/输出,设置环境变
量,调试一个已经执行的程序或kill掉一个子进程。
   这里许多内容在早先的例子中都已经用到过,可以参见gdb(二)。
目录:

* 编译::                        为调试编译带调试信息的代码
* 运行::                        运行你的程序
* 参变量::                      为你的程序设置参变量
* 运行环境::                    为你的程序设置运行时环境
* 设置工作目录::                在gdb中设置程序的工作目录。
* 输入/输出::                   设定你程序的输入和输出
* 连接::                        调试一个已经运行的程序
* 结束子进程::                  Kill子进程
* 进程信息::                    附加的进程信息
* 线程::                        调试带多线程的程序
* 多进程::                   调试带多进程的程序
为调试准备带调试信息的代码
===========================
   为了高效的调试一个程序,你需要使用编译器来产生附带调试信息的可执行代码
这些调试信息存储在目标文件中;描述了变量数据类型和函数声明,在原文件代码行
和执行代码之间建立联系。
   为产生调试信息,当你使用编译器时指定'-g'选项,就可以为你的程序产生带有
调试信息的可执行代码。
   有些c编译器不支持'-g'选项和'-O'选项,那你就有麻烦了,或者有别的方法产生
带调试信息的可执行代码,要不就没办法了。
   gcc,GNU的c语言编译器支持'-g'和'-O'选项。这样你就可以产生带调试信息的且
优化过的可执行代码.
   当你使用gdb来调试一个使用'-g','-O'选项产生的程序时,千万记住编译器为了优
化你的程序重新安排了你的程序。不要为运行次序与你原来设想的不同,最简单的例子
就是当你定义了一个变量但从未使用过它时,gdb中是看不到这个变量的--因为它已经
被优化掉了。
   所以有时你不要使用'-O'选项,如果当你不用优化时产生的程序是正确的,而优化
过后变的不正确了,那么这是编译器的bug你可以向开发者提供bug-reports(包括出错
的例子)。
   早期的GUN C语言编译器允许'-gg'选项,也用来产生调试信息,gdb不再支持这种格
式的调试信息,如果你的编译器支持'-gg'选项,请不要使用它。

`run'
`r'
     使用'run'命令在gdb下启动你的程序。你必须先指定你程序的名字(用gdb的命令行
参数)或使用'file'命令,来指定文件名。如果你在一个支持多进程的环境下运行你的程
序'run'命令创建一个子进程然后加载你的程序。如果环境不支持进程,则gdb直接调到
程序的第一条命令。
   一些父进程设置的参量可以决定程序的运行。gdb提供了指定参量的途径,但你必须
在程序执行前设置好他们。你也可以在运行过程中改变它们,但每次改变只有在下一次
运行中才会体现出来。这些参量可以分为四类:
---参数
     你可以在使用'run'命令时设置,如果shell支持的话,你还可以使用通配符,或
变量代换。在UNIX系统中你可以使用'shell环境变量'来控制shell。
---环境:
     你的程序一般直接从gdb那里继承环境变量。但是你可以使用'set environment'
命令来设置专门的环境变量。
---工作目录
     你的程序还同时从gdb那里继承了工作目录,你可以使用'cd'命令在gdb中改变工作
目录。
---标准输入/输出
     你的程序一般使用与gdb所用的相似的设备来输入/输出。不过你可以为你的程序的
输入/输出进行重定向。使用'run'或'tty'命令来设置于gdb所用不同的设备。
*注意:当你使用输入/输出重定向时,你将不能使用无名管道来把你所调试的程序的输出
传给另一个程序。这样gdb会认为调试程序出错。
   当你发出'run'命令后,你的程序就开始运行。
   如果你的符号文件的时间与gdb上一次读入的不同,gdb会废弃原来的符号表并重新读
入。当前的断点不变。

GDB使用简介

1、GDB 是什么?
GDB(GNU symbolic debugger)简单地说就是一个调试工具。它是一个受通用公共许可证即GPL保护的自由软件。

2、GDB特性

象所有的调试器一样,GDB可以让你调试一个程序,包括让程序在你希望的地方停下,此时你可以查看变量,寄存器,内存及堆栈。更进一步你可以修改变量 及内存值。GDB是一个功能很强大的调试器,它可以调试多种语言。在此我们仅涉及C和C++的调试,而不包括其它语言。还有一点要说明的是,GDB是一个 调试器,而不象VC一样是一个集成环境。你可以使用一些前端工具如XXGDB,DDD等。他们都有图形化界面,因此使用更方便,但它们仅是GDB的一层外 壳。因此,你仍应熟悉GDB命令。事实上,当你使用这些图形化界面时间较长时,你才会发现熟悉GDB命令的重要性。下面我们将结合简单的例子,来介绍 GDB的一些重要的常用命令。在你调试你的程序之前,当你编译你的源程序时,不要忘了-g选项或其它相应的选项,才能将调试信息加到你要调试的程序中。例 如:gcc -g -o hello hello.c 。

3、GDB常用命令简介

GDB的命令很多,本文不会全部介绍,仅会介绍一些最常用的。在介绍之前,先介绍GDB中的一个非常有用的功能:补齐功能。它就如同Linux下 SHELL中的命令补齐一样。当你输入一个命令的前几个字符,然后输入TAB键,如果没有其它命令的前几个字符与此相同,SHELL将补齐此命令。如果有 其它命令的前几个字符与此相同,你会听到一声警告声,再输入TAB键,SHELL将所有前几个字符与此相同的命令全部列出。而GDB中的补齐功能不仅能补 齐GDB命令,而且能补齐参数。
本文将先介绍常用的命令,然后结合一个具体的例子来演示如何实际使用这些命令。下面的所有命令除了第一条启动GDB命令是在SHELL下输入的,其余 都是GDB内的命令。大部分GDB内的命令都可以仅输入前几个字符,只要不与其它指令冲突。如quit可以简写为q,因为以q打头的命令只有quit。 List可以简写为l,等等

3.1 启动GDB
你可以输入GDB来启动GDB程序。GDB程序有许多参数,在此没有必要详细介绍,但一个最为常用的还是要介绍的:如果你已经编译好一个程序,我们假设文件名为hello,你想用GDB调试它,可以输入gdb hello来启动GDB并载入你的程序。如果你仅仅启动了GDB,你必须在启动后,在GDB中再载入你的程序。

3.2 载入程序 === file
在GDB内,载入程序很简单,使用file命令。如file hello。当然,程序的路径名要正确。

退出GDB === quit
在GDB的命令方式下,输入quit,你就可以退出GDB。你也可以输入'C-d'来退出GDB。

3.3 运行程序 === run
当你在GDB中已将要调试的程序载入后,你可以用run命令来执行。如果你的程序需要参数,你可以在run指令后接着输入参数,就象你在SHELL下执行一个需要参数的命令一样。

3.4 查看程序信息 === info
info指令用来查看程序的信息,当你用help info查看帮助的话,info指令的参数足足占了两个屏幕,它的参数非常多,但大部分不常用。我用info指令最多的是用它来查看断点信息。

3.4.1 查看断点信息
info br
br是断点break的缩写,记得GDB的补齐功能吧。用这条指令,你可以得到你所设置的所有断点的详细信息。包括断点号,类型,状态,内存地址,断点在源程序中的位置等。

3.4.2 查看当前源程序
info source

3.4.3 查看堆栈信息
info stack
用这条指令你可以看清楚程序的调用层次关系。
3.4.4 查看当前的参数
info args

3.5 列出源一段源程序 === list

3.5.1 列出某个函数
list FUNCTION

3.5.2 以当前源文件的某行为中间显示一段源程序
list LINENUM

3.5.3 接着前一次继续显示
list

3.5.4 显示前一次之前的源程序
list -

3.5.5 显示另一个文件的一段程序
list FILENAME:FUNCTION 或 list FILENAME:LINENUM

3.6 设置断点 === break
现在我们将要介绍的也许是最常用和最重要的命令:设置断点。无论何时,只要你的程序已被载入,并且当前没有正在运行,你就能设置,修改,删除断点。设置断点的命令是break。有许多种设置断点的方法。如下:

3.6.1 在函数入口设置断点
break FUNCTION

3.6.2 在当前源文件的某一行上设置断点
break LINENUM

3.6.3 在另一个源文件的某一行上设置断点
break FILENAME:LINENUM

3.6.4 在某个地址上设置断点,当你调试的程序没有源程序是,这很有用
break *ADDRESS
除此之外,设置一个断点,让它只有在某些特定的条件成立时程序才会停下,我们可以称其为条件断点。这个功能很有用,尤其是当你要在一个程序会很多次执 行到的地方设置断点时。如果没有这个功能,你必须有极大的耐心,加上大量的时间,一次一次让程序断下,检查一些值,接着再让程序继续执行。事实上,大部分 的断下并不是我们所希望的,我们只希望在某些条件下让程序断下。这时,条件断点就可以大大提高你的效率,节省你的时间。条件断点的命令如下,在后面的例子 中会有示例。

3.6.5 条件断点
break ...if COND
COND是一个布尔条件表达式,语法与C语言中的一样。条件断点与一般的断点不同之处是每当程序执行到断点处,都要计算条件表达式,如果为真,程序才会断下,否则程序会一直执行下去。

3.7 其它断点操作
GDB给每个断点赋上一个整数数字,这个数字在操作断点时起到重要作用,它实际上就代表相应的断点。GDB中的断点有四种状态:
有效(Enabled)
禁止(Disabled)
一次有效(Enabled once)
有效后删除(Enabled for deletion)
在上面的四个状态有效和禁止都很好理解,禁止就是让断点暂时失效。一次有效就是当程序在此断点断下后,断点状态自动变为禁止状态。有效后删除就是当程序在此断点断下后,断点被删除。实际上,后两种状态一般不会碰到。
当你设置一个断点后,它的确省状态是有效。你可以用enable和disable指令来设置断点的状态为有效或禁止。例如,如果你想禁止2号断点,可以用下面的指令:
disable 2
相应的,如果想删除2号断点,可以有下面的指令:
delete 2

3.8 设置监视点 === watch
当你调试一个很大的程序,并且在跟踪一个关键的变量时,发现这个变量不知在哪儿被改动过,如何才能找到改动它的地方。这时你可以使用watch命令。简单地说,监视点可以让你监视某个表达式或变量,当它被读或被写时让程序断下。watch命令的用法如下:
watch EXPRESSION
watch指令是监视被写的,当你想监视某个表达式或变量被读的话,需要使用rwatch指令,具体用法是一样的。要注意的是,监视点有硬件和软件两 种方式,如果可能Linux尽可能用硬件方式,因为硬件方式在速度上要大大快于软件方式。软件方式由于要在每次执行一条指令后都要检查所要监视的值是否被 改变,因此它的执行速度会大大降低。同时它也无法设置成被读时让程序断下,因为读操作不会改变值,所以GDB无法检测到读操作。幸运的是,目前的PC机基 本都支持硬件方式。如果你想确认一下你的机器是否支持硬件,你可以在调试程序时用watch设置一个监视点,如果GDB向你显示:
Hardware watchpoint NUM: EXPR
那么你可以放心了,你的机器支持硬件方式。

3.9 检查数据
最常用的检查数据的方法是使用print命令。
print exp
print指令打印exp表达式的值。却省情况下,表达式的值的打印格式依赖于它的数据类型。但你可以用一个参数/F来选择输出的打印格式。F是一个 代表某种格式的字母,详细可参考输出格式一节。表达式可以是常量,变量,函数调用,条件表达式等。但不能打印宏定义的值。表达式exp中的变量必须是全局 变量或当前堆栈区可见的变量。否则GDB会显示象下面的一条信息:
No symbol "varible" in current context

3.10 修改变量值
在调试程序时,你可能想改变一个变量的值,看看在这种情况下会发生什么。用set指令可以修改变量的值:
set varible=value
例如你想将一个变量tmp的值赋为10,
set tmp=10

3.11 检查内存值
检查内存值的指令是x,x是examine的意思。用法如下:
x /NFU ADDR
其中N代表重复数,F代表输出格式(见2.13),U代表每个数据单位的大小。U可以去如下值:
b :字节(byte)
h :双字节数值
w :四字节数值
g :八字节数值
因此,上面的指令可以这样解释:从ADDR地址开始,以F格式显示N个U数值。例如:
x/4ub 0x4000
会以无符号十进制整数格式(u)显示四个字节(b),0x4000,0x4001,0x4002,0x4003。

3.12 输出格式
缺省情况下,输出格式依赖于它的数据类型。但你可以改变输出格式。当你使用print命令时,可以用一个参数/F来选择输出的打印格式。F可以是以下的一些值:
'x' 16进制整数格式
'd' 有符号十进制整数格式
'u' 无符号十进制整数格式
'f' 浮点数格式

3.13 单步执行指令
单步执行指令有两个step和next。Step可以让你跟踪进入一个函数,而next指令则不会进入函数。

3.14 继续执行指令
当程序被断下后,你查看了所需的信息后,你会希望程序执行下去,输入 continue, 程序会继续执行下去。

3.15 帮助指令help
在GDB中,如果想知道一条指令的用法,最方便的方法是使用help。使用方法很简单,在help后跟上指令名。例如,想知道list指令用法,输入
help list

4.一个简单的例子

上面仅是GDB常用指令的简单介绍。本节将结合一个简单的例子,向大家演示这些常用指令的具体应用。这是一个冒泡排序算法的程序,这个例子的目的仅仅是演示,并不是实际调试。将下面的源程序存为bubble.c文件,并编译好。
#include <stdio.h>

#define MAX_RECORD_NUMBER 10

int record[MAX_RECORD_NUMBER] =
{12,76,48,62,94,17,37,52,69,32};

swap(int * x , int * y )
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}

int main()
{
int i,j;
for( i = 0 ; i < MAX_RECORD_NUMBER - 1; i++ )
{
for( j = MAX_RECORD_NUMBER - 1; j > i; j--)
if( record[j] < record[j-1] )
swap(&record[j],&record[j-1]);
}

for( i = 0; i < MAX_RECORD_NUMBER -1; i++)
printf("%d ",record[i]);

printf("\n");
return 1;
}
记得在编译时用-g开关。如:gcc -g -o bubble bubble.c。你能在当前子目录下得到一个编译好的文件bubble。我们下面将以这个程序为例子向大家演示上面的指令在实际中的应用。
首先启动GDB,可以在启动的同时载入文件bubble,如:gdb bubble。也可以分两步进行,先启动GDB,执行gdb,进入GDB后,再执行file bubble。
这时可以用list指令列出源程序,list的使用比较简单,但其实在GDB中最不方便的就是看源程序,主要原因是因为GDB仅是一个文本方式的调试器,无法让你用鼠标和光标键来翻阅源程序,在这方面ddd等窗口程序有巨大的优势。
我们先来查看一下当前源程序的信息,如下:
(gdb) info source
Current source file is bubble.c
Compilation directory is /root/sample/
Located in /root/sample/bubble.c
Contains 32 lines.
Source language is c.
Compiled with stabs debugging format.
我们可以知道程序名,目录,文件大小,语言等信息。
下面我们来设置断点,我们想在函数swap出设置一个断点:
(gdb) br swap
Breakpoint 1 at 0x80483d6: file bubble.c, line 11.
br是break的简写。上面的一行是GDB告诉我们这个断点的信息,我们可以知道这个断点的断点号是1,地址是0x80483d6,它在文件bubble.c的11行。
我们再在一个行号上设一个断点,
(gdb) br 23
Breakpoint 2 at 0x804844a: file bubble.c, line 23.
我们已经设了两个断点,许多时候你会想查看一下断点的信息和状态,因此你会用到你最常使用的info指令,info br。
(gdb) info br
Num Type Disp Enb Address What
1 breakpoint keep y 0x080483d6 in swap at bubble.c:11
2 breakpoint keep y 0x0804844a in main at bubble.c:23
我用这条指令的大多数原因是想查看一下某个断点的断点号,就是第一列的数值。有时也会看一下断点的状态是enable还是disable。以上的两个断点都是y,也就是都处于enable状态。type列显示breakpoint,是因为info br指令同时也会显示watch的信息,因此用type来识别是断点breakpoint还是检查点watch。
如果你知道断点号,想删除断点很简单,例如想删除断点2,执行del 2就行了。
在程序中,断点2本来设在循环中,那样程序会频烦断下,这也许不是我们希望的。也许我们仅想在某个条件下让它断下,如想当j=5时。
(gdb) br 23 if j==5
Breakpoint 3 at 0x804844a: file bubble.c, line 23.
(gdb) info br
Num Type Disp Enb Address What
1 breakpoint keep y 0x080483d6 in swap at bubble.c:11
3 breakpoint keep y 0x0804844a in main at bubble.c:23
stop only if j == 5
注意现在的断点信息,虽然断点2被删除了,但新设的断点号没有使用2号,而是使用了3号。新设的断点是个条件断点,这从"stop only if j == 5"可以清楚的看出。
现在执行程序,输入run指令。
(gdb) run
Starting program: /root/sample/bubble

Breakpoint 1, swap (x=0x80495a4, y=0x80495a0) at bubble.c:11
11 temp = *x;
程序已经在断点1停了下来。当断点停下时,我们经常需要查看变量值。如查看x值。
(gdb) p x
$1 = (int *) 0x80495a4
GDB告诉我们x是一个指向整数的指针,指针值是0x80495a4。如果想查看指针指向的值。执行:
(gdb) p *x
$2 = 32
(gdb) p *y
$3 = 69
单步执行
(gdb) n
12 *x = *y;
查看变量temp值
(gdb) p temp
$4 = 32
(gdb) n
13 *y = temp;
(gdb) p *x
$5 = 69
现在删除断点1
(gdb) del 1
继续执行
(gdb) cont
Continuing.

Breakpoint 3, main () at bubble.c:23
23 swap(&record[j],&record[j-1]);
程序在断点3停下,记得断点3是个条件断点。要验证很简单,查看一下变量j的值是不是5。
(gdb) p j
$6 = 5
我们可以查看一下全局变量record的值,
(gdb) p record
$7 = {12, 76, 48, 62, 94, 17, 32, 37, 52, 69}
也可以查看一下变量record的地址,
(gdb) p &record
$8 = (int (*)[10]) 0x8049580
知道地址时,也可以x指令查看内存值。
(gdb) x/4uw 0x8049580
0x8049580 <record>: 12 76 48 62
上面的指令查看4个4字节数,以整数方式显示。可以看到这与reocrd值是相附的。
(gdb) x/4bb record
0x8049580 <record>: 12 0 0 0
显示4个单字节数,以字节当时显示。上面的4个字节值正好是record数组第一个整数值,因为整数是4字节,而且intel机器的数值是低字节在前。
改变变量值也很简单,如果想将reocrd数组第一个值该为1,
(gdb) set record[0]=1
看一下值是否改变了。
(gdb) p record
$10 = {1, 76, 48, 62, 94, 17, 32, 37, 52, 69}
第一个值以改成了1。

以上简单地介绍了一些常用的GDB指令,由于篇幅所限,我们无法涉及GDB所有指令及GDB其它许多功能,读者应当自己在实践中不断地学习。Linux系统中会有详细的GDB的资料,你可以用info gdb来查阅这些资料。

AT&T汇编伪指令

  最近一直在看OS方面的东西,其中要用到许多AT&T汇编,下面是在网上打到的关于它的伪指令方面的中英文对照版本。英文版本也可以输入如下命令来查看:
    info as   
    read the "Pseudo Ops" node

7 Assembler Directives
All assembler directives have names that begin with a period (‘.’). The rest
of the name is letters, usually in lower case.
This chapter discusses directives that are available regardless of the target
machine configuration for the gnu assembler. Some machine configurations provi
de additional directives. See Chapter 8 [Machine Dependencies], page 61.

7 汇编器命令
所有的汇编器命令名都由句号('.')开头。命令名的其余是字母,通常使用小写。
本章讨论可用命令,不理会gun汇编器针对目标机器配置。某些机器的配置提供附加的命令
。见第8章[机器相关性],第61页。

7.1 .abort
This directive stops the assembly immediately. It is for compatibility with ot
her assemblers. The original idea was that the assembly language source would
be piped into the assembler. If the sender of the source quit, it could use th
is directive tells as to quit also. One day .abort will not be supported.

7.1 .abort
本命令立即终止汇编过程。这是为了兼容其它的汇编器。早期的想法是汇编语言的源码会
被输送进汇编器。如果发送源码的程序要退出,它可以使用本命令通知as退出。将来可能
不再支持使用.abort


7.2 .ABORT
When producing COFF output, as accepts this directive as a synonym for ‘.abor
t’.
When producing b.out output, as accepts this directive, but ignores it.

7.2 .ABORT
当生成COFF输出时,汇编器把这条命令作为.abort接受。
当产成b.out输出时,汇编器允许使用这条命令,但忽略它。


7.3 .align abs-expr, abs-expr, abs-expr
Pad the location counter (in the current subsection) to a particular storage b
oundary. The first expression (which must be absolute) is the alignment requir
ed, as described below.
The second expression (also absolute) gives the fill value to be stored in the
padding bytes. It (and the comma) may be omitted. If it is omitted, the paddi
ng bytes are normally zero. However, on some systems, if the section is marked
as containing code and the fill value is omitted, the space is filled with no
-op instructions.
The third expression is also absolute, and is also optional. If it is present,
it is the maximum number of bytes that should be skipped by this alignment di
rective. If doing the alignment would require skipping more bytes than the spe
cified maximum, then the alignment is not done at all. You can omit the fill v
alue (the second argument) entirely by simply using two commas after the requi
red alignment; this can be useful if you want the alignment to be filled with
no-op instructions when appropriate.
The way the required alignment is specified varies from system to system. For
the a29k, hppa, m68k, m88k, w65, sparc, and Hitachi SH, and i386 using ELF for
mat, the first expression is the alignment request in bytes. For example ‘.al
ign 8’ advances the location counter until it is a multiple of 8. If the loca
tion counter is already a multiple of 8, no change is needed.
For other systems, including the i386 using a.out format, and the arm and stro
ngarm, it is the number of low-order zero bits the location counter must have
after advancement. For example ‘.align 3’ advances the location counter unti
l it a multiple of 8. If the location counter is already a multiple of 8, no c
hange is needed.
This inconsistency is due to the different behaviors of the various native ass
emblers for these systems which GAS must emulate. GAS also provides .balign an
d .p2align directives, described later, which have a consistent behavior acros
s all architectures (but are specific to GAS).


7.3 .align abs-expr, abs-expr, abs-expr
增加位置计数器(在当前的子段)使它指向规定的存储边界。第一个表达式参数(结果必须是
纯粹的数字)是必需参数:边界基准,见后面的描述。
第二个表达式参数(结果必须是纯粹的数字)给出填充字节的值,用这个值填充位置计数器
越过的地方。这个参数(和逗点)可以省略,如果省略它,填充字节的值通常是0。但在某些
系统上,如果本段标识为包含代码,而填充值被省略,则使用no-op指令填充这个空间。

第3个参数表达式的结果也必须是纯粹的数字,这个参数是可选的。如果存在第3个参数,
它代表本对齐命令允许越过字节数的最大值。如果完成这个对齐需要跳过的字节比指定的
最大值还多,则根本无法完成对齐。您可以在边界基准后简单地使用两个逗号,以省略填充
值参数(第二参数);如果您想在适当的时候,对齐操作自动使用no-op指令填充,这个方法
将非常奏效。
边界基准的定义因系统而有差异。a29k,hppa,m68k,m88k,w65,sparc,Hitachi SH,
和使用ELF格式的i386,第一个表达式是边界基准,单位是字节。例如‘.align 8’向后移
动位置计数器至8的倍数。如果地址已经是8的倍数,则无需移动。
有些其它系统,包括使用a.out格式的i386,ARM和strongarm,这代表位置计数器移动后,
计数器中连续为0的低序位数量。例如‘.align 3’向后移动位置计数器直至8的倍数(计
数器的最低的3位为0)。如果地址已经是8倍数,则无需移动。
之所以存在这样的区别,是因为GAS需要模仿各种汇编器的不同动作。GAS还提供.balign和
.p2align命令,在以后详细讲述,这两条命令在所有的机型上使用相同的动作 (但需要向
GAS明确说明机型)。


7.4 .ascii "string". . .
.ascii expects zero or more string literals (see Section 3.6.1.1 [Strings], pa
ge 19) separated by commas. It assembles each string (with no automatic traili
ng zero byte) into consecutive addresses.

7.4 .ascii "string"...
.ascii可不带参数或者带多个由逗点分开的字符串(见3.6.1.1节[Strings],第19页)。它把
汇编好的每个字符串(在字符串末不自动追加零字节)存入连续的地址。


7.5 .asciz "string". . .
.asciz is just like .ascii, but each string is followed by a zero byte. The “
z” in ‘.asciz’ stands for “zero”.

7.5 .asciz "string"...
.asciz类似与.ascii,但在每个字符串末自动追加一个零字节。‘.asciz’中的‘z’代表
“zero”。


7.6 .balign[wl] abs-expr, abs-expr, abs-expr
Pad the location counter (in the current subsection) to a particular storage b
oundary. The first expression (which must be absolute) is the alignment reques
t in bytes. For example ‘.balign 8’ advances the location counter until it i
s a multiple of 8. If the location counter is already a multiple of 8, no chan
ge is needed.
The second expression (also absolute) gives the fill value to be stored in the
padding bytes. It (and the comma) may be omitted. If it is omitted, the paddi
ng bytes are normally zero. However, on some systems, if the section is marked
as containing code and the fill value is omitted, the space is filled with no
-op instructions.
The third expression is also absolute, and is also optional. If it is present,
it is the maximum number of bytes that should be skipped by this alignment di
rective. If doing the alignment would require skipping more bytes than the spe
cified maximum, then the alignment is not done at all. You can omit the fill v
alue (the second argument) entirely by simply using two commas after the requi
red alignment; this can be useful if you want the alignment to be filled with
no-op instructions when appropriate.
The .balignw and .balignl directives are variants of the .balign directive. Th
e .balignw directive treats the fill pattern as a two byte word value. The .ba
lignl directives treats the fill pattern as a four byte longword value. For ex
ample, .balignw 4,0x368d will align to a multiple of 4. If it skips two bytes,
they will be filled in with the value 0x368d (the exact placement of the byte
s depends upon the endianness of the processor). If it skips 1 or 3 bytes, the
fill value is undefined.

7.6
.balign[wl] abs-expr, abs-expr, abs-expr
增加位置计数器(在当前子段)使它指向规定的存储边界。第一个表达式参数(结果必须是纯
粹的数字)是必需参数:边界基准,单位为字节。例如,‘.balign 8’向后移动位置计数器
直至计数器的值等于8的倍数。如果位置计数器已经是8的倍数,则无需移动。
第2个表达式参数(结果必须是纯粹的数字)给出填充字节的值,用这个值填充位置计数器越
过的地方。第2个参数(和逗点)可以省略。如果省略它,填充字节的值通常是0。但在某些
系统上,如果本段标识为包含代码,而填充值被省略,则使用no-op指令填充空白区。
第3个参数的结果也必须是纯粹的数字,这个参数是可选的。如果存在第3个参数,它代表
本对齐命令允许跳过字节数的最大值。如果完成这个对齐需要跳过的字节数比规定的最大
值还多,则根本无法完成对齐。您可以在边界基准参数后简单地使用两个逗号,以省略填充
值参数(第二参数);如果您在想在适当的时候,对齐操作自动使用no-op指令填充,本方法
将非常奏效。

.balignw和.balignl是.balign命令的变化形式。.balignw使用2个字节来填充空白区。.b
alignl使用4字节来填充。例如,.balignw 4,0x368d将地址对齐到4的倍数,如果它跳过2个
字节,GAS将使用0x368d填充这2个字节(字节的确切存放位置视处理器的存储方式而定)。
如果它跳过1或3个字节,则填充值不明确。


7.7 .byte expressions
.byte expects zero or more expressions, separated by commas. Each expression i
s assembled into the next byte.

7.7.byte expressions
.byte可不带参数或者带多个表达式参数,表达式之间由逗点分隔。每个表达式参数都被汇
编成下一个字节。


7.8 .comm symbol , length
.comm declares a common symbol named symbol. When linking, a common symbol in
one object file may be merged with a defined or common symbol of the same name
in another object file. If ld does not see a definition for the symbol–just
one or more common symbols–then it will allocate length bytes of uninitialize
d memory. length must be an absolute expression. If ld sees multiple common sy
mbols with the same name, and they do not all have the same size, it will allo
cate space using the largest size.
When using ELF, the .comm directive takes an optional third argument. This is
the desired alignment of the symbol, specified as a byte boundary (for example
, an alignment of 16 means that the least significant 4 bits of the address sh
ould be zero). The alignment must be an absolute expression, and it must be a
power of two. If ld allocates uninitialized memory for the common symbol, it w
ill use the alignment when placing the symbol. If no alignment is specified, a
s will set the alignment to the largest power of two less than or equal to the
size of the symbol, up to a maximum of 16.
The syntax for .comm differs slightly on the HPPA. The syntax is ‘symbol .com
m, length’;symbol is optional.

7.8 .comm symbol , length
.comm声明一个符号名为symbol的通用符号(common symbol)。当连接时,目标文件中的通
用符号可能被并入其它目标文件中已定义的符号,或者被并入其他目标文件中同名通用符
号。如果ld无法找到该符号的定义——只有一个或多个通用符号——则分配length个字节
的未初始化内存。Length必须是一个纯粹的表达式。如果ld发现多个同名的通用符号,并
且它们的长度不同,ld将按照它们之中最大的length值为符号分配内存。
当使用ELF格式时,.comm可以使用第3个参数。它代表符号需要对齐的边界基准(例如,边界
基准为16时意味着符号存放地址的最低4位应该是零)。第3个参数表达式结果必须是纯粹的
数字,而且一定是2的幂。当ld为通用符号分配未初始化内存时,在存放符号时要使用到这
个参数。如果没有规定边界基准,as将把边界基准设置成以2为底的该符号长度的对数,并
向下取整。最大值为16。
.comm的语法在HPPA上稍微有些不同。语法是‘symbol .comm, length’;其中参数symbol
是可选的。


7.9 .data subsection
.data tells as to assemble the following statements onto the end of the data s
ubsection numbered subsection (which is an absolute expression). If subsection
is omitted, it defaults to zero.

7.9 .data subsection
.data通知as汇编后续语句,将它们追加在编号为subsection(subsection必须是纯粹的表
达式)数据段末。如果参数subsection省略,则默认是0。


7.10 .def name
Begin defining debugging information for a symbol name; the definition extends
until the .endef directive is encountered. This directive is only observed wh
en as is configured for COFF format output; when producing b.out, ‘.def’ is
recognized, but ignored.

7.10 .def name
开始定义符号'name'的调试信息;定义区延伸至遇到.endef命令。本命令只在as被配置成C
OFF格式输出时才使用;当输出为b.out格式时,可以使用‘.def’命令,但被忽略。

7.11 .desc symbol, abs-expression
This directive sets the descriptor of the symbol (see Section 5.5 [Symbol Attr
ibutes],page 30) to the low 16 bits of an absolute expression.
The ‘.desc’ directive is not available when as is configured for COFF output
; it is only for a.out or b.out object format. For the sake of compatibility,
as accepts it, but produces no output, when configured for COFF.

7.11 .desc symbol, abs-expression
本命令用一个纯粹表达式的低16位的值设置符号symbol的描述符(见5.5[符号属性],第30页
)。当as被配置成COFF输出时,‘.desc’命令无效;它只适用于a.out或b.out目标格式。为
兼容起见,当配置为COFF时,as接受此命令,但不产生输出。


7.12 .dim
This directive is generated by compilers to include auxiliary debugging inform
ation in the symbol table. It is only permitted inside .def/.endef pairs.
‘.dim’ is only meaningful when generating COFF format output; when as is gen
erating b.out, it accepts this directive but ignores it.

7.12 .dim
这条命令由编译器生成的,以便在符号表中加入辅助调试信息。只可以在.def/.endef对之
间使用此命令。
'.dim'仅仅在生成COFF格式输出时是有意义的;当生成b.out时,as接受这条命令,但忽略它



7.13 .double flonums
.double expects zero or more flonums, separated by commas. It assembles floati
ng point numbers. The exact kind of floating point numbers emitted depends on
how as is configured. See Chapter 8 [Machine Dependencies], page 61.

7.13 .double flonums
.double后跟着零个或由逗点分开多个的浮点数。本指令汇编出浮点数字。生成的浮点数的
确切类型视as的配置而定。见第8章[机器相关性],第61页。


7.14 .eject
Force a page break at this point, when generating assembly listings.

7.14 .eject
当生成汇编清单时,强制清单页在此点中断。


7.15 .else
.else is part of the as support for conditional assembly; see Section 7.35 [.i
f], page 43. It marks the beginning of a section of code to be assembled if th
e condition for the preceding
.if was false.

7.15 .else
.else 是支持as进行的条件汇编指令之一;见7.35[.if],第43页。如果前面.if命令的条件
不成立,则表示需要汇编.else后的一段代码。


7.16 .elseif
.elseif is part of the as support for conditional assembly; see Section 7.35 [
.if],page 43. It is shorthand for beginning a new .if block that would otherwi
se fill the entire .else section.

7.16 .elseif
.elseif 是支持as进行的条件汇编指令之一。见7.35节 [.if],第43页。它可以在.esle段
中快速产生一个新的.if块。


7.17 .end
.end marks the end of the assembly file. as does not process anything in the f
ile past the .end directive.

7.17 .end
.end标记着汇编文件的结束。as不处理.end命令后的任何语句。


7.18 .endef
This directive flags the end of a symbol definition begun with .def.
‘.endef’ is only meaningful when generating COFF format output; if as is con
figured to generate b.out, it accepts this directive but ignores it.

7.18 .endef
这条命令标志着从.def开始的符号定义结束。
‘.endef’命令仅仅在生成COFF格式的输出有意义;如果as被配置为生成b.out输出,虽然a
s接受这条命令,但忽略它。


7.19 .endfunc
.endfunc marks the end of a function specified with .func.

7.19 .endfunc
.endfunc标志着一个由.func命令定义的函数的结束。


7.20 .endif
.endif is part of the as support for conditional assembly; it marks the end of
a block of code that is only assembled conditionally. See Section 7.35 [.if],
page 43.

7.20 .endif
.endif是支持as进行的条件汇编的指令之一.它标志着条件汇编代码块的结束。见7.35节[
.if],第43页。


7.21 .equ symbol, expression
This directive sets the value of symbol to expression. It is synonymous with ‘
.set’; see Section 7.68 [.set], page 53.
The syntax for equ on the HPPA is ‘symbol .equ expression’.

7.21 .equ symbol, expression
本命令把符号symbol值设置为expression。它等同与'.set'命令。见7.68[.set],第53页。

在HPPA上的equ语法是‘symbol .equ expression’。


7.22 .equiv symbol, expression
The .equiv directive is like .equ and .set, except that the assembler will sig
nal an error if symbol is already defined.
Except for the contents of the error message, this is roughly equivalent to

.ifdef SYM
.err
.endif
.equ SYM,VAL

7.22 .equiv symbol, expression
.equiv 类似与.equ & .set命令, 不同之处在于,如果符号已经定义过,as会发出错误信
号。
除了错误信息的内容之外,它大体上等价与:
.ifdef SYM
.err
.endif
.equ SYM,VAL

7.23 .err
If as assembles a .err directive, it will print an error message and, unless t
he -Z option was used, it will not generate an object file. This can be used t
o signal error an conditionally compiled code.

7.23 .err
如果as汇编一条.err命令, 将打印一条错误信息,除非使用了-Z 选项, as不会生成目标文
件。 可以在条件编译代码中使用它来发出错误信息。


7.24 .exitm
Exit early from the current macro definition. See Section 7.50 [Macro], page 4
7.

7.24 .exitm
从当前宏定义体中提前退出。见7.50 [Macro],第47页。

7.25 .extern
.extern is accepted in the source program—for compatibility with other assemb
lers—but it is ignored. as treats all undefined symbols as external.

7.25 .extern
.extern可以在源程序中使用--以便兼容其他的汇编器—但会被忽略。as将所有未定义的符
号都当作外部符号处理。


7.26 .fail expression
Generates an error or a warning. If the value of the expression is 500 or more
, as will print a warning message. If the value is less than 500, as will prin
t an error message. The message will include the value of expression. This can
occasionally be useful inside complex nested macros or conditional assembly.


7.26 .fail expression
生成一个错误(error)或警告(warning)。如果expression的值大于或等于500,as会打印一
条“警告”消息。如果expression的值小于500,as会打印一条“错误”消息。消息中包含
了expression的值。这在复杂的宏嵌套或条件汇编时偶尔用到。


7.27 .file string
.file tells as that we are about to start a new logical file. string is the ne
w file name.
In general, the filename is recognized whether or not it is surrounded by quot
es ‘"’; but if you wish to specify an empty file name, you must give the quo
tes–"". This statement may go away in future: it is only recognized to be com
patible with old as programs. In some configurations of as, .file has already
been removed to avoid conflicts with other assemblers. See Chapter 8 [Machine
Dependencies], page 61.

7.27 .file string
.file 通告as我们准备开启一个新的逻辑文件。 string 是新文件名。总的来说,文件名
是否使用引号‘"’都可以;但如果您希望规定一个空文件名时,必须使用引号-""。本语
句将来可能不再使用—允许使用它只是为了与旧版本的as程序兼容。在as的一些配置中,
已经删除了.file以避免与其它的汇编器冲突。见第8章 [Machine Dependencies], 第61页



7.28 .fill repeat , size , value
repeat, size and value are absolute expressions. This emits repeat copies of s
ize bytes. Repeat may be zero or more. Size may be zero or more, but if it is
more than 8, then it is deemed to have the value 8, compatible with other peop
le’s assemblers. The contents of each repeat bytes are taken from an 8-byte n
umber. The highest order 4 bytes are zero. The lowest order 4 bytes are value
rendered in the byte-order of an integer on the computer as is assembling for.
Each size bytes in a repetition is taken from the lowest order size bytes of
this number. Again, this bizarre behavior is compatible with other people’s a
ssemblers.
size and value are optional. If the second comma and value are absent, value i
s assumed zero. If the first comma and following tokens are absent, size is as
sumed to be 1.

7.28 .fill repeat , size , value
repeat, size 和value都必须是纯粹的表达式。本命令生成size个字节的repeat个副本。
Repeat可以是0或更大的值。Size 可以是0或更大的值, 但即使size大于8,也被视作8,以
兼容其它的汇编器。各个副本中的内容取自一个8字节长的数。最高4个字节为零,最低的
4个字节是value,它以as正在汇编的目标计算机的整数字节顺序排列。每个副本中的size
个字节都取值于这个数最低的size个字节。再次说明,这个古怪的动作只是为了兼容其他
的汇编器。
size参数和value参数是可选的。如果不存在第2个逗号和value参数,则假定value为零。
如果不存在第1个逗号和其后的参数,则假定size为1。


7.29 .float flonums
This directive assembles zero or more flonums, separated by commas. It has the
same effect as .single. The exact kind of floating point numbers emitted depe
nds on how as is configured. See Chapter 8 [Machine Dependencies], page 61.


7.29 .float flonums
本命令汇编0个或多个浮点数,浮点数之间由逗号分隔。它和.single的汇编效果相同。生
成的浮点数的确切类型视as的配置而定。见第8章 [Machine Dependencies], 61页。


7.30 .func name[,label]
.func emits debugging information to denote function name, and is ignored unle
ss the file is assembled with debugging enabled. Only ‘--gstabs’ is currentl
y supported. Label is the entry point of the function and if omitted name prep
ended with the ‘leading char’ is used. ‘leading char’ is usually _ or noth
ing, depending on the target. All functions are currently defined to have void
return type. The function must be terminated with .endfunc.

7.30 .func name[,label]
.func发出一个调试信息用以指示函数name,这个信息将被忽略,除非文件使用debugging
enabled方式的汇编。目前只支持‘--gstabs’。label是函数的入口点,如果name被省略
则使用预定的‘引导符’。‘引导符’通常可以是 _ 或者什么也没有,视目标机型而定。
所有函数现时被定义为void返回类型,函数体必须使用.endfunc来结束


7.31 .global symbol, .globl symbol
.global makes the symbol visible to ld. If you define symbol in your partial p
rogram, its value is made available to other partial programs that are linked
with it. Otherwise, symbol takes its attributes from a symbol of the same name
from another file linked into the same program.
Both spellings (‘.globl’ and ‘.global’) are accepted, for compatibility wi
th other assemblers.
On the HPPA, .global is not always enough to make it accessible to other parti
al programs. You may need the HPPA-only .EXPORT directive as well. See Section
8.8.5 [HPPA Assembler Directives], page 84.

7.31 .global symbol, .globl symbol
.global 使符号symbol对连接器ld可见。如果您在局部过程中定义符号symbol,其它和此
的局部过程都可以访问它的值。另外,symbol从连接到本过程的另一个文件中的同名符号
获取自己的属性。
两种写法都可以(‘.globl’ 和‘.global’),以便兼容多种汇编器。

在HPPA上, .global未必总能够使符号被其它局部过程访问。可能同时需要使用HPPA-only
.EXPORT命令。见8.8.5[HPPA Assembler Directives],84页。


7.32 .hidden names
This one of the ELF visibility directives. The other two are .internal (see Se
ction 7.39 [.internal], page 44) and .protected (see Section 7.58 [.protected]
, page 50).
This directive overrides the named symbols default visibility (which is set by
their binding: local, global or weak). The directive sets the visibility to h
idden which means that the symbols are not visible to other components. Such s
ymbols are always considered to be protected as well.

7.32 .hidden names
这是一条关于ELF可见度的命令。其它两条是.internal(见7.39[.internal],44页) 和 .p
rotected (见7.58 [.protected], 50页)。本命令取消指定符号的缺省可见度(可见度由其
他命令捆绑设定:local,global,weak)。本命令把可见度设置为hidden,这意味着本符号对
其他部分不可见。这最好是一些需要长期保护的符号。


7.33 .hword expressions
This expects zero or more expressions, and emits a 16 bit number for each.
This directive is a synonym for ‘.short’; depending on the target architectu
re, it may also be a synonym for ‘.word’.

7.33 .hword expressions
本命令后可以不带或带多个expressions,并且为每个参数生成一个16位数。
本命令等同与'.short'命令。在某些架构上,也可能等同与'.word'。


7.34 .ident
This directive is used by some assemblers to place tags in object files. as si
mply accepts the directive for source-file compatibility with such assemblers,
but does not actually emit anything for it.

7.34 .ident
本命令被某些汇编器用来在目标文件中加入标饰。为了使汇编源码文件兼容上述的汇编器
,as简单地接受本命令,但实际上不产生东西。


7.35 .if absolute expression
.if marks the beginning of a section of code which is only considered part of
the source program being assembled if the argument (which must be an absolute
expression) is nonzero. The end of the conditional section of code must be mar
ked by .endif (see Section 7.20 [.endif], page 40); optionally, you may includ
e code for the alternative condition, flagged by .else (see Section 7.15 [.els
e], page 40). If you have several conditions to check, .elseif may be used to
avoid nesting blocks if/else within each subsequent .else block.
The following variants of .if are also supported:
.ifdef symbol
Assembles the following section of code if the specified symbol has been defin
ed.
.ifc string1,string2
Assembles the following section of code if the two strings are the same. The s
trings may be optionally quoted with single quotes. If they are not quoted, th
e first string stops at the first comma, and the second string stops at the en
d of the line. Strings which contain whitespace should be quoted. The string c
omparison is case sensitive.
.ifeq absolute expression
Assembles the following section of code if the argument is zero.
.ifeqs string1,string2
Another form of .ifc. The strings must be quoted using double quotes.
.ifge absolute expression
Assembles the following section of code if the argument is greater than or equ
al to zero.
.ifgt absolute expression
Assembles the following section of code if the argument is greater than zero.

.ifle absolute expression
Assembles the following section of code if the argument is less than or equal
to zero.
.iflt absolute expression
Assembles the following section of code if the argument is less than zero.
.ifnc string1,string2.
Like .ifc, but the sense of the test is reversed: this assembles the following
section of code if the two strings are not the same.
.ifndef symbol
.ifnotdef symbol
Assembles the following section of code if the specified symbol has not been d
efined. Both spelling variants are equivalent.
.ifne absolute expression
Assembles the following section of code if the argument is not equal to zero (
in other words, this is equivalent to .if).
.ifnes string1,string2
Like .ifeqs, but the sense of the test is reversed: this assembles the followi
ng section of code if the two strings are not the same.

7.35 .if absolute expression
.if 标志着一段代码的开始,这段代码只有在参数absolute experession(必须是一个独立
的表达式)不为0时才进行汇编。这段条件汇编代码必须使用.endif标志结束。(见7.20[.e
ndif], 40页);另外,可以使用.esle来标记一个代码块(见7.15 [.else],40页),这个代码
块与前面那段代码只有一个会进行汇编。 如果您需要检查数个汇编条件,可以在使用.el
seif命令,以避免在.else代码块中进行if/else语句块的嵌套。
同样可以使用下面.if的变体:
.ifdef symbol
如果指定的符号symbol已经定义过,汇编下面那段代码。
.ifc string1,string2
如果两个字符串相同的话,汇编下面那段代码。 字符串可以可选地使用单引号。如果不使
用引号则第1个字符串在逗号处结束。第2个字符串在本行末结束。包含空白的字符串应该
使用引号标注。字符串比较时是区分大小写的。

.ifeq absolute expression
如果参数的值为0,汇编下面那段代码。

.ifeqs string1,string2
这是.ifc的另一种形式,字符串必须使用双引号标注。

.ifge absolute expression
如果参数的值大于等于0,汇编下面那段代码。

.ifgt absolute expression
如果参数的值大于0,汇编下面那段代码。

.ifle absolute expression
如果参数的值小于等于0,汇编下面那段代码。

.iflt absolute expression
如果参数的值小于0,汇编下面那段代码。

.ifnc string1,string2.
类似与.ifc,不过使用反向的测试: 如果两个字符串不相等的话,汇编下面那段代码。

.ifndef symbol
.ifnotdef symbol
如果指定的符号symbol不曾被定义过,汇编下面那段代码。 上面两种写法是等效的。


.ifne absolute expression
如果参数的值为不等于0,汇编下面那段代码。 (换句话说, 这是.if的另一种写法).

.ifnes string1,string2
类似与.ifeqs,不过使用反向的测试: 如果两个字符串不相等的话,汇编下面那段代码。



7.36 .incbin "file"[,skip[,count]]
The incbin directive includes file verbatim at the current location. You can c
ontrol the search paths used with the ‘-I’ command-line option (see Chapter
2 [Command-Line Options], page 11). Quotation marks are required around file.

The skip argument skips a number of bytes from the start of the file. The coun
t argument indicates the maximum number of bytes to read. Note that the data i
s not aligned in any way, so it is the user’s responsibility to make sure tha
t proper alignment is provided both before and after the incbin directive.

7.36 .incbin "file"[,skip[,count]]
这条incbin命令在当前位置逐字地引入file文件的内容。您可以使用命令行选项参数“-I
”来控制搜索路径。(见第2章[Command-Line Options], 11页)。文件名必须使用引号。

参数skip表示需要从文件头跳过的字节数目。参数count表示读入的最大字节数目。注意,
数据没有进行任何方式的对齐操作,所以用户需要在 .incbin命令的前后进行必要的边界
对齐。


7.37 .include "file"
This directive provides a way to include supporting files at specified points
in your source program. The code from file is assembled as if it followed the
point of the .include; when the end of the included file is reached, assembly
of the original file continues. You can control the search paths used with the
‘-I’ command-line option (see Chapter 2 [Command-Line Options], page 11). Q
uotation marks are required around file.

7.37 .include "file"
本命令提供在源程序中指定点引入支撑文件的手段。file中的代码如同紧跟.include后一
样被汇编。当引入文件汇编结束,继续汇编原来的文件。您可以使用命令行选项参数“-I
”来控制搜索路径(见第2章[Command-Line Options], 11页)。文件名必须使用引号来标注



7.38 .int expressions
Expect zero or more expressions, of any section, separated by commas. For each
expression, emit a number that, at run time, is the value of that expression.
The byte order and bit size of the number depends on what kind of target the
assembly is for.

7.38 .int expressions
可以不带参数或带多个expressions,参数之间由逗号分隔。每个expressions都生成一个数
字,这个数字等于表达式在目标机器运行时的值。字节顺序和数字的位数视汇编的目标机器
而定。


7.39 .internal names
This one of the ELF visibility directives. The other two are .hidden (see Sect
ion 7.32 [.hidden], page 42) and .protected (see Section 7.58 [.protected], pa
ge 50).
This directive overrides the named symbols default visibility (which is set by
their binding: local, global or weak). The directive sets the visibility to i
nternal which means that the symbols are considered to be hidden (ie not visib
le to other components), and that some extra, processor specific processing mu
st also be performed upon the symbols as well.

7.39 .internal names
这是一条与ELF可见度相关的命令。另外的两条是.hidden(见7.32[.hidden],42页) 和 .p
rotected (见7.58 [.protected],50页)。
本命令取消指定符号的缺省可见度(可见度由其他命令捆绑设定:local,global,weak)。本
命令把指定符号可见度设置为internal,这意味着此符号需要被隐藏(即对其他部分不可见
),另外,符号还必须经过处理器的特别的处理。




# 回复:linux下汇编的Directive Operands 2004-09-08 3:24 PM n9871009
定语:发现简单的把英文直译成中文有时产生会极大的混乱。向前和向后就是一例,我在
5.3节符号名发现这个问题,当时另选了两个词替代了向前和向后。看起来现在必须说明一
下。
向前(移动):向文件头的方向(移动)。
向后(移动):向文件尾的方向(移动)。
===========================================================
7.40 .irp symbol, values . . .
Evaluate a sequence of statements assigning different values to symbol. The se
quence of statements starts at the .irp directive, and is terminated by an .en
dr directive. For each value, symbol is set to value, and the sequence of stat
ements is assembled. If no value is listed, the sequence of statements is asse
mbled once, with symbol set to the null string. To refer to symbol within the
sequence of statements, use \symbol.
For example, assembling
.irp param,1,2,3
move d\param,sp@-
.endr
is equivalent to assembling
move d1,sp@-
move d2,sp@-
move d3,sp@-

7.40 .irp symbol,values . . .
加工一个需要用values替代symbol的语句序列。语句序列从.irp命令开始,在.endr命令前
结束。对于每个value都进行如下加工:用value替代Symbol,并对此语句序列进行汇编。
如果没有给出value,则用空字符串(null sting)替代symbol,并将此语句序列汇编一次。
使用\symbol, 把参数symbol提交给语句序列。
例如下列代码
.irp param,1,2,3
move d\param,sp@-
.endr
等同与
move d1,sp@-
move d2,sp@-
move d3,sp@-


7.41 .irpc symbol,values . . .
Evaluate a sequence of statements assigning different values to symbol. The se
quence of statements starts at the .irpc directive, and is terminated by an .e
ndr directive. For each character in value, symbol is set to the character, an
d the sequence of statements is assembled. If no value is listed, the sequence
of statements is assembled once, with symbol set to the null string. To refer
to symbol within the sequence of statements, use \symbol.
For example, assembling
.irpc param,123
move d\param,sp@-
.endr
is equivalent to assembling
move d1,sp@-
move d2,sp@-
move d3,sp@-

7.41 .irpc symbol,values. . .
加工一个需要用values替代symbol的语句序列。语句序列从.irpc命令开始,在.endr命令
前结束。对于value中的每个字符,都进行如下加工;用此字符替代symbol,并对此语句序
列进行汇编。如果没有给出value参数,则用空字符串(null sting)替代symbol,并将此语
句序列汇编一次。使用\symbol, 把参数symbol提交给语句序列。
例如下列代码
.irpc param,123
move d\param,sp@-
.endr
等同与
move d1,sp@-
move d2,sp@-
move d3,sp@-


7.42 .lcomm symbol , length
Reserve length (an absolute expression) bytes for a local common denoted by sy
mbol. The section and value of symbol are those of the new local common. The a
ddresses are allocated in the bss section, so that at run-time the bytes start
off zeroed. Symbol is not declared global (see Section 7.31 [.global], page 4
2), so is normally not visible to ld.
Some targets permit a third argument to be used with .lcomm. This argument spe
cifies the desired alignment of the symbol in the bss section.
The syntax for .lcomm differs slightly on the HPPA. The syntax is ‘symbol .lc
omm, length’; symbol is optional.

7.42 .lcomm symbol , length
为一个本地通用符号symbol预留length个字节的内存。symbol 的段(属性)和值(属性)被设
置为一个新的本地通用符号应有的属性:内存是在bss段中分配的,所以在运行时,这些字
节开始都是零。因为symbol没有被声明为全局性的符号,所以symbol对ld通常不可见。

某些目标格式允许在.lcomm命令中使用第3个参数。这个参数指出这个bss段中的符号对齐
操作所需要的边界基准。
.lcomm的语法在HPPA上稍有不同。表示为‘symbol .lcomm, length’; symbol 是可选的



7.43 .lflags
as accepts this directive, for compatibility with other assemblers, but ignore
s it.

7.43 .lflags
as接受本命令,以兼容其他的汇编器,但忽略之。


7.44 .line line-number
Change the logical line number. line-number must be an absolute expression. Th
e next line has that logical line number. Therefore any other statements on th
e current line (after a statement separator character) are reported as on logi
cal line number line-number - 1. One day as will no longer support this direct
ive: it is recognized only for compatibility with existing assembler programs.

Warning: In the AMD29K configuration of as, this command is not available; use
the synonym .ln in that context.
Even though this is a directive associated with the a.out or b.out object-code
formats, as still recognizes it when producing COFF output, and treats ‘.lin
e’ as though it were the COFF ‘.ln’ if it is found outside a .def/.endef pa
ir.
Inside a .def, ‘.line’ is, instead, one of the directives used by compilers
to generate auxiliary symbol information for debugging.

7.44 .line line-number
更改逻辑行号,参数line-number必须是个纯粹的表达式。本命令后的下一行将被赋予此逻
辑行号。因此在当前行之前任何其他的语句(在语句分隔符后)的逻辑行号将被视作line
-number - 1。以后 as将不在支持这条命令:只是为了兼容现存的汇编器而接受本命令。

Warning: 在为AMD29K目标机器配置的as中,不能使用本指令。在这种场合可以使用.ln命令

尽管这是与a. out或b. out目标代码格式相关的命令,在生成COFF输出时as仍然接受它,
并且如果‘.line’出现在.def/endef之外的话,就把它视为‘.ln’命令。
如果‘.line’在.def语句块中的话,.line命令则是一条编译器使用的命令,用来为调式
生成辅助符号信息。


7.45 .linkonce [type]
Mark the current section so that the linker only includes a single copy of it.
This may be used to include the same section in several different object file
s, but ensure that the linker will only include it once in the final output fi
le. The .linkonce pseudo-op must be used for each instance of the section. Dup
licate sections are detected based on the section name, so it should be unique
.
This directive is only supported by a few object file formats; as of this writ
ing, the only object file format that supports it is the Portable Executable f
ormat used on Windows NT.
The type argument is optional. If specified, it must be one of the following s
trings. For example:
.linkonce same_size
Not all types may be supported on all object file formats.
discard Silently discard duplicate sections. This is the default.
one_only Warn if there are duplicate sections, but still keep only one copy.

same_size Warn if any of the duplicates have different sizes.
same_contents
Warn if any of the duplicates do not have exactly the same contents.

7.45 .linkonce [type]
给当前段做一个标志,以便连接器只包含它的一个拷贝。这个命令可以用于几个不同的目标
文件中包含同样的段,但需要连接器在最终的输出文件中只包含一个这样的段。. linkou
ce伪操作必须在每个段的实例都中使用。对重复段的探测基于段名来进行,因此这个段将
是唯一的。
本命令只在少数目标格式文件中有效,到写本文为止,只有基于Windows NT的PE (Portab
le Executable)格式的目标文件支持本命令,
参数type是可选的,如果指定了此参数,它必须是下列字符串之一。例如
. Linkonce same_size
不是在所有的格式目标文件都可以使用所有类型的参数。
discard 静静地舍弃重复的段,这也是默认值。
one_only 如果存在重复的段则发出警告,但只保存一个拷贝。
same_size 如果重复的段有不同的大小则发出警告。
same_contents 如果重复段的内容不是精确的相符则发出警告。


7.46 .ln line-number
‘.ln’ is a synonym for ‘.line’.

7.46 .ln line-number
‘.ln’命令等同与‘.line’.


7.47 .mri val
If val is non-zero, this tells as to enter MRI mode. If val is zero, this tell
s as to exit MRI mode. This change affects code assembled until the next .mri
directive, or until the end of the file. See Section 2.8 [MRI mode], page 13.


7.47 .mri val
如果参数val是非零值,这将通知as进入MRI模式。如果参数val的值是零,这通知as退出M
RI模式。这个变化会影响汇编的结果,直到下个.mri命令,或者直到文件尾。见2.8 [MRI
mode], 13页。


7.48 .list
Control (in conjunction with the .nolist directive) whether or not assembly li
stings are generated. These two directives maintain an internal counter (which
is zero initially). .list increments the counter, and .nolist decrements it.
Assembly listings are generated whenever the counter is greater than zero.
By default, listings are disabled. When you enable them (with the ‘-a’ comma
nd line option; see Chapter 2 [Command-Line Options], page 11), the initial va
lue of the listing counter is one.

7.48 .list
控制(和.nolist命令配合)是否生成汇编清单。这两个命令维护一个内部的计数器(计数
器初始值为0).list命令增加计数器的值,.nolist减少计数器的值。当计数器的值大与0
时将汇编列表。
缺省状态汇编列表的生成是关闭的。当您打开它的时候(使用带-a选项的命令行)第2章
[Command-Line Options], 11页), 内部计数器的初始值为1。


7.49 .long expressions
.long is the same as ‘.int’, see Section 7.38 [.int], page 44.

7.49 .long expressions
.long是.int的等价命令,见7.38 [.int], 44页.

7.50 .macro
The commands .macro and .endm allow you to define macros that generate assembl
y output. For example, this definition specifies a macro sum that puts a seque
nce of numbers into memory:
.macro sum from=0, to=5
.long \from
.if \to-\from
sum "(\from+1)",\to
.endif
.endm
With that definition, ‘SUM 0,5’ is equivalent to this assembly input:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5
.macro macname
.macro macname macargs ...
Begin the definition of a macro called macname. If your macro definition requi
res arguments, specify their names after the macro name, separated by commas o
r spaces. You can supply a default value for any macro argument by following t
he name with ‘=deflt’. For example, these are all valid .macro statements:


.macro comm
Begin the definition of a macro called comm, which takes no arguments.
.macro plus1 p, p1
.macro plus1 p p1
Either statement begins the definition of a macro called plus1,which takes two
arguments; within the macro definition, write ‘\p’ or ‘\p1’ to evaluate t
he arguments.
.macro reserve_str p1=0 p2
Begin the definition of a macro called reserve_str, with two arguments. The fi
rst argument has a default value, but not the second. After the definition is
complete, you can call the macro either as ‘reserve_str a, b’ (with ‘\p1’
evaluating to a and ‘\p2’ evaluating to b), or as ‘reserve_str ,b’ (with ‘
\p1’ evaluating as the default, in this case ‘0’, and ‘\p2’ evaluating to
b).
When you call a macro, you can specify the argument values either by position,
or by keyword. For example, ‘sum 9,17’ is equivalent to ‘sum to=17, from=9
’.
.endm Mark the end of a macro definition.
.exitm Exit early from the current macro definition.
\@ as maintains a counter of how many macros it has executed in this pseudov-a
riable; you can copy that number to your output with ‘\@’, but only within a
macro definition.


7.50 .macro
本命令.macro和.endm命令允许您定义宏来生成汇编输出。例如,下面的语句定义了一个宏
sum,这个宏把一个数字序列放入内存。

.macro sum from=0, to=5
.long \from
.if \to-\from
sum "(\from+1)",\to
.endif
.endm
使用上述定义,'SUM 0,5'语句就等于输入下面的汇编语句:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5

.macro macname
.macro macname macargs ...
开始定义一个名为macname的宏。如果您的宏需要使用参数,则在宏的名字后指定他们的名
字,参数之间用逗号或空格分隔。您可以为任意的参数提供参数的缺省值,只需要在参数
后使用“=deflt”,。例如,下列都是合法的宏定义语句:
.macro comm
定义一个名为comm宏,不使用参数。
.macro plus1 p, p1
.macro plus1 p p1
两个语句都声明要定义一个名为plus1的宏,这个宏需要两个参数,在宏定义体内,使用'
\p'或'\p1'来引用参数的值。
.macro reserve_str p1=0 p2
声明要定义一个名为reserve_str的宏,使用两个参数。第一个参数有缺省值,第二个没有
缺省值。宏定义完成后,您可以通过‘reserve_str a, b’(宏体中‘\p1’引用a的值,‘
\p2’引用b值)或通过‘reserve_str ,b’(‘\p1’使用缺省值,在此为‘0’,‘\p2’引
用b的值)来调用这个宏。

当调用一个宏时,您既可以通过位置指定参数值,也可以通过关键字指定参数值。例如,
‘sum 9,17’和‘sum to=17, from=9’是等价的。
.endm 标志宏定义体的结束。
.exitm 提前从当前宏定义体中退出。
\@ 这个伪变量其实是as维护的一个计数器,用来统计执行了多少个宏。您可以通过使用\
@把这个数字复制到您的输出中,但仅限于在宏定义体中使用。


7.51 .nolist
Control (in conjunction with the .list directive) whether or not assembly list
ings are generated. These two directives maintain an internal counter (which i
s zero initially). .list increments the counter, and .nolist decrements it. As
sembly listings are generated whenever the counter is greater than zero.

7.51 .nolist
控制(和.list命令配合)是否生成汇编列表。这两个命令维护一个内部的计数器(计数器
初始值为0).list命令增加计数器的值,.nolist减少计数器的值。当计数器的值大与0时
将汇编列表。


7.52 .octa bignums
This directive expects zero or more bignums, separated by commas. For each big
num, it emits a 16-byte integer.
The term “octa” comes from contexts in which a “word” is two bytes; hence
octa-word for 16 bytes.

7.52 .octa bignums
本命令可以不带参数或多个由逗号分隔开的巨数bignum,针对每个巨数bignum,它生成一个
16个字节的整数。
术语"octa"来源:word为2个字节,故此octa-word为16个字节。


7.53 .org new-lc , fill
Advance the location counter of the current section to new-lc. new-lc is eithe
r an absolute expression or an expression with the same section as the current
subsection. That is, you can’t use .org to cross sections: if new-lc has the
wrong section, the .org directive is ignored. To be compatible with former as
semblers, if the section of new-lc is absolute, as issues a warning, then pret
ends the section of new-lc is the same as the current subsection.
.org may only increase the location counter, or leave it unchanged; you cannot
use .org to move the location counter backwards.
Because as tries to assemble programs in one pass, new-lc may not be undefined
. If you really detest this restriction we eagerly await a chance to share you
r improved assembler.
Beware that the origin is relative to the start of the section, not to the sta
rt of the subsection. This is compatible with other people’s assemblers.
When the location counter (of the current subsection) is advanced, the interve
ning bytes are filled with fill which should be an absolute expression. If the
comma and fill are omitted, fill defaults to zero.

7.53 .org new-lc , fill
向后移动当前段的位置计数器至new-lc。new-lc要么是一个纯粹的表达式,要么这个表达
式与当前子段在同一个段中。换句话说,就是您不能使用.org进行段超越。如果new-lc指
向错误的段,则忽略.org命令。为了兼容以前的汇编器,如果new-lc指向一个地址独立的
段,as发出一个警告,并假定new-lc指向当前子段。
.org 仅仅可以增大位置计数器,或者保持位置计数器不变;您不能使用.org命令把位置计
数器向回移动。
因为as尽量一次完成程序汇编,所以不能使用未定义的new-lc。如果您厌恶这个限制,我
们急切期待有机会分享经过您改进的汇编器。
注意起点相对于段的首地址,而不是子段的首地址。这与其他的汇编器相兼容。
当(当前语句块)位置计数器到达指定位置,用fill填充该字节,fill必须是纯粹的表达
式。如果没有给出逗号和fill,fill值缺省为0。


7.54 .p2align[wl] abs-expr, abs-expr, abs-expr
Pad the location counter (in the current subsection) to a particular storage b
oundary. The first expression (which must be absolute) is the number of low-or
der zero bits the location counter must have after advancement. For example ‘
.p2align 3’ advances the location counter until it a multiple of 8. If the lo
cation counter is already a multiple of 8, no change is needed.
The second expression (also absolute) gives the fill value to be stored in the
padding bytes. It (and the comma) may be omitted. If it is omitted, the paddi
ng bytes are normally zero. However, on some systems, if the section is marked
as containing code and the fill value is omitted, the space is filled with no
-op instructions.
The third expression is also absolute, and is also optional. If it is present,
it is the maximum number of bytes that should be skipped by this alignment di
rective. If doing the alignment would require skipping more bytes than the spe
cified maximum, then the alignment is not done at all. You can omit the fill v
alue (the second argument) entirely by simply using two commas after the requi
red alignment; this can be useful if you want the alignment to be filled with
no-op instructions when appropriate.
The .p2alignw and .p2alignl directives are variants of the .p2align directive.
The .p2alignw directive treats the fill pattern as a two byte word value. The
.p2alignl directives treats the fill pattern as a four byte longword value. F
or example, .p2alignw 2,0x368d will align to a multiple of 4. If it skips two
bytes, they will be filled in with the value 0x368d (the exact placement of th
e bytes depends upon the endianness of the processor). If it skips 1 or 3 byte
s, the fill value is undefined.

7.54 .p2align[wl] abs-expr, abs-expr, abs-expr
增加位置计数器(在当前的子段)使它指向规定的存储边界。第一个表达式参数(结果必须是
纯粹的数字) 代表位置计数器移动后,计数器中连续为0的低序位数量。例如‘.align 3’
向后移动位置指针直至8的倍数(指针的最低的3位为0)。如果地址已经是8倍数,则无需
移动。
第二个表达式参数(结果必须是纯粹的数字)给出填充字节的值。用这个值填充位置计数器
越过的地方。这个参数(和逗点)可以省略。如果省略它,填充字节的值通常默认为0。但在
某些系统上,如果本段标识为包含代码,而填充值被省略,则使用no-op指令填充填充区。

第3个参数表达式的结果也必须是纯粹的数字,这个参数是可选的。如果存在第3个参数,
它代表本对齐命令允许越过字节数的最大值。如果完成这个对齐需要跳过的字节比指定的
最大值还多,则根本无法完成对齐。您可以在边界基准后简单地使用两个逗号,以省略填充
值参数(第二参数);如果您想在适当的时候,对齐操作自动使用no-op指令填充,这个方法
将非常奏效。
.p2alignw和.p2alignl是.p2align命令的变化形式。.p2alignw 使用2个字节来填充填充区
。.p2alignl使用4字节来填充。例如,. .p2alignw 2,0x368d将地址对齐到4的倍数,如果
它跳过2个字节,GAS将使用0x368d填充这2个字节(字节的准确的位置视处理器的存储方式
而定)。如果它跳过1或3个字节,填充值则不明确。


7.55 .previous
This is one of the ELF section stack manipulation directives. The others are .
section (see Section 7.66 [Section], page 52), .subsection (see Section 7.79 [
SubSection], page 56), .pushsection (see Section 7.61 [PushSection], page 50),
and .popsection (see Section 7.56 [PopSection], page 50).
This directive swaps the current section (and subsection) with most recently r
eferenced section (and subsection) prior to this one. Multiple .previous direc
tives in a row will flip between two sections (and their subsections).
In terms of the section stack, this directive swaps the current section with t
he top section on the section stack.

7.55 .previous
这是一个ELF段堆栈操作命令。其他的段堆栈操作命令还有.section (见 7.66 [Section]
, 52页), .subsection (见 7.79 [SubSection], 56页),.pushsection (见 7.61 [PushS
ection], 50页), 和 .popsection (见 7.56 [PopSection], 50页)。
本命令交换当前段(及其子段)和最近访问过的段(及其子段)。多个连续的.previous命
令将使当前位置两个段(及其子段)之间反复切换。
用段堆栈的术语来说,本命令使当前段和堆顶段交换位置。


7.56 .popsection
This is one of the ELF section stack manipulation directives. The others are .
section (see Section 7.66 [Section], page 52), .subsection (see Section 7.79 [
SubSection], page 56), .pushsection (see Section 7.61 [PushSection], page 50),
and .previous (see Section 7.55 [Previous], page 49).
This directive replaces the current section (and subsection) with the top sect
ion (and subsection) on the section stack. This section is popped off the stac
k.

7.56 .popsection
这是一个ELF段堆栈操作命令。其他的段堆栈操作命令还有.section(见 7.66 [Section],
52页), .subsection (见 7.79 [SubSection], 56页),.pushsection (见 7.61 [PushSe
ction], 50页), 和 .previous (见 7.55 [Previous], 49页).
本命令用堆栈顶段(及其子段)替代当前段(及其子段)。堆栈顶段出栈。

7.57 .print string
as will print string on the standard output during assembly. You must put stri
ng in double quotes.

7.57 .print string
as会在标准输出上打印string字符串。String必须使用双引号。


7.58 .protected names
This one of the ELF visibility directives. The other two are .hidden (see Sect
ion 7.32 [Hidden], page 42) and .internal (see Section 7.39 [Internal], page 4
4).
This directive overrides the named symbols default visibility (which is set by
their binding: local, global or weak). The directive sets the visibility to p
rotected which means that any references to the symbols from within the compon
ents that defines them must be resolved to the definition in that component, e
ven if a definition in another component would normally preempt this.

7.58 .protected names
这是一条ELF可见度的相关命令。其它两条是.hidden (参见 7.32 [Hidden], 42页)和 .i
nternal (参见 7.39 [Internal], 44页)。
本命令将取消指定符号的可见度缺省值(可见度由其他命令捆绑设定:local, global, w
eak)本命令将可见度设置为protected,这个可见度意味着:在定义此符号的部件内对此符
号的任何访问,都必须解析到这个部件内的定义体。即使其他部件中存在一个正常情况下
比此优先的定义体。

7.59 .psize lines, columns
Use this directive to declare the number of lines—and, optionally, the number
of columns—to use for each page, when generating listings.
If you do not use .psize, listings use a default line-count of 60. You may omi
t the comma and columns specification; the default width is 200 columns.
as generates formfeeds whenever the specified number of lines is exceeded (or
whenever you explicitly request one, using .eject).
If you specify lines as 0, no formfeeds are generated save those explicitly sp
ecified with .eject.

7.59 .psize lines , columns
当生成清单列表时,使用本命令声明每页的行数—还可以可选地声明列数。
如果您不使用本命令,清单列表的行数为默认的60行。可以省略逗号和列参数:默认值为
200列。
当指定的行数过多的话,as会产生进纸操作。(如果您确实需要一个进纸动作,可以使用
.eject命令)
如果您指定行数为0,则不产生进纸操作,除非您明确地使用了.eject命令。


7.60 .purgem name
Undefine the macro name, so that later uses of the string will not be expanded
. See Section 7.50 [Macro], page 47.

7.60 .purgem name
取消name的宏定义,后面使用字符串name不会被宏扩展。参见 7.50 [Macro], 47页。


7.61 .pushsection name , subsection
This is one of the ELF section stack manipulation directives. The others are .
section (see Section 7.66 [Section], page 52), .subsection (see Section 7.79 [
SubSection], page 56), .popsection (see Section 7.56 [PopSection], page 50), a
nd .previous (see Section 7.55 [Previous], page 49).
This directive is a synonym for .section. It pushes the current section (and s
ubsection) onto the top of the section stack, and then replaces the current se
ction and subsection with name and subsection.

7.61 .pushsection name , subsection
本命令是一个ELF段堆栈操作命令。其余的几个是.section (参见 7.66 [Section], 52页
) , .subsection (参见7.79 [SubSection], 56页),.popsection (参见 7.56 [PopSecti
on], 50页), 和 .previous (参见 7.55 [Previous], 49页)。
本命令与.section命令是等价的。它将当前段(及子段)推入段堆栈的顶部。并使用name
和subsection来替代当前段和子段。

7.62 .quad bignums
.quad expects zero or more bignums, separated by commas. For each bignum, it e
mits an 8-byte integer. If the bignum won’t fit in 8 bytes, it prints a warni
ng message; and just takes the lowest order 8 bytes of the bignum.
The term “quad” comes from contexts in which a “word” is two bytes; hence
quad-word for 8 bytes.

7.62 .quad bignums
.quad 可带0或多个bignum参数,每个参数由逗号分隔。对于每个bignum都汇编成一个8字
节的整数。如果某个bignum用8字节无法表示,则给出警告信息;只汇编这个bignum的最低
8字节。
术语“quad”源于一个“word”代表2个字节,所以quad-word代表8个字节。

7.63 .rept count
Repeat the sequence of lines between the .rept directive and the next .endr di
rective count times.
For example, assembling
.rept 3
.long 0
.endr
is equivalent to assembling
.long 0
.long 0
.long 0

7.63 .rept count
汇编.rept和.endr之间的语句count次。
如, 汇编下列语句:
.rept 3
.long 0
.endr
与下列语句是等价的:
.long 0
.long 0
.long 0

7.64 sbttl "subheading"
Use subheading as the title (third line, immediately after the title line) whe
n generating assembly listings.
This directive affects subsequent pages, as well as the current page if it app
ears within ten lines of the top of a page.

7.64 sbttl "subheading"
当生成汇编清单时,使用subheading作为标题(第3行,紧跟在标题行之后)。
本命令对清单的后续页起作用,如果它位于当前页的前10行内,则对当前页也起作用。



7.65 .scl class
Set the storage-class value for a symbol. This directive may only be used insi
de a .def/.endef pair. Storage class may flag whether a symbol is static or ex
ternal, or it may record further symbolic debugging information.
The ‘.scl’ directive is primarily associated with COFF output; when configur
ed to generate b.out output format, as accepts this directive but ignores it.


7.65 .scl class
设置一个符号的存储类型值(storage-class value)。本命令只能在.def/.endef之间使
用。符号的存储类型可以表明符号是static类型或是external类型,或者进一步记录符号
的调试信息。
‘.scl’命令主要与在COFF输出有关,当生成b.out输出格式时,as接受本命令,但忽略本
命令。




7.66 .section name (COFF version)
Use the .section directive to assemble the following code into a section named
name.
This directive is only supported for targets that actually support arbitrarily
named sections; on a.out targets, for example, it is not accepted, even with
a standard a.out section name.
For COFF targets, the .section directive is used in one of the following ways:

.section name [, "flags"]
.section name [, subsegment]
If the optional argument is quoted, it is taken as flags to use for the sectio
n. Each flag is a single character. The following flags are recognized:
b bss section (uninitialized data)
n section is not loaded
w writable section
d data section
r read-only section
x executable section
s shared section (meaningful for PE targets)
If no flags are specified, the default flags depend upon the section name. If
the section name is not recognized, the default will be for the section to be
loaded and writable. Note the n and w flags remove attributes from the section
, rather than adding them, so if they are used on their own it will be as if n
o flags had been specified at all.
If the optional argument to the .section directive is not quoted, it is taken
as a subsegment number (see Section 4.4 [Sub-Sections], page 25).

7.66 .section name (COFF 版本)
使用.section命令将后续的代码汇编进一个定名为name的段。
本命令只能在目标格式真正支持任意命名段时使用;例如,汇编一个a.out目标格式时,即
使name是一个标准的a.out段名,本命令也不被接受。
当目标格式为COFF时,.section命令的使用为下面某一种格式:
.section name[, "flags"]
.section name[, subsegment]
如可选参数使用了引号,它将被视为该段的标志(flags)。每个标记是单个的字符。下列是
认可的标志。
b bss 段 (未初始化的数据)
n 未装入内存的段
w 可写的段
d 数据段
r 只读段
x 代码段 (executable section)
s 共享段 (目标为PE格式有意义)
如果本命令没有指定标志,则依靠段名来确定标志缺省值。如果该段名没有使用标准段名
,则默认该段已装入内存并且可写。注意在使用n和w标志组合时,不是增加这组属性,而
是删除该段的属性。所以如果只存在这两个标志,就代表该段没有指定任何标志。
如果本命令的可选参数没有使用引号,参数将被视为子段的编号。(参见 4.4 [Sub-Secti
ons], 25页)。



7.67 .section name (ELF 版本)
This is one of the ELF section stack manipulation directives. The others are .
subsection (see Section 7.79 [SubSection], page 56), .pushsection (see Section
7.61 [PushSection], page 50), .popsection (see Section 7.56 [PopSection], pag
e 50), and .previous (see Section 7.55 [Previous], page 49).
For ELF targets, the .section directive is used like this:
.section name [, "flags"[, @type]]
The optional flags argument is a quoted string which may contain any combinati
on of the following characters:
a section is allocatable
w section is writable
x section is executable
The optional type argument may contain one of the following constants:
@progbits section contains data
@nobits section does not contain data (i.e., section only occupies space)

If no flags are specified, the default flags depend upon the section name. If
the section name is not recognized, the default will be for the section to hav
e none of the above flags: it will not be allocated in memory, nor writable, n
or executable. The section will contain data.
For ELF targets, the assembler supports another type of .section directive for
compatibility with the Solaris assembler:
.section "name"[, flags...]
Note that the section name is quoted. There may be a sequence of comma separat
ed flags:
#alloc section is allocatable
#write section is writable
#execinstr section is executable
This directive replaces the current section and subsection. The replaced secti
on and subsection are pushed onto the section stack. See the contents of the g
as testsuite directory gas/testsuite/gas/elf for some examples of how this dir
ective and the other section stack directives work.

7.67 .section name (ELF 版本)
本命令是ELF的段堆栈操作命令之一,其他的段堆栈命令为.subsection (见 Section 7.7
9 [SubSection], page 56), .pushsection (见Section 7.61 [PushSection], page 50)
, .popsection (见 Section 7.56 [PopSection], page 50), and .previous (见 Secti
on 7.55 [Previous], page 49).
当目标格式为ELF时,.section命令应如下使用:
.section name [, "flags"[, @type]]
可选参数flags是被引号包围的字符串,可以由下列字符的任意组合:
a 可分配的段(allocatable)
w 可写段
x 代码段
可选的参数type可以包含下列的任一常量:
@progbits 包含数据的段
@nobits 不包含数据的段(只占用空间的段)
如果本命令没有指定标志,则依靠段名来确定标志缺省值。如果段名不是标准的段名,则
默认的该段不包含上述标志:该段不可分配内存,不可写,不可执行。该段是包含数据的
段。
当目标格式为ELF时,as还支持另一种形式的.section命令,以便兼容Solaris的汇编器:

.section "name"[, flags...]
注意段名是使用引号包围的,可能存在一系列由逗号分隔分隔的标志:
#alloc 可分配的段(section is allocatable)
#write 可写的段
#execinstr 可执行的段
本命令将(用段名为name的段)替代当前段和子段。被替换的段将被推入段堆栈。参见ga
s的测试套件目录gas/testsuite/gas/elf,可以找到一些本命令和其他段堆栈操作命令的
例子。

7.68 .set symbol, expression
Set the value of symbol to expression. This changes symbol’s value and type t
o conform to expression. If symbol was flagged as external, it remains flagged
(see Section 5.5 [Symbol Attributes], page 30).
You may .set a symbol many times in the same assembly.
If you .set a global symbol, the value stored in the object file is the last v
alue stored into it.
The syntax for set on the HPPA is ‘symbol .set expression’.

7.68 .set symbol, expression
设置symbol为expression。这将改变symbol的值域和类型领域以符合expression参数。如
果symbol已被标志为external,则symbol保持它的标志。(见 5.5 [Symbol Attributes],
30页)。
您可以在同一个汇编程序中多次使用.set命令来设置同一个符号。
如果设置一个全局符号,该符号在目标文件中值为最后设定的值。
在HPPA上的语法是‘symbol .set expression’。

7.69 .short expressions
.short is normally the same as ‘.word’. See Section 7.92 [.word], page 59.

In some configurations, however, .short and .word generate numbers of differen
t lengths; see Chapter 8 [Machine Dependencies], page 61.

7.69 .short expressions
本命令通常和’.word’命令一样,见7.92 [.word], 59页.
然而在某些配置中,.short和.word命令生成的数字长度却不相同;见第8章 [Machine De
pendencies], 61页.



7.70 .single flonums
This directive assembles zero or more flonums, separated by commas. It has the
same effect as .float. The exact kind of floating point numbers emitted depen
ds on how as is configured. See Chapter 8 [Machine Dependencies], page 61.

7.70 .single flonums
本命令可以汇编0个或多个浮点参数,各个参数之间使用逗号分隔。它的作用和.float相同
。生成浮点数的具体类型视as的配置而定。见第8章 [Machine Dependencies], 61页。






--------------------
一切有为法 如梦幻泡影




# 回复:linux下汇编的Directive Operands 2004-09-08 3:25 PM n9871009
Re: 7 汇编器命令(下) [re: amtb]



位组合:bit pattern,想不出有什么特别的意义,大概指的是有限个数的0和1所有的组合
吧。Fix me.
sleb128/uleb128: 基于128位的低地址结尾带/无符号的数。您有什么好建议?
==========================下==================================
7.71 .size (COFF 版本)
This directive is generated by compilers to include auxiliary debugging inform
ation in the symbol table. It is only permitted inside .def/.endef pairs.
‘.size’ is only meaningful when generating COFF format output; when as is ge
nerating b.out, it accepts this directive but ignores it.

7.71 .size (COFF 版本)
本命令一般由编译器生成,以在符号表中加入辅助调试信息。本命令只能在.def/.endef命
令对之间使用。
本命令只在生成COFF格式的输出文件有意义。当as生成b.out时,as接受本命令但忽略之。




7.72 .size name , expression (ELF 版本)
This directive is used to set the size associated with a symbol name. The size
in bytes is computed from expression which can make use of label arithmetic.
This directive is typically used to set the size of function symbols.
本命令经常用来设置符号name的内存大小。内存大小的单位是字节, 通过计算参数expres
sion得到,参数expression中可以使用标签进行计算。本命令常用来设置函数符号的长度


7.73 .sleb128 expressions
sleb128 stands for “signed little endian base 128.” This is a compact, varia
ble length representation of numbers used by the DWARF symbolic debugging form
at. See Section 7.86 [Uleb128], page 58.

7.73 .sleb128 expressions
sleb128代表“signed little endian base 128”(低地址结尾的带符号128位基数)。这是
一个紧凑的,变长的数字表示方法,当使用DWARF符号调试格式时使用。参见7.86 [Uleb1
28], 58页。



7.74 .skip size , fill
This directive emits size bytes, each of value fill. Both size and fill are ab
solute expressions. If the comma and fill are omitted, fill is assumed to be z
ero. This is the same as ‘.space’.

7.74 .skip size , fill
本命令生成size个字节,每个字节的值都是fill。参数size和fill都必须是纯粹的表达式
。如果省略逗号和fill,则默认fill的值为0。这与’.space’相同。



7.75 .space size , fill
This directive emits size bytes, each of value fill. Both size and fill are ab
solute expressions. If the comma and fill are omitted, fill is assumed to be z
ero. This is the same as ‘.skip’.
Warning: .space has a completely different meaning for HPPA targets; use .bloc
k as a substitute. See HP9000 Series 800 Assembly Language Reference Manual (H
P 92432-90001) for the meaning of the .space directive. See Section 8.8.5 [HPP
A Assembler Directives], page 84, for a summary.
On the AMD 29K, this directive is ignored; it is accepted for compatibility wi
th other AMD 29K assemblers.
Warning: In most versions of the gnu assembler, the directive .space has the e
ffect of .block See Chapter 8 [Machine Dependencies], page 61.

7.75 .space size , fill
本命令生成size个字节,每个字节的值都是fill。参数size和fill都必须是纯粹的表达式
。如果省略了逗号和fill,则默认fill的值为0。这与’.skip’相同。
警告:在生成HPPA目标格式时,.space的意义完全不同。应该使用.block命令替代本命令
。在HP9000系列800汇编语言参考手册(HP 92432-90001),可以找到.space命令的用法。参
见 8.8.5 [HPPA Assembler Directives],84页, 可以找到使用摘要。
在AMD 29K上,本命令将被忽略。出于兼容其它一些AMD 29K汇编器的目的,as接受本命令

警告:在gnu汇编器大多数版本中,这个.space命令和.block命令等效。见第8章 [Machin
e Dependencies], 61页。

7.76 .stabd, .stabn, .stabs
There are three directives that begin ‘.stab’. All emit symbols (see Chapter
5 [Symbols], page 29), for use by symbolic debuggers. The symbols are not ent
ered in the as hash table:they cannot be referenced elsewhere in the source fi
le. Up to five fields are required:
string This is the symbol’s name. It may contain any character except ‘\000’
, so is more general than ordinary symbol names. Some debuggers used to code a
rbitrarily complex structures into symbol names using this field.
type An absolute expression. The symbol’s type is set to the low 8 bits of th
is expression. Any bit pattern is permitted, but ld and debuggers choke on sil
ly bit patterns.
other An absolute expression. The symbol’s “other” attribute is set to the
low 8 bits of this expression.
desc An absolute expression. The symbol’s descriptor is set to the low 16 bit
s of this expression.
Value An absolute expression that becomes the symbol’s value.
If a warning is detected while reading a .stabd, .stabn, or .stabs statement,
the symbol has probably already been created; you get a half-formed symbol in
your object file. This is compatible with earlier assemblers!
.stabd type , other , desc
The “name” of the symbol generated is not even an empty string. It is a null
pointer, for compatibility. Older assemblers used a null pointer so they didn
’t waste space in object files with empty strings.
The symbol’s value is set to the location counter, relocatably. When your pro
gram is linked, the value of this symbol is the address of the location counte
r when the .stabd was assembled.
.stabn type , other , desc , value
The name of the symbol is set to the empty string "".
.stabs string , type , other , desc , value
All five fields are specified.

7.76 .stabd, .stabn, .stabs
有3个以.stab开头的命令。它们都用来产生符号,(参见第5章 [Symbols], 29页),供符号
调试器使用。这些符号没有收入as的散列表中:这些符号不能被源文件其他地方所访问。
它们至少需要5个属性域:
string 这是符号的名字。它可以包含除‘\000’之外的任何字符,故此可用名比普通符号
名更广泛。很多调试器经常利用这个空间,把任意复杂的结构编码为符号名。
type 这是一个纯粹的表达式。符号的类型属性由这个表达式的低8位设定。任何的位组合
(bit pattern)都可以,但连接器和调试器会被没有义的位组合所中断。
other 这是一个纯粹的表达式。由这个表达式的低8位设定此符号的“其它”属性。
desc 这是一个纯粹的表达式。由这个表达式的低16位设定此符号的描述符。
Value 这个纯粹的表达式将作为符号的值。

如果汇编.stabd, .stabn, 或 .stabs语句时引发了一个警告,该符号有可能已经被创建;
在目标文件中存在一个半成品的符号。这样做兼容于早期的汇编器!

.stabd type , other , desc
生成符号的“名字”甚至不是空字符串,而是一个空指针(null),这样安排是出于对兼
容性要求。早期的汇编器经常使用空指针,以避免空字符串在目标文件中浪费空间。
这个符号的值(值域)在重定位时设置为位置计数器的值。当程序连接之后,这个符号的
值是.stabd命令汇编时位置计数器的地址。
.stabn type , other , desc , value
这个符号的名字被设置为空字符串“”。
.stabs string , type , other , desc , value
5个属性域全部指定好。



7.77 .string "str"
Copy the characters in str to the object file. You may specify more than one s
tring to copy, separated by commas. Unless otherwise specified for a particula
r machine, the assembler marks the end of each string with a 0 byte. You can u
se any of the escape sequences described in Section 3.6.1.1 [Strings], page 19
.

7.77 .string "str"
将参数str中的字符复制到目标文件中去。您可以指定多个字符串进行复制,之间使用逗号
分隔。除非另外指定了具体的机器,汇编器将在每个字符串后追加一个0字节作为标记。您
可以使用任意的逃逸序列,参见19页中3.6.1.1 [Strings]的描述。



7.78 .struct expression
Switch to the absolute section, and set the section offset to expression, whic
h must be an absolute expression. You might use this as follows:
.struct 0
field1:
.struct field1 + 4
field2:
.struct field2 + 4
field3:
This would define the symbol field1 to have the value 0, the symbol field2 to
have the value 4, and the symbol field3 to have the value 8. Assembly would be
left in the absolute section, and you would need to use a .section directive
of some sort to change to some other section before further assembly.

7.78 .struct expression
切换到独立地址段,并用expression设定段的偏移量,expression必须是个纯粹的表达式
。您可以如下使用:
.struct 0
field1:
.struct field1 + 4
field2:
.struct field2 + 4
field3:

定义符号field1的值为0,符号field2的值为4,符号field3的值为8。这段汇编程序将保存
在独立地址段中,在进行下一步汇编前,您需要使用一个某种类型的.section命令,以切
换到相应的段。



7.79 .subsection name
This is one of the ELF section stack manipulation directives. The others are .
section (see Section 7.66 [Section], page 52),.pushsection (see Section 7.61 [
PushSection], page 50), .popsection (see Section 7.56 [PopSection], page 50),
and .previous (see Section 7.55 [Previous], page 49).
This directive replaces the current subsection with name. The current section
is not changed. The replaced subsection is put onto the section stack in place
of the then current top of stack subsection.

7.79 .subsection name
本命令是一个ELF段堆栈操作命令。其它的几个命令是(参见 7.66 [Section], 52页),
.pushsection (参见 7.61 [PushSection],50页), .popsection (参见 7.56 [PopSectio
n], 50页), and .previous (参见7.55 [Previous], 49页)。
本命令用name子段替换当前子段。当前段并不改变。被替换的子段入段堆栈,成为段堆栈
的新栈顶。



7.80 .symver
Use the .symver directive to bind symbols to specific version nodes within a s
ource file. This is only supported on ELF platforms, and is typically used whe
n assembling files to be linked into a shared library. There are cases where i
t may make sense to use this in objects to be bound into an application itself
so as to override a versioned symbol from a shared library.
For ELF targets, the .symver directive can be used like this:
.symver name, name2@nodename
If the symbol name is defined within the file being assembled, the .symver dir
ective effectively creates a symbol alias with the name name2@nodename, and in
fact the main reason that we just don’t try and create a regular alias is th
at the @ character isn’t permitted in symbol names. The name2 part of the nam
e is the actual name of the symbol by which it will be externally referenced.
The name name itself is merely a name of convenience that is used so that it i
s possible to have definitions for multiple versions of a function within a si
ngle source file, and so that the compiler can unambiguously know which versio
n of a function is being mentioned. The nodename portion of the alias should b
e the name of a node specified in the version script supplied to the linker wh
en building a shared library. If you are attempting to override a versioned sy
mbol from a shared library, then nodename should correspond to the nodename of
the symbol you are trying to override.
If the symbol name is not defined within the file being assembled, all referen
ces to name will be changed to name2@nodename. If no reference to name is made
, name2@nodename will be removed from the symbol table.
Another usage of the .symver directive is:
.symver name, name2@@nodename
In this case, the symbol name must exist and be defined within the file being
assembled. It is similar to name2@nodename. The difference is name2@@nodename
will also be used to resolve references to name2 by the linker.
The third usage of the .symver directive is:
.symver name, name2@@@nodename
When name is not defined within the file being assembled, it is treated as nam
e2@nodename. When name is defined within the file being assembled, the symbol
name, name, will be changed to name2@@nodename.

7.80 .symver
使用.symver命令把符号装订到在源文件里指定的节点。本命令只在ELF平台上可用,如果
当前汇编的文件被连接到一个共享库中时常常用到。有些情况下应该在目标文件中使用本
命令,把目标文件自我装订进某个应用软件中,从而取代共享库中旧版本符号。
对于ELF目标,.symver命令可以这样使用:
.symver name, name2@nodename
如果符号name的定义在当前正在汇编的文件中,这个.symver命令实际用name2@nodename创
建一个符号别名,而且我们不打算创建一个正规的别名,因为在符号名中是不允许存在‘
@’这个字符的。别名中name2才是符号的真正名字,外部访问是通过这个名字进行的。符
号自己的名字name仅仅为了使用上的方便,这样在同一个源文件中的一个函数才可能有多
个定义体;编译器才能够清楚当前使用的函数是哪个具体的定义。别名中的nodename部分
应是某个节点的名字,这个节点的名字是在建立共享库时,提供给连接器的版本脚本中指
定的。如果您想覆盖共享库中的旧版本符号,则nodename应该是将被取代符号的节点名。

如果符号name的定义不在当前正在汇编的文件中,则所有对name的访问都变为对name2@no
dename的访问。如果根本没有对name的访问,将会把name2@nodename从符号表中删除。

.symver命令的另一种用法:
.symver name, name2@@nodename
在这种情况下,符号name必须存在,并且它必须在当前正在汇编的文件中被定义。这类似
与name2@nodename。区别是name2@@nodename还被连接器用来解析对name2的访问。//注:
对name2的访问被转向到nodename
.symver命令的第3种用法:
.symver name, name2@@@nodename
如果name不是在当前正在汇编的文件中被定义的时候,对符号的处理就如同name2@nodena
me。如果name是当前正在汇编的文件中定义的,符号的名字name,会被转换为name2@@nod
ename。



7.81 .tag structname
This directive is generated by compilers to include auxiliary debugging inform
ation in the symbol table. It is only permitted inside .def/.endef pairs. Tags
are used to link structure definitions in the symbol table with instances of
those structures.
‘.tag’ is only used when generating COFF format output; when as is generatin
g b.out, it accepts this directive but ignores it.

7.81 .tag structname
本命令由编译器生成,用来在符号表中增加调试辅助的信息。本命令只允许在.def/.ende
f语句对内使用。标饰(tags)常用来连接符号表中的结构定义和该结构实例。
‘.tag’只能在生成COFF格式的输出文件时使用。当as生成b.out格式的输出文件时,接受
本命令但忽略之。



7.82 .text subsection
Tells as to assemble the following statements onto the end of the text subsect
ion numbered subsection, which is an absolute expression. If subsection is omi
tted, subsection number zero is used.

7.82 .text subsection
通知as把后续语句汇编到编号为subsection的正文子段的末尾,subsection是一个纯粹的
表达式。如果省略了参数subsection,则使用编号为0的子段。


7.83 .title "heading"
Use heading as the title (second line, immediately after the source file name
and page number) when generating assembly listings.
This directive affects subsequent pages, as well as the current page if it app
ears within ten lines of the top of a page.

7.83 .title "heading"
当生成汇编清单时,把heading作为标题使用(标题在第2行,紧跟在源文件名和页号后)

如果这个命令出现在某页的前10行中,它不但作用影响到后续的页,也同样影响到当前页



7.84 .type int (COFF version)
This directive, permitted only within .def/.endef pairs, records the integer i
nt as the type attribute of a symbol table entry.
‘.type’ is associated only with COFF format output; when as is configured fo
r b.out output, it accepts this directive but ignores it.

7.84 .type int (COFF 版本)
本命令紧允许在.def/.endef 命令对之间使用,把整数int作为类型属性记录进符号表表项

‘.type’只和COFF格式的输出有关,当as配置生成b.out输出格式时,as接受本命令但忽
略之。

7.85 .type name , type description (ELF version)
This directive is used to set the type of symbol name to be either a function
symbol or an object symbol. There are five different syntaxes supported for th
e type description field, in order to provide compatibility with various other
assemblers. The syntaxes supported are:

.type <name>,#function
.type <name>,#object

.type <name>,@function
.type <name>,@object

.type <name>,%function
.type <name>,%object

.type <name>,"function"
.type <name>,"object"

.type <name> STT_FUNCTION
.type <name> STT_OBJECT

7.85 .type name , type description (ELF 版本)
本命令经常用来设置符号name的类型(属性)为函数符号或是目标符号两者之一。type d
escription部分允许使用5种不同的语法,以兼容众多的汇编器。这些语法是:

.type <name>,#function
.type <name>,#object

.type <name>,@function
.type <name>,@object

.type <name>,%function
.type <name>,%object

.type <name>,"function"
.type <name>,"object"

.type <name> STT_FUNCTION
.type <name> STT_OBJECT


7.86 .uleb128 expressions
uleb128 stands for “unsigned little endian base 128.” This is a compact, var
iable length representation of numbers used by the DWARF symbolic debugging fo
rmat. See Section 7.73 [Sleb128], page 54.

7.86 .uleb128 expressions
uleb128代表“unsigned little endian base 128”(低地址结尾的无符号128位基数)。这
是一个紧凑的,变长的数字表示方法,当使用DWARF符号调试格式时使用。参见7.83 [Sle
b128], 54页。



7.87 .val addr
This directive, permitted only within .def/.endef pairs, records the address a
ddr as the value attribute of a symbol table entry.
‘.val’ is used only for COFF output; when as is configured for b.out, it acc
epts this directive but ignores it.

7.87 .val addr
本命令只能在.def/.endef命令对之间使用,把addr的地址作为值属性存入符号表的表项中

‘.val’命令只能在COFF输出时使用;当as被配置成生成b.out输出时,接受本命令但忽略
之。



7.88 .version "string"
This directive creates a .note section and places into it an ELF formatted not
e of type NT VERSION. The note’s name is set to string.

7.88 .version "string"
本命令创建一个.note段,并把一个NT VERSION类型ELF格式的note放入该.note段。Note的
名字被设置为string。



7.89 .vtable_entry table, offset
This directive finds or creates a symbol table and creates a VTABLE_ENTRY relo
cation for it with an addend of offset.

7.89 .vtable_entry table, offset
本命令寻找或创建一个符号表,并用offset作偏移量的增量,为此符号表产生一个VTABLE
_ENTRY重定位。



7.90 .vtable_inherit child, parent
This directive finds the symbol child and finds or creates the symbol parent a
nd then creates a VTABLE_INHERIT relocation for the parent whose addend is the
value of the child symbol. As a special case the parent name of 0 is treated
as refering the *ABS* section.

7.90 .vtable_inherit child, parent
本命令寻找符号child, 并寻找或创建符号parent,为符号parent产生一个VTABLE_INHERI
T重定位,parent的偏移量增量为符号child的值。一个特例,如果parent的名字为0,则将
它交给*ABS*段处理。



7.91 .weak names
This directive sets the weak attribute on the comma separated list of symbol n
ames. If the symbols do not already exist, they will be created.

7.91 .weak names
本命令设置names中每个符号(由逗号分隔)的weak属性。如果这些符号尚不存在,则创建
这些符号。


7.92 .word expressions
This directive expects zero or more expressions, of any section, separated by
commas.
The size of the number emitted, and its byte order, depend on what target comp
uter the assembly is for.
Warning: Special Treatment to support Compilers
Machines with a 32-bit address space, but that do less than 32-bit addressing,
require the following special treatment. If the machine of interest to you do
es 32-bit addressing (or doesn’t require it; see Chapter 8 [Machine Dependenc
ies], page 61), you can ignore this issue.
In order to assemble compiler output into something that works, as occasionall
y does strange things to ‘.word’ directives. Directives of the form ‘.word
sym1-sym2’ are often emitted by compilers as part of jump tables. Therefore,
when as assembles a directive of the form ‘.word sym1-sym2’, and the differe
nce between sym1 and sym2 does not fit in 16 bits, as creates a secondary jump
table, immediately before the next label. This secondary jump table is preced
ed by a short-jump to the first byte after the secondary table. This short-jum
p prevents the flow of control from accidentally falling into the new table. I
nside the table is a long-jump to sym2. The original ‘.word’ contains sym1 m
inus the address of the long-jump to sym2.
If there were several occurrences of ‘.word sym1-sym2’ before the secondary
jump table, all of them are adjusted. If there was a ‘.word sym3-sym4’, that
also did not fit in sixteen bits, a long-jump to sym4 is included in the seco
ndary jump table, and the .word directives are adjusted to contain sym3 minus
the address of the long-jump to sym4; and so on, for as many entries in the or
iginal jump table as necessary.

7.92 .word expressions
本命令可不带表达式或带多个表达式,这些表达式可以属于任意段,每个表达式由逗号分
隔。
汇编生成的数字的大小,字节顺序视生成程序运行的目标机器而定。
警告:支持编译器的特殊处理
有些机器具有32位地址空间,但不能完全进行32位寻址,需要下列的特殊处理。如果您关
心的机器能够进行32位寻址,(或者根本不需要32位寻址;见第8章[机器相关性],61页)
则可以忽略这个问题。
为了使由编译器产生源码的汇编结果能够正确地运行,as偶尔会对'.word'命令进行些奇怪
的操作。编译器在跳转表部分经常生成类似'.word sym1-sym2'形式的命令。所以,当as汇
编一条形如'.word sym1-sym2'的命令,且sym1和sym2之间的偏移量大于16位时,as会在下
个标签前创建一个'次级跳转表',在'次级跳转表'前面加插上一个短-跳转指令,这个短-跳
转指令的目的地址是'次级跳转表'之后的第一个字节。 这个短跳转防止控制流程意外地落
入新的跳转表(次级跳转表)。在'次级跳转表'内是个目的地址为sym2的长-跳转指令。原
来的'.word'命令调整为sym1减去到sym2的长-跳转指令地址,。
如果在次级跳转表前出现了几个'.word sym1-sym2',这些命令都要进行调整。如果存在一
个'.word sym3-sym4',且地址差也大与16位,次级跳转表中将包含一个至sym4的长-跳转
指令,且.word命令将被调整为包含sym3减去到sym4长-跳转指令的地址; 如是类推,处理
原始跳转表中的需要处理的各个表项。



7.93 Deprecated Directives
One day these directives won’t work. They are included for compatibility with
older assemblers.
.abort
.line

7.93 不赞成使用的命令
将来下列命令可能不再被支持,它们的存在只是为了与老版本的汇编器相兼容。
.abort
.line

AT&T汇编指令

GAS中每个操作都是有一个字符的后缀,表明操作数的大小。

C声明

GAS后缀

大小(字节)

char

b

1

short

w

2

(unsigned) int / long / char*

l

4

float

s

4

double

l

8

long double

t

10/12

注意:GAL使用后缀“l”同时表示4字节整数和8字节双精度浮点数,这不会产生歧义因为浮点数使用的是完全不同的指令和寄存器。

 

 

操作数格式:

格式

操作数值

名称

样例(GAS = C语言)

$Imm

Imm

立即数寻址

$1 = 1

Ea

R[Ea]

寄存器寻址

%eax = eax

Imm

M[Imm]

绝对寻址

0x104 = *0x104

Ea

M[R[Ea]]

间接寻址

%eax= *eax

Imm(Ea)

M[Imm+R[Ea]]

(基址+偏移量)寻址

4(%eax) = *(4+eax)

Ea,Eb

M[R[Ea]+R[Eb]]

变址

(%eax,%ebx) = *(eax+ebx)

ImmEa,Eb

M[Imm+R[Ea]+R[Eb]]

寻址

9(%eax,%ebx)= *(9+eax+ebx)

(,Ea,s)

M[R[Ea]*s]

伸缩化变址寻址

(,%eax,4)= *(eax*4)

Imm(,Ea,s)

M[Imm+R[Ea]*s]

伸缩化变址寻址

0xfc(,%eax,4)= *(0xfc+eax*4)

(Ea,Eb,s)

M(R[Ea]+R[Eb]*s)

伸缩化变址寻址

(%eax,%ebx,4) = *(eax+ebx*4)

Imm(Ea,Eb,s)

M(Imm+R[Ea]+R[Eb]*s)

伸缩化变址寻址

8(%eax,%ebx,4) = *(8+eax+ebx*4)

注:M[xx]表示在存储器中xx地址的值,R[xx]表示寄存器xx的值,这种表示方法将寄存器、内存都看出一个大数组的形式。

 

 

数据传送指令:

指令

效果

描述

movl S,D

D <-- S

传双字

movw S,D

D <-- S

传字

movb S,D

D <-- S

传字节

movsbl S,D

D <-- 符号扩展S

符号位填充(字节->双字)

movzbl S,D

D <-- 零扩展S

零填充(字节->双字)

pushl S

R[%esp] <-- R[%esp] – 4;

M[R[%esp]] <-- S

压栈

popl D

D <-- M[R[%esp]]

R[%esp] <-- R[%esp] + 4;

出栈

注:均假设栈往低地址扩展。

 

 

算数和逻辑操作地址:

指令

效果

描述

leal S,D

D = &S

movl地版,S地址入DD仅能是寄存器

incl D

D++

1

decl D

D--

1

negl D

D = -D

取负

notl D

D = ~D

取反

addl S,D

D = D + S

subl S,D

D = D – S

imull S,D

D = D*S

xorl S,D

D = D ^ S

异或

orl S,D

D = D | S

andl S,D

D = D & S

sall k,D

D = D << k

左移

shll k,D

D = D << k

左移(sall)

sarl k,D

D = D >> k

算数右移

shrl k,D

D = D >> k

逻辑右移

 

 

特殊算术操作:

指令

效果

描述

imull S

R[%edx]:R[%eax] = S * R[%eax]

无符号64位乘

mull S

R[%edx]:R[%eax] = S * R[%eax]

有符号64位乘

cltd S

R[%edx]:R[%eax] = 符号位扩展R[%eax]

转换为4字节

idivl S

R[%edx] = R[%edx]:R[%eax] % S;

R[%eax] = R[%edx]:R[%eax] / S;

有符号除法,保存余数和商

divl S

R[%edx] = R[%edx]:R[%eax] % S;

R[%eax] = R[%edx]:R[%eax] / S;

无符号除法,保存余数和商

注:64位数通常存储为,高32位放在edx,低32位放在eax

 

 

条件码:

条件码寄存器描述了最近的算数或逻辑操作的属性。

CF:进位标志,最高位产生了进位,可用于检查无符号数溢出。

OF:溢出标志,二进制补码溢出——正溢出或负溢出。

ZF:零标志,结果为0

SF:符号标志,操作结果为负。

 

 

比较指令:

指令

基于

描述

cmpb S2,S1

S1 – S2

比较字节,差关系

testb S2,S1

S1 & S2

测试字节,与关系

cmpw S2,S1

S1 – S2

比较字,差关系

testw S2,S1

S1 & S2

测试字,与关系

cmpl S2,S1

S1 – S2

比较双字,差关系

testl S2,S1

S1 & S2

测试双字,与关系

 

 

访问条件码指令:

指令

同义名

效果

设置条件

sete D

setz

D = ZF

相等/

setne D

setnz

D = ~ZF

不等/非零

sets D

 

D = SF

负数

setns D

 

D = ~SF

非负数

setg D

setnle

D = ~(SF ^OF) & ZF

大于(有符号>

setge D

setnl

D = ~(SF ^OF)

小于等于(有符号>=)

setl D

setnge

D = SF ^ OF

小于(有符号<)

setle D

setng

D = (SF ^ OF) | ZF

小于等于(有符号<=)

seta D

setnbe

D = ~CF & ~ZF

超过(无符号>)

setae D

setnb

D = ~CF

超过或等于(无符号>=)

setb D

setnae

D = CF

低于(无符号<)

setbe D

setna

D = CF | ZF

低于或等于(无符号<=)

 

 

跳转指令:

指令

同义名

跳转条件

描述

jmp   Label

 

1

直接跳转

jmp   *Operand

 

1

间接跳转

je     Label

jz

ZF

等于/

jne    Label

jnz

~ZF

不等/非零

js     Label

 

SF

负数

jnz    Label

 

~SF

非负数

jg     Label

jnle

~(SF^OF) & ~ZF

大于(有符号>)

jge    Label

jnl

~(SF ^ OF)

大于等于(有符号>=)

jl     Label

jnge

SF ^ OF

小于(有符号<

jle     Label

jng

(SF ^ OF) | ZF

小于等于(有符号<=)

ja     Label

jnbe

~CF & ~ZF

超过(无符号>)

jae    Label

jnb

~CF

超过或等于(无符号>=)

jb     Label

jnae

CF

低于(无符号<)

jbe    Label

jna

CF | ZF

低于或等于(无符号<=)

 

 

转移控制指令:(函数调用):

指令

描述

call    Label

过程调用,返回地址入栈,跳转到调用过程起始处,返回地址是call后面那条指令的地址

call    *Operand

leave

为返回准备好栈,为ret准备好栈,主要是弹出函数内的栈使用及%ebp

 

 

GCCC中潜入汇编代码:

asm( code-string [:output-list [ : input-list [ :overwrite-list]]]);

注意,后面的参数(如overwrite-list)如果为空则不要相应的“:”,而如果前面参数(如output-list)为空则需要用“:”占位。

如:

asm ("..."

    :                    //output需要占位

    : "r" (src)       //后面的Overwrites不能写,我测试的结果是写了编译不过

};


如:

Int ok_umul(unsigned x,unsigned y,unsigned *dest)

{

  int result;

asm(“movl %2 , %%eax; mull %3; movl %%eax,%0;\

           setae %dl; movzbl %%dl,%1”

           :  “=r” (*dest)  ,  “=r” (result)         //output

           :  “r” (x)  ,  “r” (y)                         //inputs

           :  “%ebx”  , “%edx”                        //Overwrites

);

 

return result;

}

我们用%0--%n表示输入的参数,”r”表示整数寄存器,”=”表示对其进行了赋值。%eax要写成%%eax,这是c语言字符串的规则,别忘了code-string就是一个c语言的字符串。

unix 守护进程

守护进程在Linux/Unix系统中有着广泛的应用。有时,开发人员也想把自己的程序变成守护进程。在创建一个守护进程的时候,要接触到子进程、 进程组、会晤期、信号机制、文件、目录和控制终端等多个概念。因此守护进程还是比较复杂的,在这里详细地讨论Linux/Unix的守护进程的编写,总结 出八条经验,并给出应用范例。

编程要点

1.屏蔽一些有关控制终端操作的信号。防止在守护进程没有正常运转起来时,控制终端受到干扰退出或挂起。示例如下:

signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
signal(SIGHUP ,SIG_IGN);

所有的信号都有自己的名字。这些名字都以“SIG”开头,只是后面有所不同。开发人员可以通过这些名字了解到系统中发生了什么事。当信号出现时,开发人员可以要求系统进行以下三种操作:
◆ 忽略信号。大多数信号都是采取这种方式进行处理的,这里就采用了这种用法。但值得注意的是对SIGKILL和SIGSTOP信号不能做忽略处理。
◆ 捕捉信号。最常见的情况就是,如果捕捉到SIGCHID信号,则表示子进程已经终止。然后可在此信号的捕捉函数中调用waitpid()函数取得该子进程 的进程ID和它的终止状态。另外,如果进程创建了临时文件,那么就要为进程终止信号SIGTERM编写一个信号捕捉函数来清除这些临时文件。
◆ 执行系统的默认动作。对绝大多数信号而言,系统的默认动作都是终止该进程。

对这些有关终端的信号,一般采用忽略处理,从而保障了终端免受干扰。

这类信号分别是,SIGTTOU(表示后台进程写控制终端)、SIGTTIN(表示后台进程读控制终端)、SIGTSTP(表示终端挂起)和SIGHUP(进程组长退出时向所有会议成员发出的)。

2.将程序进入后台执行。由于守护进程最终脱离控制终端,到后台去运行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。这就是常说的“脱壳”。子进程继续函数fork()的定义如下:

#include
#include
pid_t fork(void);

该函数是Linux/Unix编程中非常重要的函数。它被调用一次,但返回两次。这两次返回的区别是子进程的返回值为“0”,而父进程的返回值为子进程的ID。如果出错则返回“-1”。

3.脱离控制终端、登录会话和进程组。开发人员如果要摆脱它们,不受它们的影响,一般使用 setsid() 设置新会话的领头进程,并与原来的登录会话和进程组脱离。这只是其中的一种方法,也有如下处理的办法:

if ((fd = open("/dev/tty",O_RDWR)) >= 0) {
ioctl(fd,TIOCNOTTY,NULL);
close(fd);
}

其中/dev/tty是一个流设备,也是终端映射,调用close()函数将终端关闭。

4.禁止进程重新打开控制终端。进程已经成为无终端的会话组长,但它可以重新申请打开一个控制终端。开发人员可以通过不再让进程成为会话组长的方式来禁止进程重新打开控制终端,需要再次调用fork函数。
上面的程序代码表示结束第一子进程,第二子进程继续(第二子进程不再是会话组长)。

5. 关闭打开的文件描述符,并重定向标准输入、标准输出和标准错误输出的文件描述符。进程从创建它的父进程那里继承了打开的文件描述符。如果不关闭,将会浪费系统资源,引起无法预料的错误。关闭三者的代码如下:

for (fd = 0, fdtablesize = getdtablesize();
fd 0)
…… }

8.在Linux/Unix下有个syslogd的守护进程,向用户提供了syslog()系统调用。任何程序都可以通过syslog记录事件。

由于syslog非常好用和易配置,所以很多程序都使用syslog来发送它们的记录信息。一般守护进程也使用syslog向系统输出信息。 syslog有三个函数,一般只需要用syslog(...)函数,openlog()/closelog()可有可无。syslog()在 shslog.h定义如下:

#include
void syslog(int priority,char *format,...);

其中参数priority指明了进程要写入信息的等级和用途。第二个参数是一个格式串,指定了记录输出的格式。在这个串的最后需要指定一个%m,对应errno错误码。

应用范例

下面给出Linux下编程的守护进程的应用范例,在UNIX中,不同版本实现的细节可能不一致,但其实现的原则是与Linux一致的。

#include
#include
#include
main(int argc,char **argv)
{
time_t now;
int childpid,fd,fdtablesize;
int error,in,out;
/* 忽略终端 I/O信号,STOP信号 */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
signal(SIGHUP ,SIG_IGN);
/* 父进程退出,程序进入后台运行 */
if(fork()!=0) exit(1);
if(setsid()<0)exit(1);/* 创建一个新的会议组 */
/* 子进程退出,孙进程没有控制终端了 */
if(fork()!=0) exit(1);
if(chdir("/tmp")==-1)exit(1);
/* 关闭打开的文件描述符,包括标准输入、标准输出和标准错误输出 */
for (fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd++)
close(fd);
umask(0);/*重设文件创建掩模 */
signal(SIGCHLD,SIG_IGN);/* 忽略SIGCHLD信号 */
/*打开log系统*/
syslog(LOG_USER|LOG_INFO,"守护进程测试!\n");
while(1)
{
time(&now);
syslog(LOG_USER|LOG_INFO,"当前时间:\t%s\t\t\n",ctime(&now));
sleep(6);
}
}

此程序在Turbo Linux 4.0下编译通过。这个程序比较简单,但基本体现了守护进程的编程要点。读者针对实际应用中不同的需要,还可以做相应的调整。(

正则表达式备忘

正则表达式备忘
字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0$9 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。
\n 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (©)。
 

LiveCD 制作命令

find . | cpio -o -H newc | gzip > ../initrd.img


mkisofs -o spglivecd.iso -r -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table iso

linux汇编常见问题

1.gcc嵌入汇编
(1). 在gcc嵌入汇编中输入输出使用相同的寄存器?

static void * __memcpy(void * to, const void * from, size_t n)
{
 int d0,d1,d2;
 __asm__ __volatile__(
  "rep;movsl\n\t"
  "testb $2,%b4\n\t"
  "je 1f\n\t"
  "movsw\n"
  "1:\ttestb $1,%b4\n\t"
  "je 2f\n\t"
  "movsb\n"
  "2:"
  :"=&c" (d0), "=&D" (d1), "=&S" (d2)
  :"0" (n/4), "q" (n), "1" ((long) to), "2" ((long) from)
  :"memory");
 return (to);
}

操作数0,1,2和3,5,6使用相同的寄存器的理解:
a. 3,5,6在输入过程中将值n/4,to和from的地址读入ecx,edi,esi寄存器中;
b. 0,1,2在输出过程中将ecx,edi,esi寄存器中的值存入d0,d1,d2内存变量中。
c. 注意在上面的语句中也有"&"限定符,但输入和输出仍使用相同的寄存器,如操作数0和3都使用寄存器ecx,这是因为"0"限定的结果,如果

把"0" (n/4)换成"c" (n/4),则因为"=&c"的限定而使得编译时报错。

(2). 关于gcc嵌入式汇编中"&"限定符的作用?
"&"限定符用于输出操作数,使其唯一的使用某寄存器

int bar,foo;
__asm__ __volatile__(
 "call func \n\t"
 "mov ebx,%1"
 :"=a" (foo)
 :"r" (bar));

在gcc编译时默认会让bar也使用eax寄存器,如果把"=a"改为"=&a",那么foo将唯一使用eax,而让bar使用其它的寄存器。

(3). _start和main的关系?
main是gcc看到的程序入口点,而ld和as所看到的程序入口点其实是_start。libc库中的_start会调用main函数。
a. 编译带_start的汇编程序时的步骤:as -o a.o a.s,ld -o a a.o; gcc -g -c a.s,ld -o a a.o。(使用gcc编译可以增加调试选项-g,这

时不能直接用gcc -o a a.s编译的原因是gcc会默认在程序中查找main函数,并且会将libc中的_start加入进来。如果直接用gcc -o a a.s编译

,则会报两个错误"重复的_start"和"没找到main")
b. 编译带main的汇编程序或C程序时的步骤:gcc -o a a.s;gcc -o a a.c。

(4).section和.previous
将这两个.section和.previous中间的代码汇编到各自定义的段中,然后跳回去,将这之后的的代码汇编到上一个section中(一般是.text段),

也就是自定义段之前的段。.section和.previous必须配套使用。

2. AT&T汇编
(1).data,.section等都是伪操作,不能直接翻译成机器码,只有相应的assembler才能识别
(2).section将程序分成几个片断,如.data,.text,.bss
(3).globl 函数名表示该函数被export,并可以被其它文件中的函数调用
(4).bss可以用来申请一块空间,但不需要对其进行初始化
(5)使用内核定义函数如open,read等可以通过int $80中断来完成
(6)MOVL $FOO,%EAX是把FOO在内存中的地址放到EAX中,而MOVL FOO,%EAX是把FOO这个变量的内容放入EAX
(7).include "文件名",将其它文件包含进来
(8)如何在汇编中表示结构?如c语言中的如下结构:
struct para
{
 char Firstname[40];
 char Lastname[40];
 char Address[240];
 long Age;//4 bytes
}
在汇编中可以表示成:
.section data
record1:
.ascii "Fredrick\0"
.rept 31 #Padding to 40 bytes
.byte 0
.endr
.ascii "Bartlett\0"
.rept 31 #Padding to 40 bytes
.byte 0
.endr
.ascii "4242 S Prairie\nTulsa, OK 55555\0"
.rept 209 #Padding to 240 bytes
.byte 0
.endr
.long 45
其中.rept n和.endr表示重复两者之间的序列n次,可用于填充数据
(9)当汇编程序由多个文件构成时,可以采用以下方式编译与连接:
as write-records.s -o write-records.o (gcc -g -c write-records.s)
as write-record.s -o write-record.o (gcc -g -c write-record.s)
ld write-record.o write-records.o -o write-records
(10)如何在汇编语言中使用动态库中的函数?
#helloworld-lib.s
.section .data
helloworld:
.ascii "hello world\n\0"
.section .text
.globl _start
_start:
pushl $helloworld
call printf
pushl $0
call exit

as helloworld-lib.s -o helloworld-lib.o
ld -dynamic-linker /lib/ld-linux.so.2 -o helloworld-lib helloworld-lib.o -lc
产生动态库:ld -shared write-record.o read-record.o -o librecord.so
(11)使用汇编文件生成动态库
as write-record.s -o write-record.o
as read-record.s -o read-record.o
ld -shared write-record.o read-record.o -o librecord.so
as write-records.s -o write-records.o
ld -L . -dynamic-linker /lib/ld-linux.so.2 -o write-records -lrecord write-records.o
记得运行write-records时还需要将动态库路径加到/etc/ld.so.conf中,并运行ldconfig
(12)编译汇编文件时如何产生调试符号
as --gstabs a.s -0 a.o 或者gcc -g -c a.s

附录:
(1)函数调用时栈的情况
#Parameter #N <--- N*4+4(%ebp)
#...
#Parameter 2 <--- 12(%ebp)
#Parameter 1 <--- 8(%ebp)
#Return Address <--- 4(%ebp)
#Old %ebp <--- (%ebp)
#Local Variable 1 <--- -4(%ebp)
#Local Variable 2 <--- -8(%ebp) and (%esp)

(2)例子
 .include "external_func.s"

 .section .data
data_array:     #定义long型数组
 .long 3,67,34,0        
data_strings:    #定义字符串
 .ascii "Hello there\0"
data_long: #定义long型变量
 .long 5

 .section .bss
 .lcomm my_buffer, 500   #申请一块500字节的内存

 .section .text
 .equ LINUX_SYSCALL, 0x80 #定义符号LINUX_SYSCALL的值为0x80
 .globl _start
_start:
 pushl %edx
 movl data_long,%edx     #将data_long变量的值放入edx寄存器
 movl $data_long,%edx    #将data_long的地址放入edx寄存器
 popl %edx

 pushl $3      #push second argument
 pushl $2      #push first argument
 call power    #call the function
 addl $8, %esp #move the stack pointer back
 pushl %eax    #save the first answer before,calling the next function

 movl $1, %eax #exit (%ebx is returned)
 int $LINUX_SYSCALL    

 .type power, @function #定义函数power
power:
 pushl %ebp         #save old base pointer
 movl %esp, %ebp    #make stack pointer the base pointer
 subl $4, %esp      #get room for our local storage
 movl 8(%ebp), %eax #put first argument in %eax
 movl 12(%ebp), %ebx #put second argument in %ebx
 imull %ebx,%eax
 movl %ebp, %esp    #restore the stack pointer
 popl %ebp          #restore the base pointer
 ret