C言語 for whileアセンブリ上で違いはあるのか　x86

以下のコードをそれぞれアセンブリ言語へコンパイルします。

## Cソース
同条件下で比較するため為、両者の書き方を出来るだけ近づけました。
```forasm.c
//#include<stdio.h> /* debug */

int main() {
	int a=0;
	for(int i=0;i<7;i++){
		a+=i;
	}
	//printf("result = %d",a); /* debug */
    return 0;
}
```
```whileasm.c
//#include<stdio.h> /* debug */

int main() {
	int a=0;
	int i=0;
	while(i<7){
		a+=i;
		i++;
	}
	//printf("result = %d",a); /* debug */
    return 0;
}
```

## コンパイル
```
C:\Users\nanasi\loopasm>gcc -S -masm=intel -o forasm.s forasm.c
C:\Users\nanasi\loopasm>gcc -S -masm=intel -o whileasm.s whileasm.c
```

```forasm.s
	.file	"forasm.c"
	.intel_syntax noprefix
	.text
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	push	rbp
	.seh_pushreg	rbp
	mov	rbp, rsp
	.seh_setframe	rbp, 0
	sub	rsp, 48
	.seh_stackalloc	48
	.seh_endprologue
	call	__main
	mov	DWORD PTR -4[rbp], 0
	mov	DWORD PTR -8[rbp], 0
	jmp	.L2
.L3:
	mov	eax, DWORD PTR -8[rbp]
	add	DWORD PTR -4[rbp], eax
	add	DWORD PTR -8[rbp], 1
.L2:
	cmp	DWORD PTR -8[rbp], 6
	jle	.L3
	mov	eax, 0
	add	rsp, 48
	pop	rbp
	ret
	.seh_endproc
	.def	__main;	.scl	2;	.type	32;	.endef
	.ident	"GCC: (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders, r3) 14.2.0"
```
```whileasm.s
	.file	"whileasm.c"
	.intel_syntax noprefix
	.text
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	push	rbp
	.seh_pushreg	rbp
	mov	rbp, rsp
	.seh_setframe	rbp, 0
	sub	rsp, 48
	.seh_stackalloc	48
	.seh_endprologue
	call	__main
	mov	DWORD PTR -4[rbp], 0
	mov	DWORD PTR -8[rbp], 0
	jmp	.L2
.L3:
	mov	eax, DWORD PTR -8[rbp]
	add	DWORD PTR -4[rbp], eax
	add	DWORD PTR -8[rbp], 1
.L2:
	cmp	DWORD PTR -8[rbp], 6
	jle	.L3
	mov	eax, 0
	add	rsp, 48
	pop	rbp
	ret
	.seh_endproc
	.def	__main;	.scl	2;	.type	32;	.endef
	.ident	"GCC: (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders, r3) 14.2.0"
```
## 比較
1行づつ確認するのは難しい為winmergiを用いて比較します。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/00570d5f-27b0-4b52-a185-1b149e8a318a.png)
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/239c9c93-1db3-4597-a315-d845d751a8ce.png)

なんということでしょう。ソース名以外は完全に一致しました。
実際forとwhileを使う時にはプログラムの書き方も異なってくると思いますが、forとwhile自体にはあまり差が無いようです。

## 分析
せっかくアセンブリ言語へ変換したので中身を読んでみます。
```s
    ;...前略
	mov	DWORD PTR -4[rbp], 0 ; int a=0 （変数aはrbp-4に格納）
	mov	DWORD PTR -8[rbp], 0 ; int i=0 （変数iはrbp-8に格納）
	jmp	.L2 ; 先ずL2へ跳びcmp命令でi<7の条件に当てはまるかを確認する
.L3: ;L3ラベルの処理がfor文の中身に相当
	mov	eax, DWORD PTR -8[rbp] ; eax = i 
	add	DWORD PTR -4[rbp], eax ; a = a + eax
	add	DWORD PTR -8[rbp], 1   ; i++
.L2:
	cmp	DWORD PTR -8[rbp], 6 ; i==6 ならば L3へ跳ぶ(iがintの場合 i<7 は i<=6 と等価)
	jle	.L3
	mov	eax, 0   ; return 0（main関数の戻り値はeax経由で返す）
	;後略...

```
#### 以下の流れになっていることが分かりました。
スタックへ変数a,iを格納
ラベルL2にてi==6の判定を行う
i<=6の場合ラベルL3の中でa+=i及びi++を実行
iが7になったら終了
eaxにmain関数の返り値0を格納

eaxが本当に返り値を表していることの根拠
https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
>Return values
A scalar return value that can fit into 64 bits, including the __m64 type, is returned through RAX. Nonscalar types including floats, doubles, and vector types such as __m128, __m128i, __m128d are returned in XMM0. The state of unused bits in the value returned in RAX or XMM0 is undefined.
>(機械翻訳：64ビットに収まるスカラー戻り値（__m64型を含む）はRAXレジスタを通じて返されます。浮動小数点数（float/double）やベクトル型（__m128、__m128i、__m128dなど）を含む非スカラー型はXMM0レジスタに返されます。RAXまたはXMM0で返される値のうち、使用されなかったビットの状態は未定義です。)

eaxとraxはビット数が違うだけで同じレジスタです。(よね？)

以上