透過彙編代碼分析C語言的數據對齊(Data Alignment)與參數傳遞

C代碼

#include <stdio.h>
typedef struct S {
  short a;
  int b;
  long c;
  long d;
  long e;
  long f;
  long g;
  long h;
  short i;
} S;

void foo(S s) {
  
  printf("%hd, %d, %ld, %ld, %ld, %ld, %ld, %ld, %hd\n", 
      s.a, s.b, s.c, s.d, s.e, s.f, s.g, s.h, s.i);
}

int main() {
  S s = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  foo(s);
  printf("%ld\n", sizeof(short));
}

gcc -S -g test.c 生成的彙編代碼

	.file	"test_align.c"
	.text
.Ltext0:
	.section	.rodata
	.align 8
.LC0:
	.string	"%hd, %d, %ld, %ld, %ld, %ld, %ld, %ld, %hd\n"
	.text
	.globl	foo
	.type	foo, @function
foo:
.LFB0:
	.file 1 "test_align.c"
	.loc 1 14 0
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	.loc 1 17 0
	movzwl	72(%rbp), %eax
	.loc 1 16 0
	movswl	%ax, %r9d
	movq	64(%rbp), %r8
	movq	56(%rbp), %rdi
	movq	48(%rbp), %rsi
	movq	40(%rbp), %r11
	movq	32(%rbp), %r10
	movq	24(%rbp), %rcx
	movl	20(%rbp), %edx
	.loc 1 17 0
	movzwl	16(%rbp), %eax
	.loc 1 16 0
	cwtl
	pushq	%r9
	pushq	%r8
	pushq	%rdi
	pushq	%rsi
	movq	%r11, %r9
	movq	%r10, %r8
	movl	%eax, %esi
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	addq	$32, %rsp
	.loc 1 18 0
	nop
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	foo, .-foo
	.section	.rodata
.LC1:
	.string	"%ld\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB1:
	.loc 1 20 0
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$64, %rsp
	.loc 1 21 0
	movw	$1, -64(%rbp)
	movl	$2, -60(%rbp)
	movq	$3, -56(%rbp)
	movq	$4, -48(%rbp)
	movq	$5, -40(%rbp)
	movq	$6, -32(%rbp)
	movq	$7, -24(%rbp)
	movq	$8, -16(%rbp)
	movw	$9, -8(%rbp)
	.loc 1 22 0
	pushq	-8(%rbp)
	pushq	-16(%rbp)
	pushq	-24(%rbp)
	pushq	-32(%rbp)
	pushq	-40(%rbp)
	pushq	-48(%rbp)
	pushq	-56(%rbp)
	pushq	-64(%rbp)
	call	foo
	addq	$64, %rsp
	.loc 1 23 0
	movl	$2, %esi
	leaq	.LC1(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$0, %eax
	.loc 1 24 0
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main

解析如下

先看struct 初始化後的棧分佈圖,設棧底爲0:

棧頂                             													          棧底
	|--a---|--b--|----c-----|-----d----|----e-----|----f-----|----g-----|----h-----|----i-----|
  -64     -60   -56       -48        -40         -32       -24         -16        -8          0

從棧分佈情況可以看出struct裏每個元素的起始地址都是自身長度的整數倍。

傳參數的棧:
棧頂
	 |--a----b--|----c----|----d----|----e----|----f----|----g----|----h----|--i------|
 
 從棧分佈情況可以看出處理器傳輸數據是以8位爲單位的。

從參數棧內取參, 現在設棧頂爲0:
棧頂
	|----返回地址----|----RBP----|--a--|--b--|----c----|----d----|----e----|----f----|----g----|----h----|--i------|
   0                8          16    20    24        32        40         48       56         64        72



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章