AT&ampamp;T汇编语言

上传人:灯火****19 文档编号:125166932 上传时间:2020-03-15 格式:PDF 页数:31 大小:105.69KB
返回 下载 相关 举报
AT&ampamp;T汇编语言_第1页
第1页 / 共31页
AT&ampamp;T汇编语言_第2页
第2页 / 共31页
AT&ampamp;T汇编语言_第3页
第3页 / 共31页
AT&ampamp;T汇编语言_第4页
第4页 / 共31页
AT&ampamp;T汇编语言_第5页
第5页 / 共31页
点击查看更多>>
资源描述

《AT&ampamp;T汇编语言》由会员分享,可在线阅读,更多相关《AT&ampamp;T汇编语言(31页珍藏版)》请在金锄头文库上搜索。

1、AT 看起来很熟悉吧 asm movl 1 eax SYS exit xor ebx ebx int 0 x80 asm movl 1 eax r t xor ebx ebx r t int 0 x80 asm volatile Instruction List 6 Developing Your Own Unix Like OS on IBM PC 1 asm asm 是 GCC 关键字 asm 的宏定义 asm 或 asm 用来声明一个内联汇编表达式 所以任何一个内联汇编表达式都是以 它开头的 是必不可少的 2 Instruction List Instruction List 是汇编指令

2、序列 它可以是空的 比如 asm volatile 或 asm 都是完全合法的内联汇编表达式 只不过这两条语句没有什么意义 但并非所 有 Instruction List 为空的内联汇编表达式都是没有意义的 比如 asm memory 就非常有意义 它向 GCC 声明 我对内存作了改动 GCC 在编译的时候 会将此因素 考虑进去 我们看一看下面这个例子 在这段代码中 那条内联汇编是被注释掉的 在这条内联汇编之前 内存指针 p 所指 向的内存被赋值为 9999 随即在内联汇编之后 一条 if 语句判断 p 所指向的内存与 9999 是否相等 很明显 它们是相等的 GCC 在优化编译的时候能够很聪

3、明的发现这一点 我 们使用下面的命令行对其进行编译 选项 O 表示优化编译 我们还可以指定优化等级 比如 O2 表示优化等级为 2 选项 S 表示将 C C 源文件编译为汇编文件 文件名和 C C 文件一样 只不过扩展名由 c 变 define asm asm cat example1 c int main int argc char argv int p int argc p 9999 asm memory if p 9999 return 5 return p gcc O S example1 c AT asm movl eax ebx sti popl edi subl ecx ebx

4、asm movl eax ebx sti n t popl edi subl ecx ebx AT subl ecx ebx asm movl eax ebx sti n t popl edi subl ecx ebx asm movl eax ebx sti n t popl edi n subl ecx ebx asm movl eax ebx sti n t popl edi subl ecx ebx asm align 2 n t movl eax ebx n t test ebx ecx n t jne error n t sti n t error popl edi n t sub

5、l ecx ebx 10 Developing Your Own Unix Like OS on IBM PC 3 volatile volatile 是 GCC 关键字 volatile 的宏定义 volatile 或 volatile 是可选的 你可以用它也可以不用它 如果你用了它 则是向 GCC 声明 不要动我所写的 Instruction List 我需要原封不动的保留每一条指令 否则当 你使用了优化选项 O 进行编译时 GCC 将会根据自己的判断决定是否将这个内联汇编表 达式中的指令优化掉 那么 GCC 判断的原则是什么 我不知道 如果有哪位朋友清楚的话 请告诉我 我 试验了一下 发

6、现一条内联汇编语句如果是基本内联汇编的话 即只有 Instruction List 没有 Input Output Clobber 的内联汇编 我们后面将会讨论这一点 无论你是否使用 volatile 来修饰 GCC 2 96 在优化编译时 都会原封不动的保留内联汇编中的 Instruction List 但或许我的试验的例子并不充分 所以这一点并不能够得到保证 为了保险起见 如果你不想让 GCC 的优化影响你的内联汇编代码 你最好在前面都加 上 volatile 而不要依赖于编译器的原则 因为即使你非常了解当前编译器的优化原则 你也无法保证这种原则将来不会发生变化 而 volatile 的含

7、义却是恒定的 2 2 Inline ASM with C C Expression GCC 允许你通过 C C 表达式指定内联汇编中 Instrcuction List 中指令的输入和输 出 你甚至可以不关心到底使用哪个寄存器被使用 完全靠 GCC 来安排和指定 这一点可 以让程序员避免去考虑有限的寄存器的使用 也可以提高目标代码的效率 先来看几个例子 define volatile volatile asm memory 前面提到的 asm mov eax ebx b rv a foo eax ebx asm volatile lidt 0 m idt descr asm subl 2 0

8、n t sbbl 3 1 a endlow d endhigh g startlow g starthigh 0 endlow 1 endhigh AT和 asm 都是合法的写法 如果 Output Input Clobber Modify 都为空 Output Input 之前的冒号 既 可以省略 也可以不省略 如果都省略 则此汇编退化为一个基本内联汇编 否则 仍然是一个带有 C C 表达式的内联汇编 此时 Instruction List 中的寄存器写法 要遵守相关规定 比如寄存器前必须使用两个百分号 而不是像基本汇编格 式一样在寄存器前只使用一个百分号 比如 asm mov eax eb

9、x asm mov eax ebx 和 asm mov eax ebx 都是正确的写法 而 asm mov eax ebx asm mov eax ebx 和 asm mov eax ebx 都是错误的写法 如果 Input Clobber Modify 为空 但 Output 不为空 Input 前的冒号 既可以 省略 也可以不省略 比如 asm mov eax ebx b foo asm mov eax ebx b foo 都是正确的 如果后面的部分不为空 而前面的部分为空 则前面的冒号 都必须保留 否则无 法说明不为空的部分究竟是第几部分 比如 Clobber Modify Output

10、 为空 而 Input 不为空 则 Clobber Modify 前的冒号必须省略 前面的规则 而 Output 前的冒号必须为保留 如果 Clobber Modify 不为空 而 Input 和 Output 都为空 则 Input 和 Output 前的冒号都必须保留 比如 asm mov eax ebx a foo 和 asm mov eax ebx ebx asm volatile Instruction List Output Input Clobber Modify 12 Developing Your Own Unix Like OS on IBM PC 从上面的规则可以看到另外

11、一个事实 区分一个内联汇编是基本格式的还是带有 C C 表达式格式的 其规则在于在 Instruction List 后是否有冒号 的存在 如果没有则 是基本格式的 否则 则是带有 C C 表达式格式的 两种格式对寄存器语法的要求不同 基本格式要求寄存器前只能使用一个百分号 这一点和非内联汇编相同 而带有 C C 表达式格式则要求寄存器前必须使用两个百分号 其原因我们会在后面讨论 1 Output Output 用来指定当前内联汇编语句的输出 我们看一看这个例子 这个内联汇编语句的输出部分为 r cr0 它是一个 操作表达式 指定了一个输出操 作 我们可以很清楚得看到这个输出操作由两部分组成

12、括号里的部分 cr0 和引号引住的部 分 a 这两部分都是每一个输出操作必不可少的 括号里的部分是一个 C C 表达式 用来保存内联汇编的一个输出值 其操作就等于 C C 的相等赋值 cr0 output value 因此 括号中的输出表达式只能是 C C 的左值表达式 也就是说它只能是一个可以合法 的放在 C C 赋值操作中等号 左边的表达式 那么右值 output value 从何而来呢 答案是引号中的内容 被称作 操作约束 Operation Constraint 在这个例子中操 作约束为 a 它包含两个约束 等号 和字母 a 其中等号 说明括号中左值表达式 cr0 是一个 Write

13、Only 的 只能够被作为当前内联汇编的输入 而不能作为输入 而字母 a 是 寄存器 EAX AX AL 的简写 说明 cr0 的值要从 eax 寄存器中获取 也就是说 cr0 eax 最终这一点被转化成汇编指令就是 movl eax address of cr0 现在你应该清楚了吧 操 作约束中会给出 到底从哪个寄存器传递值给 cr0 另外 需要特别说明的是 很多文档都声明 所有输出操作的操作约束必须包含一个等 号 但 GCC 的文档中却很清楚的声明 并非如此 因为等号 约束说明当前的表达式 是一个 Write Only 的 但另外还有一个符号 加号 用来说明当前表达式是一个 Read Wr

14、ite 的 如果一个操作约束中没有给出这两个符号中的任何一个 则说明当前表达 式是 Read Only 的 因为对于输出操作来说 肯定是必须是可写的 而等号 和加号 都表示可写 只不过加号 同时也表示是可读的 所以对于一个输出操作来说 其操作约 束只需要有等号 或加号 中的任意一个就可以了 二者的区别是 等号 表示当前操作表达式指定了一个纯粹的输出操作 而加号 则 表示当前操作表达式不仅仅只是一个输出操作还是一个输入操作 但无论是等号 约束还 是加号 约束所约束的操作表达式都只能放在 Output 域中 而不能被用在 Input 域中 另外 有些文档声明 尽管 GCC 文档中提供了加号 约束

15、但在实际的编译中通不过 我不知道老版本会怎么样 我在 GCC 2 96 中对加号 约束的使用非常正常 asm movl cr0 0 a cr0 AT asm volatile movl cr0 0 a cr0 return 0 gcc S example2 c cat example2 s main pushl ebp movl esp ebp subl 4 esp movl 5 4 ebp cr0 5 APP movl cr0 eax NO APP movl eax eax movl eax 4 ebp cr0 eax movl 0 eax leave ret cat example3 c

16、int main int argc char argv int cr0 5 asm volatile movl cr0 0 a cr0 return 0 14 Developing Your Own Unix Like OS on IBM PC 从编译的结果可以看出 当使用加号 约束的时候 cr0 不仅作为输出 还作为输入 所使用寄存器都是寄存器约束 字母 a 表示使用 eax 寄存器 指定的 关于寄存器约束我们 后面讨论 在 Output 域中可以有多个输出操作表达式 多个操作表达式中间必须用逗号 分开 例如 2 Input Input 域的内容用来指定当前内联汇编语句的输入 我们看一看这个例子 例中 Input 域的内容为一个表达式 a cpu db7 被称作 输入表达式 用来表示一 个对当前内联汇编的输入 像输出表达式一样 一个输入表达式也分为两部分 带括号的部分 cpu db7 和带引号 的部分 a 这两部分对于一个内联汇编输入表达式来说也是必不可少的 gcc S example3 c cat example3 s main pushl ebp movl esp ebp sub

展开阅读全文
相关资源
相关搜索

当前位置:首页 > IT计算机/网络 > 其它相关文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号