GCC 内联汇编

所需积分/C币:50 2018-10-28 13:08:39 185KB PDF
45
收藏 收藏
举报

gcc 内联汇编 1 AT&T 与 INTEL 的汇编语言语法的区别 1.1 大小写 1.2 操作数赋值方向 1.3 前缀 1.4 间接寻址语法 1.5 后缀 1.6 指令 2 GCC 内嵌汇编 2.1 简介 2.2 内嵌汇编举例 2.3 语法 2.3.1 汇编语句模板 2.3.2 输出部分 2.3.3 输入部分 2.3.4 限制字符 2.3.5 破坏描述部分 2.4GCC 如何编译内嵌汇编代码
都是可选的,在指定 而没有显式指定 的情况下使用默认值 不需要加前缀 指令后缀 语法中大部分指令操作码的最后一个字母表示操作数大小,表示 一个字节);表示 (,个字节);表 (,个字节)。 中处理内存操作数时也有类似的语法如: 例 汇编指令中,操作数扩展指令有两个后缀,一个指定源操作数的字长,另 个指定日标操作数的字长。 的符号扩展指令的为 零扩展指令 为 (相应的 指令为 和 )。因此 表示对寄存器 中的字节数据进行字节到长字的符号扩展,计算结果存放在寄存器 中。卜面是一些允许的操作数扩展后缀: 字节长字 ,字节 ,字长字 跳转指令标号后的后缀表示眺转方向,表示向前( 表示向后() 例 指令 汇编与 汇编指令基本相同,差别仅在话法上:。关于每条指令的语 法可以参考 内嵌汇编 简介 内核代码绝大部分使用 语言编写,只有一小部分使用汇编语言编写,例如与特定体系结构相关的代码和 对性能影响很大的代码 提供了内嵌汇编的功能,可以在代码中直接内 嵌汇编语言语句,大大方便了程序设计 简单的内嵌汇编很容易理解 例 表示后面的代码为内嵌汇编, 是 的别名。 表示编译器不要优化代码,后面的指令保留原样 是它的别名。括号里面是汇编指令。 内嵌汇编举例在内嵌汇编中, 可以将语言表达式指定为汇编指令的操作数,而且不用去管如何将 语言表达式的值读入哪个寄存器,以及如何将计算结果写回变量,你只要告 诉程序中语言表达式与汇编指令操作数之间的对应关系即可 会自动 插入代码完成必要的操作 使用内嵌汇编,要先编写汇编指令模板,然后将语言表达式与指令的操 作数相关联,并牛诉对这些操作有哪些限制条件。例如在下面的汇编语句: 是指令模板 和代表指令的操作数,称为占位符, 内嵌汇编靠它们将语言表达式与指令操作数相对应。指令模板后亩川小括号 括起来的是语言表达式,本例中只有两个: 和 他们按照出 现的顺序分别与指令操作数 ,对应;注意对应顺序:第一个表 达式对应 第二个表达式对应 ,依次类推,操作数至多有个,分别用 ,表示。在 每个操作数前面有一个用引号括起来的字符串,字符串的内容是对该操作数的限 制或者说要求。 前面的限制字符串是,其中表示 是输 出操作数,表示需要将 与某个通用奇存器相关联,先将操作数的值读 入寄存器,然后在指令中使用相应寄存器,而不是 本身,当然指令执行 完后需要将寄存器中的值存入变量 ,从表面上看好像是指令直接对 进行操作,实际上做了隐式处理,这样我们可以少写一些指令。 前面的表示该表达式需要先放入某个寄存器,然后在指令中使用该寄 存器参加运算。 我们将上:面的内嵌代码放到一个源文件中,然后使用 得到该 文件源代码相对应的汇编代码,然后査看一下汇编代码,看看是如何处理 的 源文件如下内容如下,注意该代码没有实际意义,仅仅作为例子 对应的汇编代码如下 行号 代码 解释 对应语言语句 插入的注释,表示内嵌汇编开始 我们的内嵌汇编语句 插入的注释,表示内嵌汇编结束 将结果存入 变量 从汇编代码可以看出,第行和第行是,自动增加的代码 根据限定字符串决定如何处理表达式,本例两个表达式都被指定为型,所 以先使用指令: 将读入寄存器 也指定一个寄存器与输出变量 相关,本例也是,等得到操作结果后再使用指令: 将寄存器的值写回变量 中。从上面的汇编代码我们可以看出与 和 相关连的寄存器都是 使用,替换内嵌汇编指令模 板中的, 显然这一句可以不要。但是没有优化,所以这句没有被去掉。 由此可见,表达式或者变量与寄存器的关系由 自动处理,我们只需使用 限制字符串指导如何处理即可。限制字符必须与指令对操作数的要求相匹 配,否则产生的汇编代码将会有错,读者可以将上例中的两个,都改为 ,表示操作数放在内存,而不是寄存器中,编译后得到的结果是: 很明显这是一条非法指令,因此限制字符串必须与指令对操作数的要求匹配。例 如指令允许寄存器到寄存器,立即数到寄存器等,但是不允许内存到内存 的操作,因此两个操作数不能同吋使用作为限定字符。 语法 内嵌汇编语法如下: 汇编语句模板 输出部分 输入部分 破坏描述部分 共四个部分:汇编语句模板,输岀部分,输入部分,破坏措述部分,各部分使 用格开,汇编语句模板必不可少,其他三部分可选,如果使用了后面的部分, 而前面部分为空,也需要用格开,相应部分内谷为空。例如 汇编语句模板 汇编语句模板由汇编语句序列组成,语句之间使用 分开。 指令屮的操作数可以使用占位符引用语言变量,操作数占位符最多个,名 称如下:, 指令中使用占位符表小的操作数,总被视为 型(,个字节),但对其施加的操作根据指令可以是字或者字节,当把操作数 当作字或者字节使用时,默认为低宇或者低字节。对字节操作可以显式的指明是 低字节还是次字节。方法是在和序号之间插入一个字母,代表低字节 代表高字节,例如: 输出部分 输出部分描述输岀操作数,不同的操作数措述符之间用逗号格开,每个操作 数描述符由限定字符串和语言变量组成ε每个输出操作数的限定字符串必须 包含表示他是一个输出操作数。 例 描述符字符串表示对该变量的限制条件,这样就可以根据这些条件决 定如何分配寄存器,如何产生必要的代码处理指令操作数与表达式或变量 之间的联系。 输入部分 输入部分描述输入操作薮,不同的操作数描述符之间使用逗号格开,每个操作数 描述符由限定字符串和语言表达式或者语言变量组成。 例 例二( 后例功能是将 的第位设为。第一个占位符与,语言变量 对应,第二个占位符与,话言变量对应。因此上面的汇编语句代码与 下面的伪代码等价: ,该指令的两个操作数不能全是内存变量,因此将的限定字 符串指定为,将,与立即数或者寄存器相关联,这样两个操作数屮只有 为内存变量 限制字符 限制字符列表 限制字符有很多种,有些是与特定体系结构相关,此处仅列出常用的限定字符和 中可能用到的一些常用的限定符。它们的作用是指示编译器如何处理其后 的语言变量与指令操作数之间的关系,例如是将变量放在寄存器中还是放在 内存中等,下表列出了常用的限定字母。 分类限定符描述通用寄存器 将输入变量放入 这里有一个问题:假设已经被使用,那怎么办? 其实很简单:因为知道已被使用,它在这段汇编代码的起始处插入 一条语句 将内容保存到堆栈,然后在这段代码结束处再增 加一条语句 ,恢复的内容 将输入变量放入 将输入变量放入 将输入变量放入 s"将输入变量放入esi D"将输入变量放入edi 将输入变量放入 中的一个将输入变量放入通用寄 行器,也就是 中的一个把和 合成一个位的寄存器 内存变量 操作数为内存变量,但是其寻址方式是偏移量类型,也即是基址寻址,或者 是基址加变址寻址 操作数为内存变量,但寻址方式不是偏移量类型 操作数为内存变量,但寻址方式为自动增量 操作数是一个合法的内存地址(指针) 寄存器或内存 将输入变量放入, 屮的一个或者作为内存变量 操作数可以是任何类型 立即数 之间的立即数(用于位移位指令) 之间的立即数(用于位移位指令) ,之间的立即数(用于指令) 立即数 立即数,有些系统不支持除字以外的立即数,这些系统应该使川而不是 匹配 表示用亡限制的操作数与某个指定的操作数匹配 也即该操作数就是指定的那个操作数,例如用去描述%操作数,那么 引用的其实就是操作数,注意作为限定符字母的 ,与指令中 的%—%的区别,前者描述操作数,后者代表操作数。后面有详细摧述 该输岀操作数不能使用过和输入操作数相同的寄存器后亩有详细描述操作数 类型 操作数在指令中是只写的(输出操作数) 操作数在指令中是读写类型的(输入输出操作数) 浮点数 浮点寄存器 第一个浮点寄存器 第二个浮点寄存器 标准的 浮点常数 该操作数可以和下一个操作数交换位冒 例如的两个操作数可以交换顺序(当然两个操作数都不能是立即数) 部分注释,从该字符到其后的逗号之间所有字母被忽略 表示如果选用寄存器,则其后的字母被忽略 现在继续看上面的例子, 表示 为内存变量( 而且是输出变量() 表示,为 之间的立即数()或者一个寄存器操作数()。 匹配限制符 指令集中许多指令的操作数是读写型的(读写型操作数指先读取原米 的值然后参加运算,最后将结果写回操作数),例如 ,它的作用 是将操作数与操作数的和存入操作数,因此操作数是读写型操 作数。老版木的对这种类型操作数的支持不是很好,它将操作数严格分为 输入和输出两种,分别放在输入部分和输出部分,而没有一个单独部分描述读写 型操作数,因此在屮读写型的操作数需要在输入和输出部分分别描述,靠 匹配限制符将两者关联到一起注意仪在输入和输出部分使用相同的变量,但 是不用匹配限制符,产生的代码很可能不对,后面会分析原因 匹配限制符是一位数 ,,分别表示它限制的表达式 分别与占位符, 对应的变量匹配。例如使用作为 的限制字符,那么和%表示同一个,变量。 看下下面的代码就知道为什么要将读写型操作数,分别在输入和输岀部分加 以描述。该例功能是求 的和,然后存入 对应的汇编代码为: 为输入型变量,而且需要放在寄存器中 给它分配的寄存器是 ,在执行之前 ,的内容已经是 的值。可见对于使用 限制的输入型变量或者表达式,在使用之前会插入必要的代码将他们的值 读到寄存器;型变量则不需要这步。读入 后执行 显然 的值不对,需要先读入 的值才行。再往后看: 和 的作用是将结果存回 ,分配给 的寄存器与 分配给的一样,都是。综上可以总结出如下几点 仗用限制的输入变量, 先分配一个寄存器,然后将值读入寄存器, 最后用该寄存器替换占位符 使用限制的输出变量, 会分配一个寄存器,然后用该寄存器替换占 位符,但是在使用该奇存器之前并不将变量值先读入寄存器 认为所有输 出变量以前的值都没有用处,不读入寄存器(可能是因为 汇编源于 架构处理器的汇编语言在处理器中大部分指令的输入输出明显分开,而不 像 那样一个操作数既做输入又做输出,例如 和是 输入,是输岀,输入和输岀分开,没有使用输入输岀型操作数,这样我们就 可以认为对应的操作数原来的值没有用处,也就没有必要先将操作数的值读 入,因为这是浪费处理器的期),最后插入代码,将寄存器的 值写回变量; 输入变量使用的寄存器在最后一处使用它的指令之后,就可以挪做其他用 处,因为已经不再使用。例如上例中的。在执行完之后就作为与 对应的寄存器。因为第二条,上面的内嵌汇编指令不能奏效,因此需要在 执行之前把 的值读入寄存器,也许再将 放入输入部分就可 以了(因为第一条会保证将 先读入寄存器)。修改后的指令如下(为了 更容易说明问题将 限制符由,改为):

...展开详情
试读 20P GCC 内联汇编
立即下载 身份认证后 购VIP低至7折
一个资源只可评论一次,评论内容不能少于5个字
您会向同学/朋友/同事推荐我们的CSDN下载吗?
谢谢参与!您的真实评价是我们改进的动力~
  • 分享达人

关注 私信
上传资源赚钱or赚积分
最新推荐
GCC 内联汇编 50积分/C币 立即下载
1/20
GCC 内联汇编第1页
GCC 内联汇编第2页
GCC 内联汇编第3页
GCC 内联汇编第4页

试读结束, 可继续读2页

50积分/C币 立即下载