関数の定義だけ考える

昨日は、なんだか悩んでしまってたのですが、
関数には関数の呼び出し部分と、関数定義の2つがあって、当たり前なんですけど、
昨日はごっちゃになっていたので今日は関数定義の方だけ考えることにしました。
ということで、もう一度最初から

int a(int a,int b,int c,int d,int e,int f,int g,int h,int i) {
  return a+b+c+d+e+f+g+h+i;
}

こういうプログラムを作って、コンパイルします。

>gcc fn.c -S -m64

すると以下のようになります。

        .text
.globl _a
_a:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    %edi, -4(%rbp)
        movl    %esi, -8(%rbp)
        movl    %edx, -12(%rbp)
        movl    %ecx, -16(%rbp)
        movl    %r8d, -20(%rbp)
        movl    %r9d, -24(%rbp)
        movl    -8(%rbp), %eax
        addl    -4(%rbp), %eax
        addl    -12(%rbp), %eax
        addl    -16(%rbp), %eax
        addl    -20(%rbp), %eax
        addl    -24(%rbp), %eax
        addl    16(%rbp), %eax
        addl    24(%rbp), %eax
        addl    32(%rbp), %eax
        leave
        ret
object fn {
  def asm(s:String) {
    println(s)
  }
  val regs = List("%edi","%esi","%edx","%ecx","%r8d","%r9d")

  def main(argv:Array[String]) {
    val args = List("a","b","c","d","e","f","g","h","i")
    h(args,regs)
  }
  var c = 0
  var c2 = 8
  def h(as:List[String], rs:List[String]) {
    (as, rs) match {
      case (List(),_) =>
      case (as, List()) =>
        h2(as)
      case (a::as,r::rs) =>
        c -= 4
        asm("movl "+r+", "+c+"(%rbp)")
        h(as,rs)
    }
  }

  def h2(as:List[String]) {
    as match {
      case List() =>
      case a::as =>
        c2 += 8
        c -= 4
        asm("movl "+c2+"(%rbp), "+c+"(%rbp)")
        h2(as)
    }
  }
}

でこんなプログラムを実行すると、

>scala fn

こんな出力が得られました。これは、受け取った引数をメモリに入れるだけのプログラムです。
というものを作ってみました。

movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl %edx, -12(%rbp)
movl %ecx, -16(%rbp)
movl %r8d, -20(%rbp)
movl %r9d, -24(%rbp)
movl 16(%rbp), -28(%rbp)
movl 24(%rbp), -32(%rbp)
movl 32(%rbp), -36(%rbp)

次に考えないと行けないのは、メモリ上の引数はそのまま使って、レジスタ上の引数は今作った感じで一度メモリに入れるということを
どこかのタイミングでうまいことやる。なんだろうなぁ、
まず、変数名からアドレスに置き換えるmapを作って、変数名を置き換える必要があります。

Map(
  "a"->"-4(%rbp)",
  "b"->"-8(%rbp)",
  "c"->"-12(%rbp)",
  "d"->"-16(%rbp)",
  "e"->"-20(%rbp)",
  "f"->"-24(%rbp)",
  "g"->"16(%rbp)",
  "h"->"24(%rbp)",
  "i"->"32(%rbp)"
)

あと、

movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl %edx, -12(%rbp)
movl %ecx, -16(%rbp)
movl %r8d, -20(%rbp)
movl %r9d, -24(%rbp)

こういうプロローグの部分で引数をメモリに格納する必要があります。
また、引数以外の変数のメモリもあわせて用意しないといけません。
ってことなんだけど、なんだか、考えがごちゃごちゃしてます。
ということを、週末に作ってみて、すっきりするといいなぁっと思ってます。
ここは苦しいんだけど、なれると楽にすっきりしてしまうんだけど、
っていうのをできれば、苦しまずに通る方法を見つけ出したいところなので、よけい大変という。
大変だけど、見つければみんな嬉しいということになるはずなので、まったり考えます。