アセンブラの勉強(1)

Mona等のソースコードをそのまま64ビットgccにかけるとインラインアセンブラの部分でそんな構文は使えないよというエラーが出ます。使えないといわれてもどうしたらいいのか途方にくれていたらKタンに簡単なコードをgccに食わせて、どう変換されているか見たらどうかとアドバイスを受けました。たしか"gcc -S"でアセンブラソースを吐くオプションがあったはずなのでいろいろ調べてみました。

ソースコード

 int main(void) {
	/* この部分に注目 */
	char  a = 0xff;
	short b = 0xffff;
	int   c = 0xffffffff;
	long  d = 0xffffffff;
	a++;
	b++;
	c++;
	d++;
	/* この部分に注目 */
	return 0xff;
 }

32ビットコード

	gcc -m32 -S -O0 -Wall test01.c

	movb	$-1, -1(%ebp)
	movw	$-1, -4(%ebp)
	movl	$-1, -8(%ebp)
	movl	$-1, -12(%ebp)
	leal	-1(%ebp), %eax
	incb	(%eax)
	leal	-4(%ebp), %eax
	incw	(%eax)
	leal	-8(%ebp), %eax
	incl	(%eax)
	leal	-12(%ebp), %eax
	incl	(%eax)
	movl	$255, %eax
	leave
	ret

64ビットコード

	gcc -S -O0 -Wall test01.c

	movb	$-1, -1(%rbp)
	movw	$-1, -4(%rbp)
	movl	$-1, -8(%rbp)
	movl	$-1, -16(%rbp)
	movl	$0, -12(%rbp)
	leaq	-1(%rbp), %rax
	incb	(%rax)
	leaq	-4(%rbp), %rax
	incw	(%rax)
	leaq	-8(%rbp), %rax
	incl	(%rax)
	leaq	-16(%rbp), %rax
	incq	(%rax)
	movl	$255, %eax
	leave
	ret

64ビット用インラインアセンブラ

	asm volatile(
		"movb	$-1, -1(%rbp)\n"
		"movw	$-1, -4(%rbp)\n"
		"movl	$-1, -8(%rbp)\n"
		"movl	$-1, -16(%rbp)\n"
		"movl	$0, -12(%rbp)\n"
		"leaq	-1(%rbp), %rax\n"
		"incb	(%rax)\n"
		"leaq	-4(%rbp), %rax\n"
		"incw	(%rax)\n"
		"leaq	-8(%rbp), %rax\n"
		"incl	(%rax)\n"
		"leaq	-16(%rbp), %rax\n"
		"incq	(%rax)\n"
	);

違い

  • 使用するレジスタが変わっている(eax->rax、ebp->rbp)
  • 通常演算の多くにq(64ビット用)がつくようになっている
  • %%eaxが(%rax)に変わっている
  • インラインアセンブラの移植性が低いというのはこういうことだったのかと納得・・