Re: Linux / NASM equivalent of Iczelion's Win32 assembly tut's

Discussion in 'C Programming' started by Herbert Kleebauer, Mar 5, 2008.

  1. Frank Kotler wrote:


    > I observed that you code "looks like" it calls the OS for every
    > character. It does not.


    Now GCC disappoints me. Just compiled the two line C program:

    #include <stdio.h>
    main() {putchar(10);}

    GCC gives me:

    main:
    leal 4(%esp), %ecx
    andl $-16, %esp
    pushl -4(%ecx)
    pushl %ebp
    movl %esp, %ebp
    pushl %ecx
    subl $20, %esp
    movl stdout, %eax
    movl $10, (%esp)
    movl %eax, 4(%esp)
    call _IO_putc
    addl $20, %esp
    popl %ecx
    popl %ebp
    leal -4(%ecx), %esp
    ret
    .size main, .-main
    .ident "GCC: (GNU) 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)"
    .section .note.GNU-stack,"",@progbits

    This means, for each putchar() in the source, _IO_putc is called.


    The Microsoft C compiler defines the macro putchar() in stdio.h

    #define putchar(_c) putc((_c),stdout)
    #define putc(_c,_stream) (--(_stream)->_cnt >= 0 \
    ? 0xff & (*(_stream)->_ptr++ = (char)(_c)) : _flsbuf((_c),(_stream)))

    And therefore the compiled code looks like:

    ; 3 : main() {putchar(10);}

    00000 a1 24 00 00 00 mov eax, DWORD PTR __iob+36
    00005 48 dec eax
    00006 a3 24 00 00 00 mov DWORD PTR __iob+36, eax
    0000b 78 14 js SHORT $L201
    0000d a1 20 00 00 00 mov eax, DWORD PTR __iob+32
    00012 c6 00 0a mov BYTE PTR [eax], 10 ; 0000000aH
    00015 a1 20 00 00 00 mov eax, DWORD PTR __iob+32
    0001a 40 inc eax
    0001b a3 20 00 00 00 mov DWORD PTR __iob+32, eax
    00020 c3 ret 0
    $L201:
    00021 68 20 00 00 00 push OFFSET FLAT:__iob+32
    00026 6a 0a push 10 ; 0000000aH
    00028 e8 00 00 00 00 call __flsbuf
    0002d 83 c4 08 add esp, 8
    00030 c3 ret 0
    _main ENDP

    It only calls an external subroutine when the buffer is full.
    Herbert Kleebauer, Mar 5, 2008
    #1
    1. Advertising

  2. Herbert Kleebauer

    Tim Prince Guest

    Herbert Kleebauer wrote:
    > Frank Kotler wrote:
    >
    >
    >> I observed that you code "looks like" it calls the OS for every
    >> character. It does not.

    >
    > Now GCC disappoints me. Just compiled the two line C program:
    >
    > #include <stdio.h>
    > main() {putchar(10);}
    >
    > GCC gives me:
    >
    > main:
    > leal 4(%esp), %ecx
    > andl $-16, %esp
    > pushl -4(%ecx)
    > pushl %ebp
    > movl %esp, %ebp
    > pushl %ecx
    > subl $20, %esp
    > movl stdout, %eax
    > movl $10, (%esp)
    > movl %eax, 4(%esp)
    > call _IO_putc
    > addl $20, %esp
    > popl %ecx
    > popl %ebp
    > leal -4(%ecx), %esp
    > ret
    > .size main, .-main
    > .ident "GCC: (GNU) 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)"
    > .section .note.GNU-stack,"",@progbits
    >
    > This means, for each putchar() in the source, _IO_putc is called.


    You want gcc to over-ride the headers provided by Ubuntu (and make
    similar provisions for each target), even if you don't invoke whatever
    options are present in your particular header?
    Tim Prince, Mar 5, 2008
    #2
    1. Advertising

  3. In article <>,
    Herbert Kleebauer <> wrote:

    >This means, for each putchar() in the source, _IO_putc is called.


    I think this is for thread-safety (so multiple threads can use the
    same stream simultaneously, though that seems like a Really Bad Idea).
    There may be some way to override it.

    -- Richard
    --
    :wq
    Richard Tobin, Mar 5, 2008
    #3
  4. Herbert Kleebauer

    Chris Torek Guest

    In article <>
    Herbert Kleebauer <> wrote:
    >Now GCC disappoints me. Just compiled the two line C program:
    >
    >#include <stdio.h>
    >main() {putchar(10);}


    [assembly snipped]

    >This means, for each putchar() in the source, _IO_putc is called.


    It is possible that any putchar() calls _IO_putc(), but the above
    does not show this (even if you put back the assembly that I
    snipped). The reason is that 10 happens to be equal to value of
    '\n' on this system, and putchar('\n') must push the output to the
    system if the stream in question is line-buffered. Since stdout
    is very often line-buffered, one should expect putchar('\n') to
    make an O/S call very often as well, and an implementation-specific
    function like _IO_putc() is a good place to hide the test for
    whether the call is needed, along with the call itself.

    On the other hand, putchar('x'), for instance, could be done without
    making a function call (since 'x' is clearly not a newline).
    Similarly, a source-code construct like putchar(c), where c is a
    variable rather than a known-constant newline, might expand to code
    that tests whether c=='\n', then buffers c or calls _IO_putc(c) as
    appropriate. (As someone suggested in another follow-up, one might
    need to turn off thread support to see this, too.)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: gmail (figure it out) http://web.torek.net/torek/index.html
    Chris Torek, Mar 6, 2008
    #4
  5. In article <>,
    Chris Torek <> wrote:

    >It is possible that any putchar() calls _IO_putc(),


    .... and it seems to be true on the Linux systems I have access to. It
    appears to be for thread-safety, but making writes to the same file
    "thread-safe" is not very useful: it guarantees that you won't, for
    example, get a segmentation fault, but the characters may come out in
    any order. To make the pointless case safe at the expensive of making
    the common case slow seems like a mistake to me.

    >Since stdout
    >is very often line-buffered, one should expect putchar('\n') to
    >make an O/S call very often as well, and an implementation-specific
    >function like _IO_putc() is a good place to hide the test for
    >whether the call is needed, along with the call itself.


    That was my initial guess as to the explanation too, but it turns out
    to be wrong.

    -- Richard
    --
    :wq
    Richard Tobin, Mar 6, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Prasanna Padmanabhan
    Replies:
    1
    Views:
    802
    Mattias Sjögren
    Nov 19, 2003
  2. Marcin Balcerzak

    C to NASM - lnkflat problem

    Marcin Balcerzak, Jun 2, 2005, in forum: C Programming
    Replies:
    3
    Views:
    901
    Keith Thompson
    Jun 3, 2005
  3. globalrev
    Replies:
    3
    Views:
    1,095
  4. John Forse

    getting tut. example to work

    John Forse, Feb 24, 2009, in forum: Python
    Replies:
    1
    Views:
    250
    alex23
    Feb 24, 2009
  5. oyster
    Replies:
    3
    Views:
    237
    Stefaan Himpe
    May 23, 2009
Loading...

Share This Page