AT&T ASM

来源:互联网 发布:sys types.h windows 编辑:程序博客网 时间:2024/05/20 04:10

1.Syntax
Register Reference

  • 引用寄存器要在寄存器号前加百分号 movl %eax,%ebx
  • 80386有如下寄存器:
  • 32bit: %eax,%ecx,%edx,%ebx,%edi,%esi,%ebp,%esp
  • 16bit 8bit 寄存器分别上32bit的一部分
  • 6个段寄存器 %cs(code), %ds(data), %ss(stack),%es,%fs,%gs
  • 3个控制寄存器 %cr0 %cr2 %cr3
  • 6个debug寄存器 %db0 %db1 %db2 %db3 %db6 %db7
  • 2个测试寄存器 %tr6 %tr7
  • 8个浮点寄存器 %st(0) %st(1) %st(2) %st(3) %st(4) %st(5) %st(6) %st(7)

Operator Sequence
movl %eax,%ebx 从左到右 左边为源 右边为 目的操作数

Immediately Operator
立即数前面加上符号eg:movlor:para=0x04movlpara,%ebx

Symbol Constant
符号常数直接引用eg:
value: .long 0x12a3f2de
movl value,%ebx
如果写成movl $value,%ebx 则是将符号value的地址装入寄存器ebx

Length of Operator
b:byte w:word l:long
如果没有制定操作数的长度的话,编译器将按照目标操作数的长度来设置。 eg:
movb %al,%bl
mov 4,eg:push4

Sign and Zero Extension
在AT&T语法中,基本部分movs/movz(intel为movsx movzx)后面跟上源操作数的长度和目的操作数的长度。eg:
movsbl: movs from byte to long
而对于intel来说还有其他的符号扩展指令:cbw,cwde,cwd,cdq

Call and Jump
段内调用和跳转指令为 call ret jmp
段间调用和。。。。为 lcall lret ljmp 格式为:
lcall/ljmp SECTION,OFFSET
lret $STACK-ADJUST

Prefix:
字符串重复操作指令 rep repne
指定被操作的段 cs ds ss es fs gs
进行总线加锁 lock
指定地址和操作的大小 data16 addr16
eg:
repne
scas

Memory Reference
Intel语法间接内存引用的格式为:
section:[base+index*scale+displacement]
AT&T:
section:displacement(base,index,scale)
eg:
-4(%ebp): base=%ebp,section=ss index=0
foo(,%eax,4) index=%eax base=0 section=%ds
foo(,1): 这个表达式引用的是指针foo指向的地址所存放的值。
%gs:foo 表达式引用的是放置于%gs段里变量foo的值

如果call和jump操作在操作数前指定前缀* 则表示是一个 绝对地址调用/跳转。 否则操作数是一个相对地址。
任何指令如果其操作数是一个 内存操作,则指令必须指定它的操作尺寸。


2.gcc Inline ASM

2.1 Essential Inline ASM

__asm__("movl %esp,%eax");

or

__asm__("    movl $1,%eax    xor %ebx,%ebx    int $0x80");

or:

___asm__(    "movl $1,%eax\r\t"    "xor %ebx,%ebx\r\t"    "int $0x80");

基本的内联汇编格式 asm __volatile(“Instruction List”);

1.asm
是GCC关键字asm的宏定义

define __asm__ asm

2.Instruction List

__asm__("":::memory");

表示我对内存进行了改动。

内嵌汇编的指令的原则可以总结为:
- 任意两个指令要么被分号分开,要么被放在两行
- 放在两行的方法既可以从过\n的方法实现,也可以真正的放在两行;
- 可以使用1对或者多对引号,每对引号里面可以放任一多条指令,所有的指令都要放到引号中。

  1. volatile

volatitle是gcc的关键字volatile的宏定义

#define __volatitle__ volatitle

它的作用是向GCC声明 不要改动我们写的Instruction List,否则当使用-o进行编译是,GCC将会自己觉得是否需要进行优化。

2.2 Inline ASM with C/C++ Expression
带有C/C++表达式的内联汇编格式位
“`
asm volatitle(“Instruction List”
:output
: Input
:Clobber/Modify
);

1.output

__asm__("movl %%cr0,%0":"=a" (cr0));

=表示输出 +表示输入和输出
Output域可以有多个输出表达式,但中间要用逗号分开

2.Input
Input域的内容用来指定当前内联汇编的语句的输入

__asm__("movol %0,%%db7": : "a" (cpu->db7));

3.Operation Constraint
每一个Input和Output表达式都必须指定自己的操作约束。
这里讨论在386平台上所可能使用的操作约束。

3.1 Register Constraint
当输入需要借助一个寄存器的时候,需要为其指定一个寄存器约束。可以直接指定寄存器的名字

__asm__ __volititle__("movl %0,%%cr0"::"eax"(cr0));

3.2 Memory Constraint
如果一个Input/Output 操作表达式表现位一个内存地址,不像借助与任何一个寄存器 则可以使用内存约束。eg:

__asm__ ("lidt %0":"=m"(__idt_addr));

对于c++内联汇编理解不够深入。以后再进行学习。

0 0