汇编语言代码编写c 语言代码,通过内联汇编实现字符串的复制,C内联汇编

内联汇编:在C/C++代码中嵌入汇编代码。

汇编的用武之地:

效率依旧比C高。

有特殊的指令必须用汇编,在C中没有等价的语法。

(1) 内嵌汇编的格式

在GNU下,在高级语言中嵌汇编语言用关键字asm来实现,简单的格式如下:

asm( “assembly code” );

asm用来标识汇编代码段。括号内的汇编代码必须在引号之内。

如果asm模块内有多条语句,若每条语句独占一行则需要将每条语句都用双引号引起来。并且每条语句的末尾需要有换行。

C中嵌汇编的例子,记录C中嵌汇编的格式:

1  #include

2

3  int main(void)

4  {

5         //AT&T asm systemcall: exit

6         asm(    "movl $1, %eax\n\t"

7                 "movl $0,%ebx\n\t"

8                 "int$0x80");

9

10        //Print string on screen

11        printf("Hello ""world"" C\n");

12

13        return 0;  14  }

6到8行是用GNU内敛汇编的格式编写的汇编代码。这些汇编代码表示系统调用exit函数,让程序退出。

asm括号内有多行汇编代码时,没行代码都需要括起来且需要以\n\t结束。如果不加\n\t的话下一行的首字母会被连接到上一行的末尾(这个是双引号的用法)。关于加\n\t的机制,可能在windows之上不一样。

如果,内敛汇编成功,那么编译并执行此C语言程序是不会输出字符串的。

(2)内敛汇编代码访问C的全局变量

在C中内嵌的汇编代码能够处理在C中的变量,可惜只能处理全局变量(已验证)。以下笔记示例:

1  #include

2

3  int a;

4  int b;

5  int c;

6

7  int main(void)

8  {

9         a = b = 1;

10        c =0;

11        //AT&T asm system call: exit

12        asm(    "movl a,%eax\n\t"

13                 "movl b, %ebx\n\t"

14                 "addl %eax,%ebx\n\t"

15                 "movl %ebx, c");

16

17        //Print string on screen

18        printf("Result is %d\n", c);

19

20        return 0;  21  }

12行至15行代码是内敛的汇编代码。用来处理全局变量a, b, c。在内敛汇编中处理C中的全局变量按照汇编的规则直接引用变量的名称即可。

内嵌汇编代码的C程序编译跟编译纯C代码一样。结果输出C的值为2。

(3)内敛汇编扩展

使用以上的内敛汇编代码有一定的局限性,比如在内敛汇编代码中只能访问C的全局变量。而在扩展内敛汇编代码内就能够让内敛汇编代码访问C的任何变量。GNU的扩展内敛汇编笔记如下。

[1]扩展内敛汇编格式

asm (“assembly code”

:output locations

:input operands

:change dregisters);

assembly code:跟前面笔记的内敛汇编代码具一样的格式。

output locations:指示汇编指令的运算结果要输出到哪些C操作数中,C操作数应该是左值表达式。

input operands:第三部分指示汇编指令需要从哪些C操作数获得输入。

changed registers:第四部分是在汇编指令中被修改过的寄存器列表,指示编译器哪些寄存器的值在执行这条asm指令后会改变.

对于后三块,没有的模块可以直接省略。非最后一部分省略时冒号不可被省略。

output locations,input operands具有的格式:

“constraint1”(variable1),“constraint2”(variable2)…

onstraint定义variable将被置于何处。[可查看《Professional Assembly language》page402]

variable是在C中定义的变量。

[2]使用扩展内敛汇编

还是针对于以上的内敛汇编代码,将全局变量改为局部变量,用扩展内敛汇编去访问C中的变量。

<1>寄存器

1  #include

2

3

4  int main(void)

5  {

6         int a, b, c;

7

8         a = b = 1;

9         c =0;

10        //AT&T asm system call: exit

11        asm(    "movl $0,%%eax\n\t"

12                 "addl %%ebx,%%ecx\n\t"

13                 "addl %%ecx,%%eax\n\t"

14                 : "=a"(c)

15                : "b"(a),"c"(b)

16        );

17

18        //Print string on screen

19        printf("Result is %d\n", c);

20

21        return 0;  22  }

定义局部变量a, b, c供扩展内敛汇编代码访问。

11到16行是扩展内敛汇编代码。针对之前提到的笔记对应解释这段内敛汇编代码。

14对应output locations。”a”表示eax寄存器,”c”表示程序中定义定义的变量c。在output locations限制内存处要加“=”。即经此段内敛内敛代码处理后,C语言变量c的值存在a所代表的的内存里。

15对应input operands,”b”、”c”分别表示ebx、ecx寄存器。”a”、”b”分表代表程序中的变量b、c。此语句表面,将程序中的变量值b、c分别放在寄存器ebx、ecx中。

11行到13行的汇编代码依次表示初始化eax为0,将ebx与ecx内的值相加后放在ecx中,将ecx和eax内的值相加后放在eax中。

用寄存器来作为C变量的存储地,再经汇编代码处理。这个过程其实就是将变量的值拷贝到各寄存器中,然后操作各寄存器,再将作为输出的变量重新赋值。不过为什么在这种情况下要在寄存器前面加两个%应该与%本身功能相关,点到为止,遇到再议。

<2>占位符

当需要内敛汇编代码处理的代码数量较多时,可能会有不知道用哪个寄存器来保存输入变量才比较,恐怕有心有余而力不足的赶脚。使用占位符可解决此烦恼。

占位符用除寄存器外的其它constraint[可查看《Professional Assembly language》page402]来表示。如:

asm(   "addl %1, %2\n\t"

"addl %2, %0\n\t"

: "=r"(c)

: "r"(a), "r"(b) );

r只能表示任何可用的通用寄存器。

%0代表存c变量的地方。

%1代表存a变量的地方。

%2代表存b变量的地方。

故而汇编代码的操作就是操作%0, %1, %2了,能得到相同的效果。

使用占位符的情况还可以如此:

asm ( “addl  %[value1],  %[value2]”

: [value2]  “=r” (data2)        :[value1]  “r”(data1));

<3>内存空间

内存空间的限制符为m。在使用内存空间时,需要用一个寄存器来作为中间存储。

0818b9ca8b590ca3270a3433284dd417.png

还有其它形式的扩展内敛汇编,形体都差不多。在实际编程中可根据需求和爱好进行选择。

(4)内敛汇编的标识符

[1]asm volatile(“assembly code”);

在asm之后加了volatile之后,表明括号内的汇编代码不被优化。这些是volatile关键字的作用,道理深着。

[2]__asm_

在GNU下可使用asm来表示内敛的汇编代码。如果是在ANSC C中编写内敛汇编代码,需要用__asm_来替换asm。同时volatile也需要换成__volatile_。

(5)内敛汇编用途总结

在C/C++中使用内敛汇编的很多形式为宏。即将内敛汇编定义成宏供C/C++代码调用。将内敛汇编定义成宏的形式更加方便。定义宏的方式跟在C中定义C宏的方法一致,只是宏的形式跟以上笔记的内敛汇编的形式一致。

CNote Over。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值