2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

スタックを使わずに引数何個渡せるか

Last updated at Posted at 2020-09-27

スタックを使わずに引数何個渡せるか調べた。

調査対象は以下の コンパイラ / コンパイラ・オプション。

名前 コンパイラオプションなど
cortex-m4-hard arm-none-eabi-gcc -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
cortex-m4-soft arm-none-eabi-gcc -mthumb -mcpu=cortex-m4 -mfloat-abi=soft -mfpu=fpv4-sp-d16
cortex-a53-32hard arm-none-eabi-gcc -mcpu=cortex-a53 -mfloat-abi=hard
cortex-a53-32soft arm-none-eabi-gcc -mcpu=cortex-a53 -mfloat-abi=soft
cortex-a53-ilp32 aarch64-none-elf-gcc -mabi=ilp32 -mcpu=cortex-a53 -march=armv8-a
cortex-a53-lp64 aarch64-none-elf-gcc -mabi=lp64 -mcpu=cortex-a53 -march=armv8-a
x64ms gcc-10 -mabi=ms
x64sysv gcc-10 -mabi=sysv

まとめ

ARM(32bit)

32bit までの整数型は整数レジスタ1個使う。4個まで使える。

Thumb でも ARM でも大差ない。

浮動小数点型は -mfloat-abi=soft-mfloat-abi=hard かで全然ちがう。
-mfloat-abi=hard だと、浮動小数点数レジスタで引数渡せる。
なんと float なら16個、 double でも8個もレジスタで渡せる。

-mfloat-abi=soft だと、整数用の普通のレジスタで渡すので、 float だと 32bit レジスタ1個、 double だと 2個消費する。

中身にメンバが2個以上ある構造体があるとすぐにスタックに割り当てられる。
struct { uint16_t a; }; だと1個なのでレジスタを使うけど
struct { uint8_t a, b; }; だと2個なのでスタックを使う。

ARM(64bit)

64bit までの整数型は整数レジスタ1個使う。8個まで使える。
浮動小数点数は double でも float でもレジスタ1個使う。8個まで使える。

ARM64 には -mfloat-abi みたいなものはない。

ARM(32bit) と異なり、構造体でもレジスタを使う。
uint8_t の限界は 8 個だけど、 struct{ uint8_t a, b; }; でもスタックを使わずに8個渡せる。

ABI は ilp32lp64 があるんだけど、同じだった。

amd64

amd64 の ABI は、 sysv と ms がある。
sysv は Linux などで使われている方式らしい。
ms は、 Windows で使われているらしい。

amd64(ms)

組み込み型は4個まで渡せる。
浮動小数点数と整数は違うレジスタを使うけど、足して4個まで。

構造体は、1個のサイズが 64bit までならレジスタに乗せて、それ以上ならスタックに乗せるみたい。

amd64(sysv)

整数型は 6個 まで渡せる。
それとは別に、浮動小数点型を8個まで渡せる。
構造体になってもこのレジスタを使える。

調査

https://github.com/nabetani/arm-x64-regarg のように調査した。

本当は ABI のドキュメントを読めばいいんだろうけど、アセンブラを吐かせて調べた。

一種類の型

表内の数字は、スタックを使わないで引数を渡せる個数。

組み込み型

命令セット 条件 char short int32_t int64_t void* float double
ARM(32bit) cortex-a53-32hard 4 4 4 2 4 16 8
ARM(32bit) cortex-a53-32soft 4 4 4 2 4 4 2
ARM(32bit, Thumb) cortex-m4-hard 4 4 4 2 4 16 8
ARM(32bit, Thumb) cortex-m4-soft 4 4 4 2 4 4 2
ARM(64bit) cortex-a53-ilp32 8 8 8 8 8 8 8
ARM(64bit) cortex-a53-lp64 8 8 8 8 8 8 8
amd64 x64ms 4 4 4 4 4 4 4
amd64 x64sysv 6 6 6 6 6 8 8

構造体

命令セット 条件 char × 2 short × 1 int32_t × 2 int32_t × 4 int32_t + float int32_t + double
ARM(32bit) cortex-a53-32hard 0 4 0 0 0 0
ARM(32bit) cortex-a53-32soft 0 4 0 0 0 0
ARM(32bit, Thumb) cortex-m4-hard 0 4 0 0 0 0
ARM(32bit, Thumb) cortex-m4-soft 0 4 0 0 0 0
ARM(64bit) cortex-a53-ilp32 8 8 8 4 8 4
ARM(64bit) cortex-a53-lp64 8 8 8 4 8 4
amd64 x64ms 4 4 4 0 4 0
amd64 x64sysv 6 6 6 3 6 6

複数の型の混在

✅ は、レジスタのみで渡せる。
❌ は、スタックを使う。

double\int32_t

cortex-a53-32hard

double\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9

cortex-a53-32soft

double\int32_t 1 2 3 4 5 6 7 8 9
1
2

cortex-a53-ilp32

double\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9

cortex-a53-lp64

double\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9

cortex-m4-hard

double\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9

cortex-m4-soft

double\int32_t 1 2 3 4 5 6 7 8 9
1
2

x64ms

double\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4

x64sysv

double\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9

float\int32_t

cortex-a53-32hard

float\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

cortex-a53-32soft

float\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4

cortex-a53-ilp32

float\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9

cortex-a53-lp64

float\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9

cortex-m4-hard

float\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

cortex-m4-soft

float\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4

x64ms

float\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4

x64sysv

float\int32_t 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9

int32_t\short

cortex-a53-32hard

int32_t\short 1 2 3 4 5 6 7 8 9
1
2
3
4

cortex-a53-32soft

int32_t\short 1 2 3 4 5 6 7 8 9
1
2
3
4

cortex-a53-ilp32

int32_t\short 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8

cortex-a53-lp64

int32_t\short 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8

cortex-m4-hard

int32_t\short 1 2 3 4 5 6 7 8 9
1
2
3
4

cortex-m4-soft

int32_t\short 1 2 3 4 5 6 7 8 9
1
2
3
4

x64ms

int32_t\short 1 2 3 4 5 6 7 8 9
1
2
3
4

x64sysv

int32_t\short 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6

感想

8bit 整数をレジスタに4個つめたりするんだろうと思ってたんだけど、そういうことはないみたいで、意外だった。

ARM32 で構造体がすぐにスタックに行くのは、昔は構造体を引数に渡す習慣がなくて軽視されていたからかなと思う。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?