linux c语言编程内嵌汇编,gcc编译c语言中内嵌汇编

gcc编译c语言中内嵌汇编

--AT&T and Intel 汇编语法对照

寄存器命名:

AT&T:  %eax

Intel: eax

AT&T 语法源地址在左侧,目的地址在右侧与Intel 方式语法相反

将eax值传入ebx

AT&T:  movl %eax, %ebx

Intel: mov ebx, eax

AT&T 语法在立即数前有前缀$.

AT&T:  movl $0x0h, %eax

Intel: mov eax,0x0h

AT&T 语法在操作符后跟表示操作数类型的后缀b,w,l分别表示字节,字,双字,相当于伪操作符ptr,如果不加的话GAS会guess

AT&T:  movw %ax, %bx

Intel: mov bx, ax

内存寻址方式

AT&T:  immed32(basepointer,indexpointer,indexscale)

Intel: [basepointer + indexpointer*indexscale + immed32]

地址计算公式为:

immed32 + basepointer + indexpointer * indexscale

直接寻址

AT&T:  _a

Intel: [_a]

间接寻址

AT&T:  (%eax)

Intel: [eax]

相对寻址

AT&T: _variable(%eax)

Intel: [eax + _variable]

AT&T:  _array(,%eax,4)

Intel: [eax*4 + array]

C 代码: *(p+1) p定义为char *

AT&T:  1(%eax) where eax has the value of p

Intel: [eax + 1]

结构体数组寻址,结构体长度为8,下标存于eax,结构体内偏移地址存于ebx,_array为结构体数组首地址

AT&T:  _array(%ebx,%eax,8)

Intel: [ebx + eax*8 + _array]

函数内部实现交换

1、输入与输出变量相同

汇编代码部分标准的交换实现,输入部分用0寄存器表示"=r"(a)中所指定的寄存器即输入与输出变量相同

int main()

{                                                                              804842c:      mov    0xfffffff4(%ebp),%ecx

int a = 10, b = 0;                                                    804842f:      mov    0xfffffff0(%ebp),%edx

printf("before swap: a = %2d, b = %2d\n", a , b);   8048432:      mov    %ecx,%ebx

__asm__("nop;                                                      8048434:      mov    %edx,%esi

movl %0, %%eax;                                        8048436:      nop

movl %1, %0;                                              8048437:      mov    %ebx,%eax

movl %%eax, %1;                                        8048439:      mov    %esi,%ebx

nop;"                                                            804843b:      mov    %eax,%esi

:                                                                    804843d:      nop

"=r"(a), "=r"(b)                                             804843e:      mov    %ebx,%edx

:                                                                    8048440:      mov    %esi,%ecx

"0"(a), "1"(b)                                                8048442:      mov    %edx,%eax

:                                                                    8048444:      mov    %eax,0xfffffff4(%ebp)

"%eax"                                                         8048447:      mov    %ecx,%eax

);                                                                   8048449:      mov    %eax,0xfffffff0(%ebp)

printf("after  swap: a = %2d, b = %2d\n", a, b);

return 0;

}

2、输入与输出用不同的寄存器,&表示输入输出需要分配不同的寄存器

int main()

{

int a = 10, b = 0;

printf("before swap: a = %2d, b = %2d\n", a, b);          804842b:      mov    0xfffffff8(%ebp),%edx

__asm__("nop;                                                            804842e:      mov    0xfffffff4(%ebp),%eax

movl %2, %1;                                                     8048431:      nop

movl %3, %0;                                                     8048432:      mov    %edx,%ebx

nop;"                                                                   8048434:      mov    %eax,%ecx

:                                                                           8048436:      nop

"=&r"(a), "=&r"(b)                                              8048437:      mov    %ecx,%eax

:                                                                           8048439:      mov    %ebx,%edx

"r"(a), "r"(b)                                                        804843b:      mov    %eax,%eax

);                                                                         804843d:      mov    %eax,0xfffffff8(%ebp)

printf("after  swap: a = %2d, b = %2d\n", a , b);           8048440:      mov    %edx,%eax

return 0;                                                                       8048442:      mov    %eax,0xfffffff4(%ebp)

}

3、交换函数,需要间接寻址

#include

void swap(int* x, int* y)     08048400 :

{                                                                                          8048400:      push   %ebp

__asm__("nop;                                                             8048401:      mov    %esp,%ebp

movl (%0), %%eax;                                            8048403:      push   %ebx

movl (%1), %%ebx;                                            8048404:      mov    0x8(%ebp),%ecx

movl %%ebx, (%0);                                            8048407:      mov    0xc(%ebp),%edx

movl %%eax, (%1);                                            804840a:      nop

nop;"                                                                   804840b:      mov    (%ecx),%eax

:                                                                           804840d:      mov    (%edx),%ebx

:                                                                           804840f:      mov    %ebx,(%ecx)

"r"(x),"r"(y)                                                          8048411:      mov    %eax,(%edx)

:                                                                           8048413:      nop

"eax", "ebx", "memory"                                        8048414:      mov    (%esp,1),%ebx ;ebx还原

);                                                                         8048417:      leave   ;movl %ebp, %esp; pop ebp

}                                                                                         8048418:      ret

8048419:      lea    0x0(%esi),%esi

int main()

{

int a = 10, b = 0;

printf("before swap: a = %2d, b = %2d\n", a, b);

swap(&a, &b);

printf("after  swap: a = %2d, b = %2d\n", a, b);

return 0;

}

4、从汇编代码中分离函数

1> 获得汇编代码

这里用加法函数,源代码为:

int sum(int a, int b)

{

int c = a + b;

return c;

}

对应的汇编代码为

Disassembly of           section .text:

00000000 :

0:   55                        push   %ebp

1:   89 e5                   mov    %esp,%ebp

3:   83 ec 04              sub    $0x4,%esp

6:   8b 45 0c              mov    0xc(%ebp),%eax

9:   03 45 08              add    0x8(%ebp),%eax

c:   89 45 fc               mov    %eax,0xfffffffc(%ebp)

f:   8b 45 fc                mov    0xfffffffc(%ebp),%eax

12:   89 c0                  mov    %eax,%eax

14:   c9                       leave

15:   c3                       ret

16:   89 f6                   mov    %esi,%esi

2> 编写内嵌汇编语言函数

分析:为函数构建运行时堆栈情况即可使其顺利运行,由于编译器在函数执行开始和结束时会增加

routine begin:

push %ebp; mov %esp, %ebp

routine end:

leave; ret

将上面的0, 1, 14, 15去掉,返回参数放在eax中将输出部分设置为"=a"(r) 用eax寄存器 r 为需要的return type

步骤:

i   定义return_type r 变量

ii  去掉push %ebp; mov %esp, %ebp;   leave; ret

iii 输出部分为:"=a"(r):

$ vi sumassemble.c

int sum(int a, int b)

{

int r;

__asm__("sub $0x4, %%esp;

movl 0xc(%%ebp), %%eax;

addl 0x8(%%ebp), %%eax;

movl %%eax, 0xfffffffc(%%ebp);

movl 0xfffffffc(%%ebp), %%eax;

movl %%eax, %%eax;"

:

"=a"(r)

);

return r;

}

Disassembly of           section .text:

00000000 :

0:   55                        push   %ebp

1:   89 e5                   mov    %esp,%ebp

3:   83 ec 04              sub    $0x4,%esp

6:   83 ec 04              sub    $0x4,%esp

9:   8b 45 0c              mov    0xc(%ebp),%eax

c:   03 45 08              add    0x8(%ebp),%eax

f:   89 45 fc                mov    %eax,0xfffffffc(%ebp)

12:   8b 45 fc              mov    0xfffffffc(%ebp),%eax

15:   89 c0                  mov    %eax,%eax

17:   89 c0                  mov    %eax,%eax

19:   89 45 fc              mov    %eax,0xfffffffc(%ebp)

1c:   8b 45 fc              mov    0xfffffffc(%ebp),%eax

1f:   89 c0                   mov    %eax,%eax

21:   c9                       leave

22:   c3                       ret

23:   90                       nop

3> 编译可执行程序

$ vi summain.c

extern int sum(int ,int);

int main()

{

int x = sum(1,2);

printf("x = %d\n", x);

return 0;

}

$ cc -o sum_main sum_main.c sum_assemble.c

$ ./sum_main

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值