見出し画像

Mac miniでアセンブラコードを動かしてみる

背景

東大数学の問題のおまけで素数であるかないか?を判定するコードを利用した。
では、プログラムを高速化するには?ってのが始まり
いつもPython、Pythonなので原点に戻ってM2 Macをアセンブラコードで動かしてみよう。

コード

ChatGPTにアセンブラコードを何度か書いてもらいましたが、エラーかNullとなり全く動きませんでした。
では、参考にしたのは下記のサイト

ここを参考にして、まずHellow WorldのコードをC言語からアセンブラに変換しました。

hellow.s

.section	__TEXT,__text,regular,pure_instructions
.build_version macos, 14, 0	sdk_version 14, 4
.globl	_start                           ; -- Begin function main
.p2align	2
_start:                                  ; @main
	.cfi_startproc
; %bb.0:
	sub	sp, sp, #32
	.cfi_def_cfa_offset 32
	stp	x29, x30, [sp, #16]             ; 16-byte Folded Spill
	add	x29, sp, #16
	.cfi_def_cfa w29, 16
	.cfi_offset w30, -8
	.cfi_offset w29, -16
	mov	w8, #0
	str	w8, [sp, #8]                    ; 4-byte Folded Spill
	stur	wzr, [x29, #-4]
	adrp	x0, l_.str@PAGE
	add	x0, x0, l_.str@PAGEOFF
	bl	_printf
	ldr	w0, [sp, #8]                    ; 4-byte Folded Reload
	ldp	x29, x30, [sp, #16]             ; 16-byte Folded Reload
	add	sp, sp, #32
	ret
	.cfi_endproc
                                        ; -- End function
.section	__TEXT,__cstring,cstring_literals
l_.str:                                 ; @.str
	.asciz	"Hello, world!\n"

.subsections_via_symbols

と、なります。
これを参考にしてChatGPTに素数を出力するアセンブラを書いてもらいましょう。

prime.s

.section    __TEXT,__cstring,cstring_literals
l_.str:                                 ; @.str
    .asciz  "Prime numbers up to %d:\n"

l_.str.1:                               ; @.str.1
    .asciz  "%d\n"

.subsections_via_symbols

.section    __TEXT,__text,regular,pure_instructions
.build_version macos, 14, 0 sdk_version 14, 4
.globl  _is_prime                       ; -- Begin function is_prime
.p2align    2
_is_prime:                              ; @is_prime
    .cfi_startproc
    sub sp, sp, #16
    .cfi_def_cfa_offset 16
    str w0, [sp, #8]
    ldr w8, [sp, #8]
    subs    w8, w8, #1
    cset    w8, gt
    tbnz    w8, #0, LBB0_2
    b   LBB0_1
LBB0_1:
    mov w8, #0
    and w8, w8, #0x1
    and w8, w8, #0x1
    strb    w8, [sp, #15]
    b   LBB0_9
LBB0_2:
    mov w8, #2
    str w8, [sp, #4]
    b   LBB0_3
LBB0_3:                                 ; =>This Inner Loop Header: Depth=1
    ldr w8, [sp, #4]
    ldr w9, [sp, #4]
    mul w8, w8, w9
    ldr w9, [sp, #8]
    subs    w8, w8, w9
    cset    w8, gt
    tbnz    w8, #0, LBB0_8
    b   LBB0_4
LBB0_4:                                 ;   in Loop: Header=BB0_3 Depth=1
    ldr w8, [sp, #8]
    ldr w10, [sp, #4]
    sdiv    w9, w8, w10
    mul w9, w9, w10
    subs    w8, w8, w9
    subs    w8, w8, #0
    cset    w8, ne
    tbnz    w8, #0, LBB0_6
    b   LBB0_5
LBB0_5:
    mov w8, #0
    and w8, w8, #0x1
    and w8, w8, #0x1
    strb    w8, [sp, #15]
    b   LBB0_9
LBB0_6:                                 ;   in Loop: Header=BB0_3 Depth=1
    b   LBB0_7
LBB0_7:                                 ;   in Loop: Header=BB0_3 Depth=1
    ldr w8, [sp, #4]
    add w8, w8, #1
    str w8, [sp, #4]
    b   LBB0_3
LBB0_8:
    mov w8, #1
    and w8, w8, #0x1
    and w8, w8, #0x1
    strb    w8, [sp, #15]
    b   LBB0_9
LBB0_9:
    ldrb    w8, [sp, #15]
    and w0, w8, #0x1
    add sp, sp, #16
    ret
    .cfi_endproc
                                        ; -- End function

.globl  _main                           ; -- Begin function main
.p2align    2
_main:                                  ; @main
    .cfi_startproc
    sub sp, sp, #48
    .cfi_def_cfa_offset 48
    stp x29, x30, [sp, #32]             ; 16-byte Folded Spill
    add x29, sp, #32
    .cfi_def_cfa w29, 16
    .cfi_offset w30, -8
    .cfi_offset w29, -16
    stur    wzr, [x29, #-4]
    mov w8, #100
    stur    w8, [x29, #-8]
    ldur    w9, [x29, #-8]
    mov x8, x9
    mov x9, sp
    str x8, [x9]
    adrp    x0, l_.str@PAGE
    add x0, x0, l_.str@PAGEOFF
    bl  _printf
    mov w8, #2
    stur    w8, [x29, #-12]
    b   LBB1_1
LBB1_1:                                 ; =>This Inner Loop Header: Depth=1
    ldur    w8, [x29, #-12]
    ldur    w9, [x29, #-8]
    subs    w8, w8, w9
    cset    w8, gt
    tbnz    w8, #0, LBB1_6
    b   LBB1_2
LBB1_2:                                 ;   in Loop: Header=BB1_1 Depth=1
    ldur    w0, [x29, #-12]
    bl  _is_prime
    tbz w0, #0, LBB1_4
    b   LBB1_3
LBB1_3:                                 ;   in Loop: Header=BB1_1 Depth=1
    ldur    w9, [x29, #-12]
    mov x8, x9
    mov x9, sp
    str x8, [x9]
    adrp    x0, l_.str.1@PAGE
    add x0, x0, l_.str.1@PAGEOFF
    bl  _printf
    b   LBB1_4
LBB1_4:                                 ;   in Loop: Header=BB1_1 Depth=1
    b   LBB1_5
LBB1_5:                                 ;   in Loop: Header=BB1_1 Depth=1
    ldur    w8, [x29, #-12]
    add w8, w8, #1
    stur    w8, [x29, #-12]
    b   LBB1_1
LBB1_6:
    mov w0, #0
    ldp x29, x30, [sp, #32]             ; 16-byte Folded Reload
    add sp, sp, #48
    ret
    .cfi_endproc
                                        ; -- End function

92行目の
mov w8, #100
の#100を#10なり#1000に変えれば素数を求める範囲が変わるわけです。

リンクするには、

% as -o prime.o prime.s
% clang -o prime prime.o -e _main -lc
./prime

コマンドライン

所感

みた感じではアセンブラに無駄なコードはない、
高速化を目指す場合でも、
普通の人では、プログラミングはC言語で十分なわけです。

次は並列化してみましょう

この記事が気に入ったらサポートをしてみませんか?