嵌入汇编

在嵌入式C语言中,涉及到底层的代码经常需要使用嵌入汇编。

嵌入汇编的基本格式:

asm(

"汇编语句"

::输出寄存器

:输入寄存器

:会被改变的寄存器

)

可是实际上你会发现,一般在被改变的寄存器中没有加入eax !这是为什么?

有如下代码为例:

实际上第五行不应该改成"%ecx","%eax","%edi"?
asm("cld\n\t"
    "rep\n\t"
    :/*没有输出寄存器*/
    :"c"(count-1),"a"(fill_value),"D"(dest)
    :"%ecx","%edi");

EAX寄存器以称为累加器,AX寄存器是算术运算的主要寄存器, 所有的输入、输出只使用AL或AX人作为数据寄存器。so,eax寄存器是肯定会被改的,可以不输入,但是我个人觉得加上也无妨,没有做过这方面的的实验,有兴趣的话可以自己尝试。

再来看看下面一段代码,是一个strncmp的实现:

static inline int strncmp(const char * cs,const char * ct,int count)
{
register int __res ;
__asm__("cld\n"
	"1:\tdecl %3\n\t"
	"js 2f\n\t"
	"lodsb\n\t"
	"scasb\n\t"
	"jne 3f\n\t"
	"testb %%al,%%al\n\t"
	"jne 1b\n"
	"2:\txorl %%eax,%%eax\n\t"
	"jmp 4f\n"
	"3:\tmovl $1,%%eax\n\t"
	"jl 4f\n\t"
	"negl %%eax\n"
	"4:"
	:"=a" (__res):"D" (cs),"S" (ct),"c" (count));
return __res;
}

int main(int argc,char*argv[])
{
	strncmp("hello","world",5);
}

在这段代码中,es:edi指向cs字符串,ds:esi指向ct字符串,对两者进行比较。但是我们并没有发现对es&ds进行了赋值!这究竟是怎么回事呢?

使用gcc -S -o strncmp.S strncmp.c 看一下汇编的结果:

	.file	"strncmp.c"
	.text
	.type	strncmp, @function
strncmp:
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%edi
	pushl	%esi
	pushl	%ebx
	subl	$4, %esp
	movl	8(%ebp), %eax
	movl	%eax, -16(%ebp)
	movl	12(%ebp), %edx
	movl	16(%ebp), %ecx
	movl	-16(%ebp), %edi
	movl	%edx, %esi
#APP
# 5 "strncmp.c" 1
	cld
1:	decl %ecx
	js 2f
	lodsb
	scasb
	jne 3f
	testb %al,%al
	jne 1b
2:	xorl %eax,%eax
	jmp 4f
3:	movl $1,%eax
	jl 4f
	negl %eax
4:
# 0 "" 2
#NO_APP
	movl	%eax, %ebx
	movl	%ebx, %eax
	addl	$4, %esp
	popl	%ebx
	popl	%esi
	popl	%edi
	popl	%ebp
	ret
	.size	strncmp, .-strncmp
	.section	.rodata
.LC0:
	.string	"world"
.LC1:
	.string	"hello"
	.text
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$12, %esp
	movl	$5, 8(%esp)
	movl	$.LC0, 4(%esp)
	movl	$.LC1, (%esp)
	call	strncmp
	leave
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu 4.4.1-4ubuntu8) 4.4.1"
	.section	.note.GNU-stack,"",@progbits
至此,还没看到有对es和ds进行复制的操作。因此,我有理由相信这是有编译器来决定的。而在汇编代码中,你看到这两个字符串其实是分配在相近的地址中的,因此cs和ds寄存器应该是一样的。
不过,这里也纠正一个自己以前犯的错,以前还以为直接在函数参数中写入常量字符串的话,时会把字符串直接写到堆栈中,现在从汇编代码来看,确实直接写到.rodata 段中去的。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值