view doc/disas_examples/x86.fastcall_gnu.disas @ 499:fc614cb865c6

- doc and disasexample additions specific to non-trivial C++ aggregates as return values (incl. fixes to doc and additional LSB specific PPC32 section)
author Tassilo Philipp
date Mon, 04 Apr 2022 15:50:52 +0200
parents cb19b2fe2422
children
line wrap: on
line source

; #include <stdlib.h>
;
; void __attribute__((fastcall)) leaf_call(int b, int c, int d, int e, int f, int g, int h)
; {
; }
;
; void __attribute__((fastcall)) nonleaf_call(int a, int b, int c, int d, int e, int f, int g, int h)
; {
; 	/* use some local data */
; 	*(char*)alloca(220) = 'L';
; 	leaf_call(b, c, d, e, f, g, h);
; }
;
; int main()
; {
; 	nonleaf_call(0, 1, 2, 3, 4, 5, 6, 7);
; 	return 0;
; }



; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0 (w/ flags to simplify: -fno-stack-protector -fno-pic)

00001205 <leaf_call>:
    1205:       55                      push   %ebp                ; |
    1206:       89 e5                   mov    %esp,%ebp           ; | prolog
    1208:       83 ec 08                sub    $0x8,%esp           ; |
    120b:       89 4d fc                mov    %ecx,-0x4(%ebp)     ;
    120e:       89 55 f8                mov    %edx,-0x8(%ebp)     ;
    1211:       90                      nop                        ;
    1212:       c9                      leave                      ; |
    1213:       c2 14 00                ret    $0x14               ; | epilog

00001216 <nonleaf_call>:
    1216:       55                      push   %ebp                ; |
    1217:       89 e5                   mov    %esp,%ebp           ; | prolog
    1219:       83 ec 18                sub    $0x18,%esp          ; /
    121c:       89 4d f4                mov    %ecx,-0xc(%ebp)     ; in arg 0 -> local area on stack
    121f:       89 55 f0                mov    %edx,-0x10(%ebp)    ; in arg 1 -> local area on stack
    1222:       b8 10 00 00 00          mov    $0x10,%eax          ; |
    1227:       83 e8 01                sub    $0x1,%eax           ; |
    122a:       05 e8 00 00 00          add    $0xe8,%eax          ; |
    122f:       b9 10 00 00 00          mov    $0x10,%ecx          ; | alloca (seems like 220 is rounded up for stack alignment purposes)
    1234:       ba 00 00 00 00          mov    $0x0,%edx           ; |
    1239:       f7 f1                   div    %ecx                ; |
    123b:       6b c0 10                imul   $0x10,%eax,%eax     ; |
    123e:       29 c4                   sub    %eax,%esp           ; /
    1240:       89 e0                   mov    %esp,%eax           ; \
    1242:       83 c0 0f                add    $0xf,%eax           ; |
    1245:       c1 e8 04                shr    $0x4,%eax           ; | align alloca'd space
    1248:       c1 e0 04                shl    $0x4,%eax           ; |
    124b:       c6 00 4c                movb   $0x4c,(%eax)        ; write 'L' to alloca'd space
    124e:       8b 45 f0                mov    -0x10(%ebp),%eax    ; in arg 1 (from local area) -> eax (then copied to ecx/arg0, below, could be done directly)
    1251:       83 ec 0c                sub    $0xc,%esp           ; @@@ unsure why, alignment?
    1254:       ff 75 1c                pushl  0x1c(%ebp)          ; |
    1257:       ff 75 18                pushl  0x18(%ebp)          ; |
    125a:       ff 75 14                pushl  0x14(%ebp)          ; | read in args 3-7 from prev frame's param area, and ...
    125d:       ff 75 10                pushl  0x10(%ebp)          ; | ... push onto stack as arg 2-6
    1260:       ff 75 0c                pushl  0xc(%ebp)           ; |
    1263:       8b 55 08                mov    0x8(%ebp),%edx      ; arg 1 (via reg, read in arg 2 from prev frame's param area)
    1266:       89 c1                   mov    %eax,%ecx           ; arg 0 (via reg)
    1268:       e8 98 ff ff ff          call   1205 <leaf_call>    ; push return address and call
    126d:       83 c4 0c                add    $0xc,%esp           ; @@@ restore esp to what it was before pushing args
    1270:       90                      nop                        ;
    1271:       c9                      leave                      ; |
    1272:       c2 18 00                ret    $0x18               ; | epilog

00001275 <main>:
    1275:       8d 4c 24 04             lea    0x4(%esp),%ecx      ; |
    1279:       83 e4 f0                and    $0xfffffff0,%esp    ; |        @@@? alignment?
    127c:       ff 71 fc                pushl  -0x4(%ecx)          ; | prolog
    127f:       55                      push   %ebp                ; |
    1280:       89 e5                   mov    %esp,%ebp           ; |
    1282:       51                      push   %ecx                ; preserve ecx (so it can be used for passing arg 0)
    1283:       83 ec 04                sub    $0x4,%esp           ; @@@ unsure why, alignment?
    1286:       83 ec 08                sub    $0x8,%esp           ; @@@ unsure why, alignment? pointless
    1289:       6a 07                   push   $0x7                ; arg 7
    128b:       6a 06                   push   $0x6                ; arg 6
    128d:       6a 05                   push   $0x5                ; arg 5
    128f:       6a 04                   push   $0x4                ; arg 4
    1291:       6a 03                   push   $0x3                ; arg 3
    1293:       6a 02                   push   $0x2                ; arg 2
    1295:       ba 01 00 00 00          mov    $0x1,%edx           ; arg 1 (via reg)
    129a:       b9 00 00 00 00          mov    $0x0,%ecx           ; arg 0 (via reg)
    129f:       e8 72 ff ff ff          call   1216 <nonleaf_call> ; push return address and call
    12a4:       83 c4 08                add    $0x8,%esp           ; @@@ restore one of the two "sub...esp"s above
    12a7:       b8 00 00 00 00          mov    $0x0,%eax           ; return value
    12ac:       8b 4d fc                mov    -0x4(%ebp),%ecx     ; restore ecx
    12af:       c9                      leave                      ; |
    12b0:       8d 61 fc                lea    -0x4(%ecx),%esp     ; | epilog
    12b3:       c3                      ret                        ; |



; ---------- vararg call (shows that all args are pushed) ---------->

; void __attribute__((fastcall)) leaf_call(int a, short b, char c, ...)
; {
; }
;
; int main()
; {
;   leaf_call(0, 1, 2, 3, 4, 5, 6, 7LL);
;   return 0;
; }



; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0 (w/ flags to simplify: -fno-stack-protector -fno-pic)

00001205 <leaf_call>:
    1205:       55                      push   %ebp
    1206:       89 e5                   mov    %esp,%ebp
    1208:       90                      nop
    1209:       5d                      pop    %ebp
    120a:       c3                      ret

0000120b <main>:
    120b:       55                      push   %ebp
    120c:       89 e5                   mov    %esp,%ebp
    120e:       6a 00                   push   $0x0
    1210:       6a 07                   push   $0x7
    1212:       6a 06                   push   $0x6
    1214:       6a 05                   push   $0x5
    1216:       6a 04                   push   $0x4
    1218:       6a 03                   push   $0x3
    121a:       6a 02                   push   $0x2
    121c:       6a 01                   push   $0x1
    121e:       6a 00                   push   $0x0
    1220:       e8 e0 ff ff ff          call   1205 <leaf_call>
    1225:       83 c4 24                add    $0x24,%esp
    1228:       b8 00 00 00 00          mov    $0x0,%eax
    122d:       c9                      leave
    122e:       c3                      ret



; ---------- structs by value (arg and return value), struct arg not fitting in regs ---------->

; struct A { int x; short y; char z; long long t; };
;
; struct A __attribute__((fastcall)) leaf_call(struct A a, short b, long long c, char d, int e, int f, int g, long long h)
; {
;     a.x += 1;
;     return a;
; }
;
; int main()
; {
;   struct A a ={9, 99, 23, 12LL};
;   leaf_call(a, 1, 2, 3, 4, 5, 6, 7LL);
;   return 0;
; }



; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0 (w/ flags to simplify: -fno-stack-protector -fno-pic)

00001205 <leaf_call>:
    1205:       55                      push   %ebp              ; |
    1206:       89 e5                   mov    %esp,%ebp         ; | prolog
    1208:       83 ec 20                sub    $0x20,%esp        ; |
    120b:       89 4d fc                mov    %ecx,-0x4(%ebp)   ; ptr to retval space for struct (hidden first arg) -> local area
    120e:       8b 45 18                mov    0x18(%ebp),%eax   ;
    1211:       8b 55 24                mov    0x24(%ebp),%edx   ;
    1214:       66 89 45 f8             mov    %ax,-0x8(%ebp)    ;
    1218:       8b 45 1c                mov    0x1c(%ebp),%eax   ;
    121b:       89 45 f0                mov    %eax,-0x10(%ebp)  ;
    121e:       8b 45 20                mov    0x20(%ebp),%eax   ;
    1221:       89 45 f4                mov    %eax,-0xc(%ebp)   ;
    1224:       89 d0                   mov    %edx,%eax         ;
    1226:       88 45 ec                mov    %al,-0x14(%ebp)   ;
    1229:       8b 45 34                mov    0x34(%ebp),%eax   ;
    122c:       89 45 e0                mov    %eax,-0x20(%ebp)  ;
    122f:       8b 45 38                mov    0x38(%ebp),%eax   ;
    1232:       89 45 e4                mov    %eax,-0x1c(%ebp)  ;
    1235:       8b 45 08                mov    0x8(%ebp),%eax    ; |
    1238:       83 c0 01                add    $0x1,%eax         ; | a.x += 1 (written to param area of prev frame)
    123b:       89 45 08                mov    %eax,0x8(%ebp)    ; /
    123e:       8b 45 fc                mov    -0x4(%ebp),%eax   ; \        ptr to retval space
    1241:       8b 55 08                mov    0x8(%ebp),%edx    ; |
    1244:       89 10                   mov    %edx,(%eax)       ; |
    1246:       8b 55 0c                mov    0xc(%ebp),%edx    ; |
    1249:       89 50 04                mov    %edx,0x4(%eax)    ; | copy struct from param area in prev frame to retval space
    124c:       8b 55 10                mov    0x10(%ebp),%edx   ; |
    124f:       89 50 08                mov    %edx,0x8(%eax)    ; |
    1252:       8b 55 14                mov    0x14(%ebp),%edx   ; |
    1255:       89 50 0c                mov    %edx,0xc(%eax)    ; |
    1258:       8b 45 fc                mov    -0x4(%ebp),%eax   ; return value (passed-in hidden ptr)
    125b:       c9                      leave                    ; |
    125c:       c2 34 00                ret    $0x34             ; | epilog

0000125f <main>:
    125f:       8d 4c 24 04             lea    0x4(%esp),%ecx    ; |
    1263:       83 e4 f0                and    $0xfffffff0,%esp  ; |
    1266:       ff 71 fc                pushl  -0x4(%ecx)        ; | prolog
    1269:       55                      push   %ebp              ; |
    126a:       89 e5                   mov    %esp,%ebp         ; |
    126c:       51                      push   %ecx              ; preserve ecx (so it can be used for passing arg 0)
    126d:       83 ec 24                sub    $0x24,%esp        ; reserve stack space for struct (local area)
    1270:       c7 45 e8 09 00 00 00    movl   $0x9,-0x18(%ebp)  ; |                               int x
    1277:       66 c7 45 ec 63 00       movw   $0x63,-0x14(%ebp) ; |                               short y
    127d:       c6 45 ee 17             movb   $0x17,-0x12(%ebp) ; | struct values (local area)    char z
    1281:       c7 45 f0 0c 00 00 00    movl   $0xc,-0x10(%ebp)  ; |                               |
    1288:       c7 45 f4 00 00 00 00    movl   $0x0,-0xc(%ebp)   ; |                               | long long t
    128f:       8d 45 d8                lea    -0x28(%ebp),%eax  ; ptr to space used for struct retval (passed as hidden first arg) -> eax
    1292:       83 ec 04                sub    $0x4,%esp         ; @@@ unsure why, alignment? (also needed so what's in eax doesn't point below esp)
    1295:       6a 00                   push   $0x0              ; |
    1297:       6a 07                   push   $0x7              ; | arg 7
    1299:       6a 06                   push   $0x6              ; arg 6
    129b:       6a 05                   push   $0x5              ; arg 5
    129d:       6a 04                   push   $0x4              ; arg 4
    129f:       6a 03                   push   $0x3              ; arg 3
    12a1:       6a 00                   push   $0x0              ; |
    12a3:       6a 02                   push   $0x2              ; | arg 2 (via stack b/c not first arg and > 32 bits)
    12a5:       6a 01                   push   $0x1              ; arg 1
    12a7:       ff 75 f4                pushl  -0xc(%ebp)        ; |
    12aa:       ff 75 f0                pushl  -0x10(%ebp)       ; | arg 0 (struct by value, pushed onto stack)
    12ad:       ff 75 ec                pushl  -0x14(%ebp)       ; |
    12b0:       ff 75 e8                pushl  -0x18(%ebp)       ; |
    12b3:       89 c1                   mov    %eax,%ecx         ; ptr to free space for call's retval (struct), hidden first arg
    12b5:       e8 4b ff ff ff          call   1205 <leaf_call>  ; push return address and call
    12ba:       83 c4 04                add    $0x4,%esp         ; @@@ restore esp to what it was before pushing args
    12bd:       b8 00 00 00 00          mov    $0x0,%eax         ; return value
    12c2:       8b 4d fc                mov    -0x4(%ebp),%ecx   ; restore ecx
    12c5:       c9                      leave                    ; |
    12c6:       8d 61 fc                lea    -0x4(%ecx),%esp   ; | epilog
    12c9:       c3                      ret                      ; |



; ---------- small struct returned by value (shows it's never returned via regs) ---------->

; struct A { short x; short y; };
;
; struct A __attribute__((fastcall)) leaf_call(int a, int b)
; {
; 	struct A r = { 13, 15 };
; 	return r;
; }
;
; int main()
; {
; 	leaf_call(99, 2);
; 	return 0;
; }



; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0 (w/ flags to simplify: -fno-stack-protector -fno-pic)

00001205 <leaf_call>:
    1205:       55                      push   %ebp             ; |
    1206:       89 e5                   mov    %esp,%ebp        ; | prolog
    1208:       83 ec 18                sub    $0x18,%esp       ; |
    120b:       89 4d ec                mov    %ecx,-0x14(%ebp) ; ptr to retval space for struct (hidden first arg) -> local area
    120e:       89 55 e8                mov    %edx,-0x18(%ebp) ; in arg 0 -> local area
    1211:       66 c7 45 fc 0d 00       movw   $0xd,-0x4(%ebp)  ; |
    1217:       66 c7 45 fe 0f 00       movw   $0xf,-0x2(%ebp)  ; | struct values (local area)
    121d:       8b 45 ec                mov    -0x14(%ebp),%eax ; ptr to retval space for struct (fetched from local area) -> eax
    1220:       8b 55 fc                mov    -0x4(%ebp),%edx  ; |
    1223:       89 10                   mov    %edx,(%eax)      ; | copy struct in local area to retval space
    1225:       8b 45 ec                mov    -0x14(%ebp),%eax ; return value (passed-in hidden ptr)
    1228:       c9                      leave                   ; |
    1229:       c2 04 00                ret    $0x4             ; | epilog

0000122c <main>:
    122c:       55                      push   %ebp             ; |
    122d:       89 e5                   mov    %esp,%ebp        ; | prolog
    122f:       83 ec 04                sub    $0x4,%esp        ; |
    1232:       8d 45 fc                lea    -0x4(%ebp),%eax  ; ptr to space used for struct retval (passed as hidden first arg)
    1235:       6a 02                   push   $0x2             ; arg 1
    1237:       ba 63 00 00 00          mov    $0x63,%edx       ; arg 0 (via reg)
    123c:       89 c1                   mov    %eax,%ecx        ; ptr to free space for call's retval (struct), hidden first arg
    123e:       e8 c2 ff ff ff          call   1205 <leaf_call> ; push return address and call
    1243:       b8 00 00 00 00          mov    $0x0,%eax        ; return value
    1248:       c9                      leave                   ; |
    1249:       c3                      ret                     ; | epilog



; ---------- C++ trivial and non-trivial aggrs passed to C funcs ---------->
;
; struct Trivial { int a; };
; struct NonTrivial {
;         int a;
;         __attribute__((fastcall)) NonTrivial() : a(0) {}
;         __attribute__((fastcall)) NonTrivial(const NonTrivial& rhs) : a(rhs.a) { }
; };
;
; extern "C" {
;
;     void __attribute__((fastcall)) f1(struct Trivial s)    { }
;     void __attribute__((fastcall)) f2(struct NonTrivial s) { }
;
;     void __attribute__((fastcall)) f()
;     {
;         struct Trivial t;
;         struct NonTrivial n;
;         int a=1;
;         a += 123;
;         f1(t);
;         a -= 123;
;         f2(n);
;         a -= 12;
;     }
; }



; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0

00001215 <f1>:
    1215:       55                      push   %ebp
    1216:       89 e5                   mov    %esp,%ebp
    1218:       e8 f0 ff ff ff          call   120d <__x86.get_pc_thunk.ax>
    121d:       05 af 2d 00 00          add    $0x2daf,%eax
    1222:       90                      nop
    1223:       5d                      pop    %ebp
    1224:       c2 04 00                ret    $0x4

00001227 <f2>:
    1227:       55                      push   %ebp
    1228:       89 e5                   mov    %esp,%ebp
    122a:       83 ec 04                sub    $0x4,%esp
    122d:       e8 db ff ff ff          call   120d <__x86.get_pc_thunk.ax>
    1232:       05 9a 2d 00 00          add    $0x2d9a,%eax
    1237:       89 4d fc                mov    %ecx,-0x4(%ebp)
    123a:       90                      nop
    123b:       c9                      leave
    123c:       c3                      ret

0000123d <f>:
    123d:       55                      push   %ebp                          ;
    123e:       89 e5                   mov    %esp,%ebp                     ;
    1240:       83 ec 28                sub    $0x28,%esp                    ;
    1243:       e8 c5 ff ff ff          call   120d <__x86.get_pc_thunk.ax>  ;
    1248:       05 84 2d 00 00          add    $0x2d84,%eax                  ;
    124d:       65 a1 14 00 00 00       mov    %gs:0x14,%eax                 ;
    1253:       89 45 f4                mov    %eax,-0xc(%ebp)               ;
    1256:       31 c0                   xor    %eax,%eax                     ;
    1258:       8d 45 e8                lea    -0x18(%ebp),%eax              ;
    125b:       89 c1                   mov    %eax,%ecx                     ;
    125d:       e8 60 00 00 00          call   12c2 <_ZN10NonTrivialC1Ev>    ; NonTrivial::NonTrivial() / ctor
    1262:       c7 45 f0 01 00 00 00    movl   $0x1,-0x10(%ebp)              ;
    1269:       83 45 f0 7b             addl   $0x7b,-0x10(%ebp)             ;
    126d:       83 ec 0c                sub    $0xc,%esp                     ;
    1270:       ff 75 e4                pushl  -0x1c(%ebp)                   ;
    1273:       e8 9d ff ff ff          call   1215 <f1>                     ; call f1(struct Trivial)
    1278:       83 c4 0c                add    $0xc,%esp                     ;
    127b:       83 6d f0 7b             subl   $0x7b,-0x10(%ebp)             ;
    127f:       8d 55 e8                lea    -0x18(%ebp),%edx              ; |               ptr to n
    1282:       8d 45 ec                lea    -0x14(%ebp),%eax              ; |               |
    1285:       89 c1                   mov    %eax,%ecx                     ; | copy n        | ptr to dest of copy of n
    1287:       e8 56 00 00 00          call   12e2 <_ZN10NonTrivialC1ERKS_> ; /               NonTrivial::NonTrivial(const NonTrivial&) / copy ctor
    128c:       8d 45 ec                lea    -0x14(%ebp),%eax              ; \
    128f:       89 c1                   mov    %eax,%ecx                     ; | f2 arg 0 (ptr to copy of struct NonTrivial), via ptr as non-trivial
    1291:       e8 91 ff ff ff          call   1227 <f2>                     ; call f2(struct NonTrivial)
    1296:       83 6d f0 0c             subl   $0xc,-0x10(%ebp)              ;
    129a:       90                      nop                                  ;
    129b:       8b 45 f4                mov    -0xc(%ebp),%eax               ;
    129e:       65 33 05 14 00 00 00    xor    %gs:0x14,%eax                 ;
    12a5:       74 05                   je     12ac <f+0x6f>                 ;
    12a7:       e8 59 00 00 00          call   1305 <__stack_chk_fail_local> ;
    12ac:       c9                      leave                                ;
    12ad:       c3                      ret                                  ;

  ; ... snip, removed code of ctor and copy ctor ...



; ---------- C++ trivial and non-trivial aggrs as return values ---------->
;
; struct Trivial { int a; };
; struct NonTrivial {
;         int a;
;         __attribute__((fastcall)) NonTrivial() : a(0) {}
;         __attribute__((fastcall)) NonTrivial(const NonTrivial& rhs) : a(rhs.a) { }
; };
; 
; extern "C" {
;     struct Trivial    __attribute__((fastcall)) f1() { return Trivial(); }
; }
; 
;     struct NonTrivial __attribute__((fastcall)) f2() { return NonTrivial(); }
; 
; extern "C" {
;     void __attribute__((fastcall)) f()
;     {
;         int a=1;
;         a += 123;
;         struct Trivial t = f1();
;         a -= 123;
;         struct NonTrivial n = f2();
;         a -= 12;
;     }
; }



; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0

00001215 <f1>:
    1215:       55                      push   %ebp
    1216:       89 e5                   mov    %esp,%ebp
    1218:       83 ec 04                sub    $0x4,%esp
    121b:       e8 ed ff ff ff          call   120d <__x86.get_pc_thunk.ax>
    1220:       05 ac 2d 00 00          add    $0x2dac,%eax
    1225:       89 4d fc                mov    %ecx,-0x4(%ebp)
    1228:       8b 45 fc                mov    -0x4(%ebp),%eax
    122b:       c7 00 00 00 00 00       movl   $0x0,(%eax)
    1231:       8b 45 fc                mov    -0x4(%ebp),%eax
    1234:       c9                      leave
    1235:       c3                      ret

00001236 <_Z2f2v>:
    1236:       55                      push   %ebp
    1237:       89 e5                   mov    %esp,%ebp
    1239:       83 ec 18                sub    $0x18,%esp
    123c:       e8 cc ff ff ff          call   120d <__x86.get_pc_thunk.ax>
    1241:       05 8b 2d 00 00          add    $0x2d8b,%eax
    1246:       89 4d f4                mov    %ecx,-0xc(%ebp)
    1249:       8b 45 f4                mov    -0xc(%ebp),%eax
    124c:       89 c1                   mov    %eax,%ecx
    124e:       e8 6f 00 00 00          call   12c2 <_ZN10NonTrivialC1Ev>
    1253:       8b 45 f4                mov    -0xc(%ebp),%eax
    1256:       c9                      leave
    1257:       c3                      ret

00001258 <f>:
    1258:       55                      push   %ebp                          ;
    1259:       89 e5                   mov    %esp,%ebp                     ;
    125b:       83 ec 18                sub    $0x18,%esp                    ;
    125e:       e8 aa ff ff ff          call   120d <__x86.get_pc_thunk.ax>  ;
    1263:       05 69 2d 00 00          add    $0x2d69,%eax                  ;
    1268:       65 a1 14 00 00 00       mov    %gs:0x14,%eax                 ;
    126e:       89 45 f4                mov    %eax,-0xc(%ebp)               ;
    1271:       31 c0                   xor    %eax,%eax                     ;
    1273:       c7 45 f0 01 00 00 00    movl   $0x1,-0x10(%ebp)              ;
    127a:       83 45 f0 7b             addl   $0x7b,-0x10(%ebp)             ;
    127e:       8d 45 e8                lea    -0x18(%ebp),%eax              ; ptr space to hold aggregate retval -> eax ...
    1281:       89 c1                   mov    %eax,%ecx                     ; ... as hidden first arg (ecx)
    1283:       e8 8d ff ff ff          call   1215 <f1>                     ; call f1()
    1288:       83 6d f0 7b             subl   $0x7b,-0x10(%ebp)             ;
    128c:       8d 45 ec                lea    -0x14(%ebp),%eax              ; ptr space to hold aggregate retval -> eax ...
    128f:       89 c1                   mov    %eax,%ecx                     ; ... as hidden first arg (ecx)
    1291:       e8 a0 ff ff ff          call   1236 <_Z2f2v>                 ; call f2()
    1296:       83 6d f0 0c             subl   $0xc,-0x10(%ebp)              ;
    129a:       90                      nop                                  ;
    129b:       8b 45 f4                mov    -0xc(%ebp),%eax               ;
    129e:       65 33 05 14 00 00 00    xor    %gs:0x14,%eax                 ;
    12a5:       74 05                   je     12ac <f+0x54>                 ;
    12a7:       e8 35 00 00 00          call   12e1 <__stack_chk_fail_local> ;
    12ac:       c9                      leave                                ;
    12ad:       c3                      ret                                  ;



; vim: ft=asm