AT&T编码格式
mov %eax(源),%ebx(目的)
mov $value,%ebx 将变量value的地址给ebx
mov $4,%ebx 传立即数
mov value,%ebx 符号常数直接引用
mov $value,%ebx 引用符号地址
操作数长度 b(byte), w(word),l(long)
movw %ax,%bx 指定操作数长度
远转移
ljump $section,$offset
远调用
lcall $section,$offset
远程返回指令
lret $stack_adjust
ret far stack_adjust
寻址
section:disp(base,index,scale)
section:[base+index*scale+disp]
movl -4(%ebp),%eax 移动32位数到eax,ebp的地址-4的地址中的内容
movl array(,%eax,4),%eax base为array + eax*4
movw array(%ebx,%eax,4),%cx 将[ebx+4*eax+array]地址上的值给cx
movb $4,%fs:(%eax) 将立即数4放到fs:eax fs段中
movl $0x4,%eax <=> temp = 0x4
movl $-147,(%eax) <=> *p=-147
movl (%eax),%edx <=> temp=*p
movl %eax,(%edx) <=> *p=temp
movl %eax,%edx <=> temp2=temp1
嵌入式汇编语句
插入c代码汇编的片断分成四部分,以":
"加以分隔,其一般形式为:
指令部: 输出部: 输入部: 损坏部
这里需要双%%,区别于%0,%1等
下面例子里没有损坏部,在损坏部常常会以”memory"为约束条件,表示操作完成后内存中的内容已经有改变,若有寄存器指向则数据已不一致。
_asm_("asm statements":outputs:input:registers-modified);
__asm__("push %%fs\n\t"
"push %%ds\n\t"
"movb %%fs:%2,%%al\n\t" 取段fs:偏移地址为*addr(2即为输入从左到右数0 1 2 第2个)
"addl $8,%%esp\n\t"
:"=a(_res):"0"(seg),"m"(*(addr));"r" (i):"ax","cx","dx");
输出为a,且将a的值赋给res
输入 seg和*addr为前面定义的变量,0为与输出位置相同位置使用同一个寄存器,此处
即为res,m代表内存,m为内存地址
表示约束条件的字母有很多,主要有:
0
-9
嵌入式汇编程序规定把输出和输入寄存器按统一顺序编号,顺序是从输出寄存器序列从左到右从上到下以“%0”开始,分别记为%0、%1···%9。
符号 | 表示 |
---|---|
m,v 和 o | –表示内存单元; |
r | –表示任何寄存器 |
q | – 表示寄存器eax, ebx, ecx, edx 之一 |
i 和 h | –表示直接操作数 |
E 和 F | –表示浮点数 |
g | –表示“任意” |
a,b,c,d | – 分别表示要求使用寄存器eax, ebx, ecx或edx |
S,D | – 分别表示要求使用寄存器esi或edi |
I | –表示常数(0至31) |
#由于是16位的cpu,只能有16位的段内偏移量,故最大的段长度为64Kb
bit [16] 或者 bit 32 #是伪指令用来 指明其后的指令应该被编译成16位的还是32位的
段选择符(Selector)