如何在c代码里内联汇编

这里写图片描述

一:背景

早期,绝大多数的程序都是用汇编语言写的,甚至是计算机的操作系统OS/360.但是,汇编语言因其抽象程度低,无法提供类型检查。使得编写大型程序捉襟见肘。而且,汇编代码是和机器紧紧联系在一起,使得汇编语言编写的程序移植性差。
那为什么还要把汇编代码内联到c语言里呢?

二:汇编代码的优势

1.访问寄存器的值
2.访问条件码
3.使用一些特殊的指令和特殊的内存地址
……

三:怎么内联汇编

①手写汇编函数(不推荐)

新建一个.c文件里,写入函数,再通过

gcc -S 2.c 

生成汇编文件,再修改汇编文件里的指令

gcc -o prog 1.c 2.s

最后链接两个文件,就ok啦。
eg:

//1.c
#include<stdio.h>
int main()
{
    printf("%d\n",call());
    return 0;
}

//2.c
int call()
{
    return 15;
}

2.c生成的汇编代码:

    .file   "2.c"
    .text
    .globl  call
    .type   call, @function
call:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    movl    $15, %eax
    popl    %ebp
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE0:
    .size   call, .-call
    .ident  "GCC: (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406"
    .section    .note.GNU-stack,"",@progbits

大多数都是gcc产生的伪指令.
在call函数里,函数返回15,转换成汇编即是

movl $15,%eax

现在,我们修改这条指令

movl $14,%eax

再重新编译,运行

gcc -o prog 1.c 2.s
./prog

程序就返回14,而不是15了。

②使用gcc内联汇编宏

Gcc提供了 asm帮助我们内联汇编,其语法是:(asm长得像printf函数)

asm( code-strings [ : output-list [ : input-list [ : overwrite-list ] ] ] );

现在一项一项介绍:

code-strings:这里,放你的汇编指令,用” ”括起来(就像字符串)。例如

"movq $15,%%rax"      (后边解释为什么是%%rax)

如果你要内联多条汇编语句,则需要为每一条指令后添加 \n\t.保证格式。例:

"movq $15,%%rbx\n\t"
"movq %%rbx,%rax"




outputlist , inputlist , overwritelist要用:分隔
如果outputlist ,inputlist , overwritelist 有多个值,则用分隔

output-list:类似于返回值,即你想在汇编代码里修改的值。

[name] tag (expr)
[name] 这个值在汇编代码里的名字(汇编代码用%[name]访问,所以寄存器要用2个%访问)
tag

tag 操作权限 位置
“=r” 只写 寄存器
“+r” 读,写 寄存器
“=m” 只写 内存
“+m” 读,写 内存
“=rm” 寄存器或内存
“+rm” 读,写 寄存器或内存

(expr) c语言里的左值都行

input-list 类似于参数,即你要在汇编代码里使用的值

[name] tag (expr)
[name]同上
tag

tag 位置
r 寄存器
m 内存
rm 寄存器或内存

(expr) 同上

ovrwrite-list 这里放你要使用的寄存器 用” “括起来

这样,gcc在汇编程序时,可以把你要用的寄存器pushq保存下来



例子:

#include<stdio.h>
int call(int x,int y)
{
        int sum = 0;
        asm("movl %[val1],%%ebx\n\t"
            "movl %[val2],%%ecx\n\t"
            "addl %%ebx,%%ecx\n\t"
            "movl %%ecx,%[SUM]"
            :[SUM] "=r" (sum)      //这个是output-list
            :[val1] "r" (x),[val2] "r" (y)    //这个是input-list
            :"%ebx","%ecx"          //这个是overwriter list
        );
        return sum;
}
int main()
{
        int a=15;
        int b=20;
        printf("%d\n",call(a,b));
        return 0;
}

引用
1.CS:APP3e Web Aside ASM:EASM:
Combining Assembly Code with C Programs∗

2.百度图片(侵权删)

猜你喜欢

转载自blog.csdn.net/weixin_41256413/article/details/80444103