ページ

2012-09-09

x86/x86_64関数呼び出しチートシートを書いた

アセンブラはいまのところたまにしか触れないので、espとebpってどっちがどっちだっけとか、ebpからプラスとマイナスはどっちがどっちだっけとか、触れるたびに思ってしまう。そんなとき思い出すために、x86/x86_64関数呼び出しチートシートを書いた。呼び出し規約(calling convention)のcheet sheetみたいになってるけど、一番必要だったのは左上のスタックの絵。
(リンクでPDF。書く都合でA3にしたけど、A4で印刷しても読めると思う。)


本当はそれぞれに対して絵をつけたかったんだけど、それどころではなかった。
勉強のために書いたくらいで全然詳しくないので、間違っているところがあればぜひ教えてくださいまし。

以下余談。

興味深いのは、64bit版のcl.exe(on Windows)とgcc(on Linux)の挙動の違い。関数の引数をスタックにpushするときに、cl.exeではraxに入れてからメモリに置くんだけど、gccはDWORDで区切ってそのままメモリに置く。最適化なし(/Odと-O0)なので、-O2とかにすればまた違うんだろうけどね。

cl.exe版(cl /Od /Zi):
  0000000140001030: 48 83 EC 58        sub         rsp,58h
  0000000140001034: 48 B8 08 00 FF FF  mov         rax,0AAAAFFFF0008h
                    AA AA 00 00
  000000014000103E: 48 89 44 24 38     mov         qword ptr [rsp+38h],rax
  0000000140001043: 48 B8 07 00 FF FF  mov         rax,0AAAAFFFF0007h
                    AA AA 00 00
  000000014000104D: 48 89 44 24 30     mov         qword ptr [rsp+30h],rax
  0000000140001052: 48 B8 06 00 FF FF  mov         rax,0AAAAFFFF0006h
                    AA AA 00 00
  000000014000105C: 48 89 44 24 28     mov         qword ptr [rsp+28h],rax
  0000000140001061: 48 B8 05 00 FF FF  mov         rax,0AAAAFFFF0005h
                    AA AA 00 00
  000000014000106B: 48 89 44 24 20     mov         qword ptr [rsp+20h],rax
  0000000140001070: 49 B9 04 00 FF FF  mov         r9,0AAAAFFFF0004h
                    AA AA 00 00
  000000014000107A: 49 B8 03 00 FF FF  mov         r8,0AAAAFFFF0003h
                    AA AA 00 00
  0000000140001084: 48 BA 02 00 FF FF  mov         rdx,0AAAAFFFF0002h
                    AA AA 00 00
  000000014000108E: 48 B9 01 00 FF FF  mov         rcx,0AAAAFFFF0001h
                    AA AA 00 00
  0000000140001098: E8 6D FF FF FF     call        @ILT+5(callee)

gcc版(gcc -O0):
  400498:       48 83 ec 20             sub    rsp,0x20
  40049c:       c7 44 24 08 08 00 ff    mov    DWORD PTR [rsp+0x8],0xffff0008
  4004a3:       ff
  4004a4:       c7 44 24 0c aa aa 00    mov    DWORD PTR [rsp+0xc],0xaaaa
  4004ab:       00
  4004ac:       c7 04 24 07 00 ff ff    mov    DWORD PTR [rsp],0xffff0007
  4004b3:       c7 44 24 04 aa aa 00    mov    DWORD PTR [rsp+0x4],0xaaaa
  4004ba:       00
  4004bb:       49 b9 06 00 ff ff aa    mov    r9,0xaaaaffff0006
  4004c2:       aa 00 00
  4004c5:       49 b8 05 00 ff ff aa    mov    r8,0xaaaaffff0005
  4004cc:       aa 00 00
  4004cf:       48 b9 04 00 ff ff aa    mov    rcx,0xaaaaffff0004
  4004d6:       aa 00 00
  4004d9:       48 ba 03 00 ff ff aa    mov    rdx,0xaaaaffff0003
  4004e0:       aa 00 00
  4004e3:       48 be 02 00 ff ff aa    mov    rsi,0xaaaaffff0002
  4004ea:       aa 00 00
  4004ed:       48 bf 01 00 ff ff aa    mov    rdi,0xaaaaffff0001
  4004f4:       aa 00 00
  4004f7:       e8 06 00 00 00          call   400502 

たぶん、movは即値ではQWORDに詰められないんだろうね。

おまけとして、別のアーキテクチャでやったらどうか?ということで、x86版のCコードをARMで試してみた。
00008398 <caller>:
    8398:       e92d4800        push    {fp, lr}
    839c:       e28db004        add     fp, sp, #4
    83a0:       e24dd008        sub     sp, sp, #8
    83a4:       e59f0020        ldr     r0, [pc, #32]   ; 83cc 
    83a8:       e59f1020        ldr     r1, [pc, #32]   ; 83d0 
    83ac:       e59f2020        ldr     r2, [pc, #32]   ; 83d4 
    83b0:       e59f3020        ldr     r3, [pc, #32]   ; 83d8 
    83b4:       eb000008        bl      83dc 
    83b8:       e1a03000        mov     r3, r0
    83bc:       e50b3008        str     r3, [fp, #-8]
    83c0:       e24bd004        sub     sp, fp, #4
    83c4:       e8bd4800        pop     {fp, lr}
    83c8:       e12fff1e        bx      lr
    83cc:       ffff0001        .word   0xffff0001
    83d0:       ffff0002        .word   0xffff0002
    83d4:       ffff0003        .word   0xffff0003
    83d8:       ffff0004        .word   0xffff0004

000083dc <callee>:
    83dc:       e52db004        push    {fp}            ; (str fp, [sp, #-4]!)
    83e0:       e28db000        add     fp, sp, #0
    83e4:       e24dd01c        sub     sp, sp, #28
    83e8:       e50b0010        str     r0, [fp, #-16]
    83ec:       e50b1014        str     r1, [fp, #-20]
    83f0:       e50b2018        str     r2, [fp, #-24]
    83f4:       e50b301c        str     r3, [fp, #-28]
    83f8:       e51b2010        ldr     r2, [fp, #-16]
    83fc:       e51b3014        ldr     r3, [fp, #-20]
    8400:       e0823003        add     r3, r2, r3
    8404:       e50b300c        str     r3, [fp, #-12]
    8408:       e51b200c        ldr     r2, [fp, #-12]
    840c:       e51b3018        ldr     r3, [fp, #-24]
    8410:       e0633002        rsb     r3, r3, r2
    8414:       e50b300c        str     r3, [fp, #-12]
    8418:       e51b200c        ldr     r2, [fp, #-12]
    841c:       e51b101c        ldr     r1, [fp, #-28]
    8420:       e0030291        mul     r3, r1, r2
    8424:       e50b3008        str     r3, [fp, #-8]
    8428:       e51b3008        ldr     r3, [fp, #-8]
    842c:       e1a00003        mov     r0, r3
    8430:       e28bd000        add     sp, fp, #0
    8434:       e8bd0800        pop     {fp}
    8438:       e12fff1e        bx      lr

さすがに違うね。

0 件のコメント:

コメントを投稿