スポンサーリンク

このドキュメントの内容は、以下の通りです。

10年ぐらい前に libc を使わない、自分だけが書いたコードだけの
プログラムを書いているときに、コンパイル時に memset() がない
とエラーが出て、コンパイルが止まったことがありました。
自分のコードは memset() なんて明示的に呼んでないので、
なんでかと思って、調べてみると、gcc から吐き出される
コードのなかに memset() が入っていました。

以下のようなコードは、配列の宣言時に、メモリをゼロクリアする
ことになります。

char s [ 255 ] = { 0 };

実行時に、スタックに確保した領域をゼロクリアしなければなりません。
メモリをゼロクリアするときにどうするかというと、
たいていのプログラマは、memset()/bzero() を利用するかと思います。
そういうわけで、ローカル変数の配列をゼロクリアする宣言を
した場合には、自動的に memset() で 0 で埋めるコードが
コンパイラによって出力されるわけです。

zero_clear.c


実際にそれが起こるコードを書いてみます。

#include <stdio.h>
#include <stdlib.h>

int
main (int argc, char *argv[])
{
	char s [ 255 ] = { 0 };

	exit (EXIT_SUCCESS);
}

アセンブラコードの生成を行う。
gcc -S zero_clear.c

zero_clear.s


gcc に出力されたアセンブラのソースコードは以下の通りです。

	.file	"zero_clear.c"
	.text
	.p2align 4,,15
.globl main
	.type	main, @function
main:
	leal	4(%esp), %ecx
	andl	$-16, %esp
	pushl	-4(%ecx)
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ecx
	subl	$276, %esp
	leal	-259(%ebp), %edx
	movl	$255, %eax
	movl	%eax, 8(%esp)
	movl	$0, 4(%esp)
	movl	%edx, (%esp)
	call	memset
	movl	$0, (%esp)
	call	exit
	.size	main, .-main
	.ident	"GCC: (GNU) 4.2.1 20070719  [FreeBSD]"

memsetが呼ばれないケース


どんなコードでもゼロクリアにmemset()が呼ばれるわけでもないようです。

配列のサイズを 1 にしてみます。

char s [ 1 ] = { 0 };

movb で 0 を書きこむだけになってます。
main:
	leal    4(%esp), %ecx
	andl    $-16, %esp
	pushl   -4(%ecx)
	pushl   %ebp
	movl    %esp, %ebp
	pushl   %ecx
	subl    $20, %esp
	movb    $0, -5(%ebp)
	movl    $0, (%esp)
	call    exit
	.size   main, .-main


char s [ 2 ] = { 0 };

サイズを 2 にすると movw で 0 を書き込みます。

	.file	"zero_clear.c"
	.text
	.p2align 4,,15
.globl main
	.type	main, @function
main:
	leal	4(%esp), %ecx
	andl	$-16, %esp
	pushl	-4(%ecx)
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ecx
	subl	$20, %esp
	movw	$0, -6(%ebp)
	movl	$0, (%esp)
	call	exit
	.size	main, .-main
	.ident	"GCC: (GNU) 4.2.1 20070719  [FreeBSD]"

char s [ 3 ] = { 0 };

サイズを 3 にすると movw と movb で 0 を書き込みます。

	.file	"zero_clear.c"
	.text
	.p2align 4,,15
.globl main
	.type	main, @function
main:
	leal	4(%esp), %ecx
	andl	$-16, %esp
	pushl	-4(%ecx)
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ecx
	subl	$20, %esp
	movw	$0, -7(%ebp)
	movb	$0, -5(%ebp)
	movl	$0, (%esp)
	call	exit
	.size	main, .-main
	.ident	"GCC: (GNU) 4.2.1 20070719  [FreeBSD]"

配列のサイズが64の場合。

	.file	"zero_clear.c"
	.text
	.p2align 4,,15
.globl main
	.type	main, @function
main:
	leal	4(%esp), %ecx
	andl	$-16, %esp
	pushl	-4(%ecx)
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ecx
	subl	$100, %esp
	leal	-69(%ebp), %edx
	movl	$65, %eax
	movl	%eax, 8(%esp)
	movl	$0, 4(%esp)
	movl	%edx, (%esp)
	call	memset
	movl	$0, (%esp)
	call	exit
	.size	main, .-main
	.ident	"GCC: (GNU) 4.2.1 20070719  [FreeBSD]"

配列のサイズが 65 から memset を呼び出すコードが出力されるようです。

スポンサーリンク
スポンサーリンク
 
いつもシェア、ありがとうございます!


もっと情報を探しませんか?

関連記事

最近の記事

人気のページ

スポンサーリンク
 

過去ログ

2020 : 01 02 03 04 05 06 07 08 09 10 11 12
2019 : 01 02 03 04 05 06 07 08 09 10 11 12
2018 : 01 02 03 04 05 06 07 08 09 10 11 12
2017 : 01 02 03 04 05 06 07 08 09 10 11 12
2016 : 01 02 03 04 05 06 07 08 09 10 11 12
2015 : 01 02 03 04 05 06 07 08 09 10 11 12
2014 : 01 02 03 04 05 06 07 08 09 10 11 12
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12

サイト

Vim入門

C言語入門

C++入門

JavaScript/Node.js入門

Python入門

FreeBSD入門

Ubuntu入門

セキュリティ入門

パソコン自作入門

ブログ

トップ


プライバシーポリシー