linux汇编gas,linux gas汇编一些记录

有时侯我们会想这么写一条汇编语句:

/* 错误写法 */

asm volatile ("movl %0(%%esp), %x" : /* no outputs */ : "i" (4) );

但这样子gcc会报错:

Error: junk `(%esp)' after expression

原因是,%0是立即数(用"i"约束的),于是gcc会把这条汇编指令变成:

movl $4(%esp), x

于是它就会报错,因为多了一个$符号 -- 这在GNU as的寄存器间接寻址中是不允许的。需要改成:

asm volatile ("movl (%%esp), %x" : /* no outputs */ : "i" (4) );

例如下面的程序:

/* WARNING: WRONG! */

$ cat -n dollar.c

1  #include 2

3  int main()

4  {

5          long var = 0;

6

7          asm volatile

8                  ("pushl $0x11223344\n\t"

9                   "pushl $0x55667788\n\t"

10                   "movl  %1(%%esp), %0\n\t"

11                   "addl  $8, %%esp "     /* 消减前面两条push指令导致的esp值改变 */

12

13                   : "=r" (var)

14                   : "i" (4)

15                   : "cc", "esp"

16                  );

17

18          printf("var is 0x%x\n", var);

19          return 0;

20  }

使用gcc编译:

$ gcc dollar.c -m32 -S

查看一下生成的dollar.s文件,我们看到inline asm被gcc转换成:

pushl   $0x11223344

pushl   $0x55667788

movl    $4(%esp), x

addl    $8, %esp

如上所说,"$4(%esp)"这种寻址方式是无法通过GNU as的,因为多了一个$符号。 GCC为我们提供了一些方法,

允许我们消除那个无用的$符号:

消除%0的$符号

%n0         消除%0的$符号,并添加负号。 (例如%0是4,那么%n0就是-4)

%l0         和%0相同,但是只用于跳转指令的目标

%0本来是一个地址,例如0x8048000,放在x中。 现在把它转换为寄存器间接寻址,亦即: (x)

%P0         相同,消除%0的$符号

让我们再回头来看上面的dollar.c程序。 我们把第10行改成:

"movl (%%esp), %0\n\t"

然后再次用gcc dollar.c -m32 -S编译,查看dollar.s中的相关代码,发现这条汇编语句变成了:

movl    4(%esp), x

这正是我们期待的结果。 至于%n0、%l0和%P0,留给读者自己试验一下。

看一下的例子:

$ cat a.c

#include int main(void)

{

char c = 0;

asm volatile ("movb , %0"

: "=r" (c)

/* GNU ld 为IA32连接程序时,默认在从0x8048001开始的地方保存'E'、'L'、'F'三个字母 */

: "r" (0x8048001)

);

printf("c is %c\n", c);

return 0;

}

编译运行:

$ gcc -m32 a.c

$ ./a.out

c is E

成功的打印出了字母'E'。 倘若我们用-S生成*.s文件,再查看其中的相关汇编语句:

movb (x), %al

这说明gcc为0x8048001接合了eax寄存器,这就是%1;而,则把它转换为间接寻址,也就是『(%x)』。

阅读(1889) | 评论(0) | 转发(0) |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值