* バイナリサイズ比較
-(by [[K]], 2025.07.27)
** (1) これをコンパイルして(リンクはしないで).textのサイズを調べる。
//#include "kharc.h"
int openWin(int xsiz, int ysiz);
int isClose(int win);
void wait(int msec);
void fillRect(int w, int xsiz, int ysiz, int x, int y, int col);
void drawLine(int w, int x0, int y0, int x1, int y1, int col);
int ff16Sqrt(int x);
int ff16Sin(int x);
void wave()
{
int w, t, x, y, d, z, x1, y1, gx[1764], gy[1764];
w = openWin(640, 480);
for (t = 0; isClose(w) == 0; t++) {
wait(8); fillRect(w, 640, 480, 0, 0, 0x000000);
for (y1 = 0; y1 < 42; y1++) { y = y1 - 20;
for (x1 = 0; x1 < 42; x1++) { x = x1 - 20;
d = ff16Sqrt((x * x + y * y) * 65536);
z = ff16Sin(((d * 652) >> 12) - 1043 * t) * 100 / (d + 327680);
d = y1 * 42 + x1;
gx[d] = (x * 8 - y * 8 + z * 0) + 320;
gy[d] = (x * 4 + y * 4 + z * 1) + 240;
if (x1 >= 1 && y1 >= 1) {
drawLine(w, gx[d - 43], gy[d - 43], gx[d - 42], gy[d - 42], 0x00ffff);
drawLine(w, gx[d - 43], gy[d - 43], gx[d - 1], gy[d - 1], 0x00ffff);
}
}
}
}
}
-このプログラムではintは32bit以上のビット幅を想定しています。
-wait()関数はミリ秒単位でsleepする関数ですが、sleepに入る前にグラフィックバッファをflushします(そういう仕様なのでコード内に明示的なflush関数の呼び出しはありません)。
-ff16Sqrt()やff16Sin()は下記のような動作をする関数です。
int ff16Sqrt(int x) { return (int) (sqrt(x * (1.0 / 65536)) * 65536); }
int ff16Sin(int x) { return (int) (sin(x * (2 * 3.14159265358979323 / 65536)) * 65536); }
-ちなみに実行するとこんな絵が出て、水面が動きます。
--https://essen.osask.jp/files/pic20250626a.png
** (2) 実験手順
>gcc --version
gcc (GCC) 3.4.5 (mingw-vista special r3)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>gcc -c -Os 3dwave-bench.c
>objdump -h 3dwave-bench.o
3dwave-bench.o: file format pe-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000001e4 00000000 00000000 0000008c 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 00000000 2**2
ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000000 2**2
ALLOC
-この場合、.textのサイズは0x1e4バイト。つまり484バイト。
-実行ファイルは.textの情報だけからでは構築できないけれども、しかし大雑把には目安になると考えました。
-ELFでもCOFFでも(=つまりオブジェクトファイルフォーマットが違っても)、.textの中身は基本的には同じになりますし、サイズも同じになります。
** (3) 結果のまとめ
|RIGHT:''107バイト''|uck [ultra compact kharc]|(uckのみ、.textだけではなくヘッダや全セクションを含んだ実行ファイルサイズ)|2025.07.28版 (超高密度の自作バイトコード)|
|RIGHT:''95バイト''|uck [ultra compact kharc]|(uckのみ、.textだけではなくヘッダや全セクションを含んだ実行ファイルサイズ)|2025.08.05版 (超高密度の自作バイトコード)|
|||||
|RIGHT:276バイト|arc-elf (HS)| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (arc-elf)|
|RIGHT:286バイト|arm-eabi (thumb2, armv7-a)| -mthumb -mthumb-interwork -march=armv7-a -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (arm-eabi)|
|RIGHT:301バイト|rx-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (rx-elf)|
|RIGHT:307バイト|WCOFF x86|アセンブラ手書き →(4)参照|(考察)手書きすれば 20% くらい削減できるというめやすを得た。|
|RIGHT:320バイト|bfin-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (bfin-elf)|
|RIGHT:344バイト|arm-eabi (thumb, arm7tdmi, armv4t)| -mthumb -mthumb-interwork -mcpu=arm7tdmi -march=armv4t -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (arm-eabi)|
|RIGHT:346バイト|mn10300-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (mn10300-elf)|
|RIGHT:348バイト|m68k-elf| -mcpu=68020 -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (m68k-elf)|
//|RIGHT:356バイト|ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV) (たぶんThumb)|arm-linux-gnueabihf-gcc -c -Os -o a.o bench.c|arm-linux-gnueabihf-gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0|
|RIGHT:360バイト|cr16-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (cr16-elf)|
|RIGHT:378バイト|msp430-elf| -mlarge -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (msp430-elf)|
|RIGHT:383バイト|i386-elf| -Os|GNU C17 (GCC) version 11.5.0|
|RIGHT:392バイト|xstormy16-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (xstormy16-elf)|
|RIGHT:401バイト|x86_64-elf (x86-64)| -m64 -mtune=generic -march=x86-64 -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (x86_64-elf)|
|RIGHT:404バイト|arm-eabi (arm7tdmi, armv4t)| -mcpu=arm7tdmi -marm -march=armv4t -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (arm-eabi)|
//|RIGHT:404バイト|strongarm-eabi (arm7tdmi, armv4t)| -mcpu=arm7tdmi -marm -march=armv4t -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (strongarm-eabi)|
//|RIGHT:404バイト|xscale-eabi (arm7tdmi, armv4t)| -mcpu=arm7tdmi -marm -march=armv4t -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (xscale-eabi)|
|RIGHT:408バイト|mips-elf (mips16)| -mips16 -msoft-float -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (mips-elf)|
|RIGHT:411バイト|vax-linux| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (vax-linux)|
|RIGHT:412バイト|rl78-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (rl78-elf)|
|RIGHT:436バイト|aarch64-elf (armv8-a+crc)| -mcmodel=large -mlittle-endian -mabi=lp64 -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (aarch64-elf)|
|RIGHT:436バイト|h8300-elf| -mh -mn -malign-300 -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (h8300-elf)|
|RIGHT:444バイト|m32r-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (m32r-elf)|
|RIGHT:448バイト|fr30-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (fr30-elf)|
|RIGHT:450バイト|riscv-elf (rv32imac)| -mabi=ilp32 -misa-spec=2.2 -march=rv32imac -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (riscv-elf)|
|RIGHT:452バイト|nios2-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (nios2-elf)|
|RIGHT:456バイト|s390-linux (z900)| -m31 -mesa -march=z900 -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (s390-linux)|
|RIGHT:464バイト|powerpc64-linux| -mpowerpc64 -mcpu=powerpc64 -mtune=powerpc64 -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (powerpc64-linux)|
|RIGHT:472バイト|mcore-elf| -funsigned-bitfields -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (mcore-elf)|
|RIGHT:480バイト|frv-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (frv-elf)|
|RIGHT:484バイト|pe-i386|gcc -c -Os 3dwave-bench.c|gcc (GCC) 3.4.5 (mingw-vista special r3)|
|RIGHT:506バイト|moxie-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (moxie-elf)|
|RIGHT:512バイト|or1k-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (or1k-elf)|
|RIGHT:512バイト|xtensa-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (xtensa-elf)|
|RIGHT:516バイト|mips-elf (mips1)| -msoft-float -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (mips-elf)|
|RIGHT:524バイト|h8300s-elf| -ms -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (h8300-elf)|
//|RIGHT:527バイト|ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV)|gcc -m64 -c -Os bench.c|gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0|
//|RIGHT:540バイト|ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV)|aarch64-linux-gnu-gcc -c -Os -o a.o bench.c|aarch64-linux-gnu-gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0|
|RIGHT:544バイト|mips64-elf (mips64)| -mips64 -march=mips64 -mtune=mips64 -mlong64 -msoft-float -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (mips64-elf)|
|RIGHT:556バイト|pru-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (pru-elf)|
|RIGHT:568バイト|riscv32-elf (rv32imafd)| -mabi=ilp32 -misa-spec=2.2 -march=rv32imafd -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (riscv32-elf)|
//|RIGHT:601バイト|ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV)|gcc -m32 -c -Os bench.c|gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0|
|RIGHT:604バイト|hppa-linux| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (hppa-linux)|
|RIGHT:660バイト|sparc64-elf (v9)| -mcpu=v9 -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (sparc64-elf)|
|RIGHT:692バイト|alpha-linux (ev4)| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (alpha-linux)|
|RIGHT:692バイト|riscv64-elf (rv64imafd)| -mabi=lp64 -misa-spec=2.2 -march=rv64imafd -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (riscv64-elf)|
|RIGHT:768バイト|epiphany-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (epiphany-elf)|
|RIGHT:1232バイト|ia64-elf| -g -Os -fno-builtin -fomit-frame-pointer -fno-inline|GNU C17 (GCC) version 11.5.0 (ia64-elf)|
-[謝辞] この表の作成のためにkozosの坂井さんに多大なご協力をいただきました。 https://kozos.jp
//|RIGHT:バイト|COFF OBJECT(14c:x86)|cl /O1 /Fobench.obj bench.c|Microsoft(R) C/C++ Optimizing Compiler Version 19.38.33135 for x86|
//|RIGHT:バイト|COFF OBJECT(8664:x64)|cl /O1 /Fobench.obj bench.c|Microsoft(R) C/C++ Optimizing Compiler Version 19.38.33135 for x64|
** (4) gccを使わずに、x86アセンブラ手書きで(1)のコードを作ってみた
-→307バイト
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[OPTIMIZE 1]
[OPTION 1]
[BITS 32]
[FILE '3dwave2.nas']
GLOBAL _wave
EXTERN __chkstk
EXTERN _openWin
EXTERN _isClose
EXTERN _wait
EXTERN _fillRect
EXTERN _ff16Sqrt
EXTERN _ff16Sin
EXTERN _drawLine
; t:[ebp-4], x:[ebp-8], y:[ebp-12], w:[ebp-16], x1:esi, y1:edi
[SECTION .text]
_wave:
pushad
mov ebp,esp
mov eax,16+1764*4*2
call __chkstk
push 480
push 640
call _openWin
pop ecx
pop ecx
mov dword [ebp-16],eax ; w
xor eax,eax
mov dword [ebp-4],eax ; t
lp0:
push 8
call _wait
xor eax,eax
push eax
push eax
push eax
push 480
push 640
push dword [ebp-16] ; w
call _fillRect
add esp,28
xor edi,edi
lp1:
lea eax,[edi-20]
mov dword [ebp-12],eax ; y
xor esi,esi
lp2:
lea eax,[esi-20]
mov dword [ebp-8],eax ; x
mov ecx,eax ; x
mov edx,dword [ebp-12] ; y
imul eax,edi,42
add eax,esi
lea ebx,[esp+eax*8]
lea eax,[ecx+40]
sub eax,edx
shl eax,3
mov dword [ebx+0],eax ; gx[d]=(x-y+40)*8
lea eax,[ecx+edx+60]
shl eax,2
mov dword [ebx+4],eax ; gy[d]=(x+y+60)*4
imul ecx,ecx
imul edx,edx
add ecx,edx
shl ecx,16
push ecx
call _ff16Sqrt
pop edx
push eax ; d
imul eax,eax,652
shr eax,12
mov ecx,dword [ebp-4] ; t
imul ecx,ecx,1043
sub eax,ecx
push eax
call _ff16Sin
pop ecx
imul eax,eax,100
cdq
pop ecx ; d
add ecx,327680
idiv ecx
add dword [ebx+4],eax
lea eax,[esi-1]
lea ecx,[edi-1]
or eax,ecx
js skp0
push 0xffff
push dword [ebx-42*8+4]
push dword [ebx-42*8+0]
push dword [ebx-43*8+4]
push dword [ebx-43*8+0]
push dword [ebp-16]
call _drawLine
push 0xffff
push dword [ebx-1*8+4]
push dword [ebx-1*8+0]
push dword [ebx-43*8+4]
push dword [ebx-43*8+0]
push dword [ebp-16]
call _drawLine
add esp,48
skp0:
inc esi
cmp esi,42
jl lp2
inc edi
cmp edi,42
jl lp1
inc dword [ebp-4]
push dword [ebp-16]
call _isClose
pop ecx
test eax,eax
jz lp0
mov esp,ebp
popad
ret
; >nask bench.nas bench.obj bench.lst
-(考察)手書きによって 383→307 になったので、手書きすれば 20% くらい削減できるというめやすを得た。