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に変えれば素数を求める範囲が変わるわけです。
リンクするには、
所感
みた感じではアセンブラに無駄なコードはない、
高速化を目指す場合でも、
普通の人では、プログラミングはC言語で十分なわけです。
次は並列化してみましょう