バカ正直に計算しようとするとすぐ計算量が膨大になり、計算できなくなるたぐいの関数です。
これをアセンブリでバカ正直に計算させるコードを書いてみました。階乗を計算させるコードのおまけ付きです。
実際に実行させたところ、ack(3, 12) あたりになるとスタックがあふれました。
スタックサイズを調整すればもうちょっといけると思います。
使用した高速化のテクニック
- 末尾再帰を CALL から JMP に置き換え
 - TEST+JE でmacro fusion できる命令形式にした
 - INC / DEC を ADD / SUB に置き換えて、フラグレジスタの依存関係を解消
 - MOV RDX, 1 を MOV EDX, 1 にして命令長を短縮
 
    .code
ack PROC public
    ; RCX = m, RDX = n
    TEST    RCX, RCX
    JE      m_zero
    TEST    RDX, RDX
    JE      n_zero
    PUSH    RCX
    SUB     RDX, 1
    CALL    ack
    POP     RCX
    SUB     RCX, 1
    MOV     RDX, RAX
    JMP     ack
n_zero:
    MOV     EDX, 1
    SUB     RCX, 1
    JMP     ack
m_zero:
    MOV     RAX, RDX
    ADD     RAX, 1
    RET
    ack ENDP
factorial PROC public
    
    MOV     EAX, 1
    CMP     RCX, 1
    JLE     f_ret
f_loop:
    IMUL    RAX, RCX
    SUB     RCX, 1
    CMP     RCX, 1
    JNLE    f_loop
f_ret:
    RET
    factorial ENDP
    END
一応 C で書いた以下のコードよりは、3割ぐらい速いようです(Visual C++ 2010 で /O2 としてコンパイル)。階乗は微妙に速いだけでほとんど変わりませんでした。CPU は Penryn ベースの Core2 Duo です。
int64_t factorial_c(int64_t n)
{
    int64_t r = 1;
    while(n > 1) r *= n--;
    return r;
}
int64_t ack_c(int64_t m, int64_t n)
{
    return m == 0 ? n + 1 : n == 0 ? ack_c(m - 1, 1) : ack_c(m - 1, ack_c(m, n - 1));
}