asm: gcc - c语言的内联汇编学习(linux_gcc_c)
一、基本说明
1、操作系统:rockylinux9
[root@rocky c]# uname -a
Linux rocky 5.14.0-162.6.1.el9_1.0.1.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Nov 28 18:44:09 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
2、内联汇编的语言环境:gcc - c语言
3、gcc 版本信息:
[root@rocky c]# gcc --version
gcc (GCC) 11.3.1 20220421 (Red Hat 11.3.1-2)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
二、内联汇编说明
1、asm的基本语法:
1 __asm__ [__volatile__](
2
3 "Instruction List" // 汇编指令列表;
4
5 : Output List // 输出参数列表; “汇编语言”,将结果输出到“C语言的变量”; (C语言变量 = 汇编变量;)
6
7 : input List // 输入参数列表; “汇编语言”,从“C语言的变量”读取数据; (汇编变量 = C语言变量;)
8
9 : Clobber/Modify // 损坏部分; “汇编语言”会改变“寄存器”和“内存”的值;
10 // 在汇编代码执行前,强迫gcc编译器备份此处声明的寄存器和内存的数值;
11 // 在“汇编代码执行后”,恢复此处声明的寄存器和内存的值。
12 // 概括: 汇编前,将重要数据备份; 汇编后,恢复现场。
13 );
14
2、示例代码及说明
1 __asm__(
2 " movl %3, %%ebx \t\n" // %3 = input2
3 " movl %2, %%eax \t\n" // %2 = input1
4 " movl %%ebx, %1 \t\n" // %1 = output2
5 " movl %%eax, %0 " // %0 = output1
6
7 : "=a"(output1), "=b"(output2) // 为“汇编语言”提供输入和输出的“c语言变量”,“汇编语言”会分配一个别名给“C语言的这些变量”。
8 : "r"(input1), "r"(input2) // 汇编语言别名分配规则:
9 // 开始于“Output List”的左端,第一个C语言变量的别名为0;右端结束;
10 // 结束于“Input List”的右端,最后一个C语言变量的别名小于等于9.
11 // 别名: output1=0, output2=1, input1=2, input2=3.
12 );
三、源码及运行结果
1 [root@rocky c]# uname -a
2 Linux rocky 5.14.0-162.6.1.el9_1.0.1.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Nov 28 18:44:09 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
3 [root@rocky c]#
4 [root@rocky c]#
5 [root@rocky c]# gcc --version
6 gcc (GCC) 11.3.1 20220421 (Red Hat 11.3.1-2)
7 Copyright (C) 2021 Free Software Foundation, Inc.
8 This is free software; see the source for copying conditions. There is NO
9 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
11 [root@rocky c]#
12 [root@rocky c]#
13 [root@rocky c]# gcc -Wall -g -o asm_test asm_test.c && cat asm_test.c && ./asm_test
14 #include<stdio.h>
15 #include<stdlib.h>
16
17
18
19
20 void
21 msg()
22 {
23 int input1 = 91;
24 int input2 = 92;
25 int output1 = 11;
26 int output2 = 12;
27 printf("\n\nbefore-asm:\toutput1=%d,\toutpu2=%d\n", output1, output2);
28
29
30 // function: output1 = input1; output2 = input2;
31 // result: output1 = 91; output2 = 92;
32 __asm__(
33 " movl %3, %%ebx \t\n" // %3 = input2
34 " movl %2, %%eax \t\n" // %2 = input1
35 " movl %%ebx, %1 \t\n" // %1 = output1
36 " movl %%eax, %0 " // %0 = output1
37
38 : "=a"(output1), "=b"(output2) // nickname: output1 = %0, output2 = %1;
39 : "r"(input1), "r"(input2) // nickname: input1 = %2, input2= %3
40 ); // nickname N: 0 <= N <=9;
41 // from OUTPUT(left-to-right) to end INPUT(left-to-right)
42
43
44 printf("after-asm:\toutput1=%d,\toutpu2=%d\n\n", output1, output2);
45 }
46
47
48
49
50 int main(int argc, char *argv[], char *envp[])
51 {
52 msg();
53
54 return 0;
55 }
56
57
58 before-asm: output1=11, outpu2=12
59 after-asm: output1=91, outpu2=92
60
61 [root@rocky c]#
62 [root@rocky c]#
四、参考文献
1、AT&T汇编语言(中文版): https://max.book118.com/html/2015/1010/27027193.shtm
2、GCC内联汇编: https://www.cnblogs.com/hellokitty2/p/16344565.html
3、GCC 内联汇编语法: https://blog.csdn.net/zxjcarrot/article/details/12886085
4、GCC内联汇编: http://www.360doc.com/content/15/0604/12/496343_475591449.shtml
本文由 lnlidawei 原创、整理、转载,本文来自于【博客园】; 整理和转载的文章的版权归属于【原创作者】; 转载或引用时请【保留文章的来源信息】:https://www.cnblogs.com/lnlidawei/p/17016142.html