x86汇编语言(五)

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
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	push	rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	mov	rbp, rsp
	.cfi_def_cfa_register 6
	sub	rsp, 32
	mov	DWORD PTR -20[rbp], 10
	mov	DWORD PTR -16[rbp], 10
	mov	DWORD PTR -12[rbp], 10
	mov	DWORD PTR -8[rbp], 10
	mov	DWORD PTR -4[rbp], 10
	mov	eax, DWORD PTR -20[rbp]
	mov	esi, eax
	lea	rdi, .LC0[rip]
	mov	eax, 0
	call	printf@PLT
	mov	eax, 0
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-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
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	push	rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	mov	rbp, rsp
	.cfi_def_cfa_register 6
	sub	rsp, 32
	mov	DWORD PTR -4[rbp], 10
	mov	DWORD PTR -8[rbp], 10
	mov	DWORD PTR -12[rbp], 10
	mov	DWORD PTR -16[rbp], 10
	mov	DWORD PTR -20[rbp], 10
	mov	eax, DWORD PTR -4[rbp]
	mov	esi, eax
	lea	rdi, .LC0[rip]
	mov	eax, 0
	call	printf@PLT
	mov	eax, 0
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-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
结果正确
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值