アセンブリ言語の教科書 第3章 数値のカウント(yieldで)

たのしいプログラミングをアセンブリで実現したくなったので、RubyのtimesをGASに移植してみた。

.text
.global main

main:   push %ebp
        mov  %esp,%ebp

        mov  $10, %eax

        push %eax
        push $print
        call times

        mov  $0, %eax
        leave
        ret
 
times:  push %ebp
        mov  %esp,%ebp

        mov  8(%ebp),%ebx
        mov 12(%ebp),%eax
        mov $0, %ecx

1:      push %ecx
        call *%ebx // yield
        pop  %ecx

        inc %ecx
        cmp %ecx, %eax
        jne  1b

        leave
        ret

print:  push %ebp
        mov  %esp,%ebp

        mov 8(%ebp),%eax

        push %eax
        push $count_s
        call printf

        leave
        ret
.data
count_s: .string "count : %d\n"

数を数え上げるというメソッドと表示するメソッドを分離し、timesを使いまわすことが可能になった。

結果は昨日と逆順。0から数え上げる。

問題はスタックをどう積んでいくか・・・うぅ悩む・・・。

参考

関数ポインタプログラミング時は必修。

Using as - 80386 Dependent Features

AT&T absolute (as opposed to PC relative) jump/call operands are prefixed by `*'

jump/callで絶対アドレスを指定する場合は、*を付ける。

英語なんて読んでられないので、逆アセンブルしたんだけどさ・・・。

追記

Matzにっき(2006-05-29) - yieldとProc#call
コメント欄。

call(無名関数呼び出し)と違うセマンティクスが必要だからyieldを使っているわけなので

yieldの実装は僕の予測とは違うのかもしれない。