x86汇编语言(五)

来源:互联网 发布:天刀红唇萌妹捏脸数据 编辑:程序博客网 时间:2024/05/18 06:28

GCC中启用intel风格的内联汇编

gcc中默认的内联汇编格式默认为AT&T格式,我们可以主动声明intel风格的内联汇编——asm(".intel_syntax noprefix\n"),编译时使用-masm=intel选项,此时源文件中的汇编代码就可以得到正确处理。
以下为示例程序:
#include<stdio.h>int main(){    int a = 1,b = 2;    asm(".intel_syntax noprefix\n");    asm("mov dword ptr a,3\n");    a = a + b;    printf("%d\n",a);    return 0;}

使用gcc进行编译:gcc -masm=intel asm_test.c -o asm_test
然而编译失败,输出错误提示:/usr/bin/ld: /tmp/ccmEXVmu.o: relocation R_X86_64_32S against undefined symbol `a' can not be used when making a shared
a是一个未定义的符号所以出错。分析原因,a是一个局部变量,存储位置在栈空间,编译器对变量a的引用是通过 rbp+偏移量 的方式进行的,所以我们对a的引用也要使用 rbp+偏移量的方式,关键问题是确定a在堆栈中的偏移量。
对于如下代码,
#include<stdio.h>int main(){    int a;    int b;    int c;    int d;    int f;    a = 10;    b = 10;    c = 10;    d = 10;    f = 10;    printf("%d\n",a);    return 0;}
我们对其进行编译得到汇编代码:
.file"intel_asm.c".intel_syntax noprefix.section.rodata.LC0:.string"%d\n".text.globlmain.typemain, @functionmain:.LFB0:.cfi_startprocpushrbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movrbp, rsp.cfi_def_cfa_register 6subrsp, 32movDWORD PTR -20[rbp], 10movDWORD PTR -16[rbp], 10movDWORD PTR -12[rbp], 10movDWORD PTR -8[rbp], 10movDWORD PTR -4[rbp], 10moveax, DWORD PTR -20[rbp]movesi, eaxleardi, .LC0[rip]moveax, 0callprintf@PLTmoveax, 0leave.cfi_def_cfa 7, 8ret.cfi_endproc.LFE0:.sizemain, .-main.ident"GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005".section.note.GNU-stack,"",@progbits

我们可以看到,对于局部变量a的是通过 -20[rbp] 来进行引用的,对于局部变量f是通过 -4[rbp] 进行引用的,而堆栈又是从高地址向低地址生长,这说明gcc对于局部变量的处理是先声明后如栈,这与vc的处理方式不同,通过查阅资料可知,这是由于gcc采用了一种名为SSP的堆栈保护技术导致的,我们使用-fno-stack-protector选项不使用该技术再次编译该文件:
.file"intel_asm.c".intel_syntax noprefix.section.rodata.LC0:.string"%d\n".text.globlmain.typemain, @functionmain:.LFB0:.cfi_startprocpushrbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movrbp, rsp.cfi_def_cfa_register 6subrsp, 32movDWORD PTR -4[rbp], 10movDWORD PTR -8[rbp], 10movDWORD PTR -12[rbp], 10movDWORD PTR -16[rbp], 10movDWORD PTR -20[rbp], 10moveax, DWORD PTR -4[rbp]movesi, eaxleardi, .LC0[rip]moveax, 0callprintf@PLTmoveax, 0leave.cfi_def_cfa 7, 8ret.cfi_endproc.LFE0:.sizemain, .-main.ident"GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005".section.note.GNU-stack,"",@progbits

此时可以看到,对于变量a的引用已经是 -4[rbp] 了,这说明变量a先入栈。
现在修改我们的示例文件,由以上可知,对于变量a的引用应该是 -8[rbp]
#include<stdio.h>int main(){    int a = 1,b = 2;    asm(".intel_syntax noprefix\n");    asm("mov dword ptr [rbp -8],3\n");    a = a + b;    printf("%d\n",a);    return 0;}
jyj6536@jyj6536-VirtualBox:~/文档/C语言2/2$ gcc -masm=intel asm_test.c -o asm_test
jyj6536@jyj6536-VirtualBox:~/文档/C语言2/2$ ./asm_test
5
结果正确
原创粉丝点击