ASM on Mac OS X

Discussion in 'Mac Programming' started by Cromulent, Mar 17, 2008.

  1. macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #1
    I'm having a real problem getting to stage one of ASM on Mac OS X. Tutorials and online books either assume you are using MASM or use Linux specific calls. I do not know enough (well any at all really) to be able to see what I am doing wrong. I managed to get one piece of code to assemble and link correctly but the code does nothing (I think it is because it uses int 0x080 which is a Linux kernel call), how did you guys go about learning ASM?

    I'd preferably like to just read through a book and use the code as is just to give myself a grounding but that seems unlikely now that I look closer at ASM and the fragmentation of the language into different assemblers and operating systems. I guess that is the price to be paid for low level programming though.
     
  2. thread starter macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #2
  3. macrumors 65816

    Joined:
    Jul 28, 2004
    #3
    Although there is nothing wrong with learning assembler on OS X, it is even more of a challenge. Linux or DOS/Windows would be the best platform to learn x86 assembler with a book. After that, you just learn the OS specific differences.

    One helper on OS X is to use the Show Assembly menu in Xcode that lets you see how a piece of C code looks after translation to assembly.
     
  4. macrumors 65816

    Muncher

    Joined:
    Apr 19, 2007
    Location:
    California
    #4
    Very true. I would actually recommend windows starting out, because there is so much material for that OS on asm. Alternately, and interesting solution would be to get an old computer with a floppy or emulate it in Q, and load MenuetOS on to it. MenuetOS is a graphical operating system that runs on assembly. I read about it a while ago, and it looked pretty cool.
     
  5. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #5
    I would first read up on the x86 and PowerPC instruction sets (check out http://www.intel.com/products/processor/manuals/ for the x86 manuals). No point in trying to write assembler code if you don't know the processor instruction set.

    Next thing I would write some very, very simple C functions in XCode, switch the compiler to IA32 only, and then "Show Assembly Code" in the "Build" menu. That will show you an assembler file equivalent to the source code, so you can learn the syntax and programming from there.

    Next thing you can include .s files in your projects, with your own code. Or you use the gcc extensions to add asm code directly to a C or C++ or Objective-C function, but that is a major pain.
     
  6. macrumors 6502

    Joined:
    Jun 16, 2004
    #6
    Also, take what the compiler gives you "with a grain of salt". Generated assembler is usually horrible compared to hand written.

    For example here is GCCs version of PPC strlen:
    Code:
    stmw    r30,0xfff8(r1)
    stwu    r1,0xffc0(r1)
    or      r30,r1,r1
    stw     r3,0x58(r30)
    lwz     r0,0x58(r30)
    stw     r0,0x18(r30)
    b       0x2ac4
    0x2ab8:
    lwz     r2,0x18(r30)
    addi    r0,r2,0x1
    stw     r0,0x18(r30)
    0x2ac4:
    lwz     r2,0x18(r30)
    lbz     r0,0x0(r2)
    extsb   r0,r0
    cmpwi   cr7,r0,0x0
    bne     cr7,0x2ab8
    lwz     r2,0x18(r30)
    lwz     r0,0x58(r30)
    subf    r0,r0,r2
    or      r3,r0,r0
    lwz     r1,0x0(r1)
    lmw     r30,0xfff8(r1)
    blr
    Which can easily be reduced to:
    Code:
    or r2, r3, r3
    b compare
    loop:
    addi r2, r2, 0x1
    compare:
    lbz r0, 0x0(r2)
    cmpwi cr7, r0, 0x0
    bne cr7, loop
    subf r3, r3, r2
    blr
    Update: Mini-rant - this is why Intel, IBM, (and previously Metrowerks) were able to sell their products - GCC produces bad code. Here is an example of the same code (from same C file) by Metrowerks:
    Code:
    mr r2, r3
    b *+8
    addi r2, r2, 1
    lbz r0, 0(r2)
    extsb. r0, r0
    bne *-12
    subf r3, r3, r2
    blr
     
  7. thread starter macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #7
    The problem with that is that even with a very simple program (Hello World) it spits out tons of rubbish. Most of which I imagine is completely irrelevant to the program (I assume most of it is setting up etc).

    For instance Hello World spits out the following for me:
    Code:
        .section __DWARF,__debug_frame,regular,debug
    Lsection__debug_frame:
        .section __DWARF,__debug_info,regular,debug
    Lsection__debug_info:
        .section __DWARF,__debug_abbrev,regular,debug
    Lsection__debug_abbrev:
        .section __DWARF,__debug_aranges,regular,debug
    Lsection__debug_aranges:
        .section __DWARF,__debug_macinfo,regular,debug
    Lsection__debug_macinfo:
        .section __DWARF,__debug_line,regular,debug
    Lsection__debug_line:
        .section __DWARF,__debug_loc,regular,debug
    Lsection__debug_loc:
        .section __DWARF,__debug_pubnames,regular,debug
    Lsection__debug_pubnames:
        .section __DWARF,__debug_pubtypes,regular,debug
    Lsection__debug_pubtypes:
        .section __DWARF,__debug_str,regular,debug
    Lsection__debug_str:
        .section __DWARF,__debug_ranges,regular,debug
    Lsection__debug_ranges:
        .section __DWARF,__debug_abbrev,regular,debug
    Ldebug_abbrev0:
        .section __DWARF,__debug_info,regular,debug
    Ldebug_info0:
        .section __DWARF,__debug_line,regular,debug
    Ldebug_line0:
        .text
    Ltext0:
        .cstring
    LC0:
        .ascii "Hello, World!\0"
        .text
    .globl _main
        .private_extern _main
    _main:
    LFB3:
    LM1:
    LVL0:
        pushl    %ebp
    LCFI0:
        movl    %esp, %ebp
    LCFI1:
        subl    $24, %esp
    LCFI2:
    LM2:
        movl    $LC0, (%esp)
        call    L_puts$stub
    LM3:
        xorl    %eax, %eax
        leave
        ret
    LFE3:
        .section __DWARF,__debug_frame,regular,debug
    Lframe0:
        .set L$set$0,LECIE0-LSCIE0
        .long L$set$0
    LSCIE0:
        .long    0xffffffff
        .byte    0x1
        .ascii "\0"
        .byte    0x1
        .byte    0x7c
        .byte    0x8
        .byte    0xc
        .byte    0x4
        .byte    0x4
        .byte    0x88
        .byte    0x1
        .align 2
    LECIE0:
    LSFDE0:
        .set L$set$1,LEFDE0-LASFDE0
        .long L$set$1
    LASFDE0:
        .set L$set$2,Lframe0-Lsection__debug_frame
        .long L$set$2
        .long    LFB3
        .set L$set$3,LFE3-LFB3
        .long L$set$3
        .byte    0x4
        .set L$set$4,LCFI0-LFB3
        .long L$set$4
        .byte    0xe
        .byte    0x8
        .byte    0x85
        .byte    0x2
        .byte    0x4
        .set L$set$5,LCFI1-LCFI0
        .long L$set$5
        .byte    0xd
        .byte    0x5
        .align 2
    LEFDE0:
        .text
    Letext0:
        .section __DWARF,__debug_info,regular,debug
        .long    0x1b9
        .word    0x2
        .set L$set$6,Ldebug_abbrev0-Lsection__debug_abbrev
        .long L$set$6
        .byte    0x4
        .byte    0x1
        .ascii "GNU C 4.0.1 (Apple Inc. build 5470) (Aspen 5470.3)\0"
        .byte    0x1
        .ascii "/Users/simon/Documents/Development/Assembly/Hello World/main.c\0"
        .long    Ltext0
        .long    Letext0
        .set L$set$7,Ldebug_line0-Lsection__debug_line
        .long L$set$7
        .byte    0x2
        .byte    0x1
        .byte    0x6
        .ascii "signed char\0"
        .byte    0x2
        .byte    0x1
        .byte    0x8
        .ascii "unsigned char\0"
        .byte    0x2
        .byte    0x2
        .byte    0x5
        .ascii "short int\0"
        .byte    0x2
        .byte    0x2
        .byte    0x7
        .ascii "short unsigned int\0"
        .byte    0x2
        .byte    0x4
        .byte    0x5
        .ascii "int\0"
        .byte    0x2
        .byte    0x4
        .byte    0x7
        .ascii "unsigned int\0"
        .byte    0x2
        .byte    0x8
        .byte    0x5
        .ascii "long long int\0"
        .byte    0x2
        .byte    0x8
        .byte    0x7
        .ascii "long long unsigned int\0"
        .byte    0x2
        .byte    0x4
        .byte    0x5
        .ascii "long int\0"
        .byte    0x3
        .byte    0x4
        .byte    0x7
        .byte    0x2
        .byte    0x1
        .byte    0x6
        .ascii "char\0"
        .byte    0x2
        .byte    0x4
        .byte    0x7
        .ascii "long unsigned int\0"
        .byte    0x4
        .byte    0x4
        .long    0x142
        .byte    0x5
        .long    0x11f
        .byte    0x6
        .byte    0x1
        .ascii "main\0"
        .byte    0x1
        .byte    0x3
        .byte    0x1
        .long    0xce
        .long    LFB3
        .long    LFE3
        .byte    0x1
        .byte    0x55
        .long    0x182
        .byte    0x7
        .ascii "argc\0"
        .byte    0x1
        .byte    0x3
        .long    0xce
        .byte    0x2
        .byte    0x75
        .byte    0x8
        .byte    0x7
        .ascii "argv\0"
        .byte    0x1
        .byte    0x3
        .long    0x182
        .byte    0x2
        .byte    0x75
        .byte    0xc
        .byte    0x0
        .byte    0x4
        .byte    0x4
        .long    0x13c
        .byte    0x8
        .long    0xce
        .long    0x193
        .byte    0x9
        .byte    0x0
        .byte    0xa
        .ascii "__CFConstantStringClassReference\0"
        .long    0x188
        .byte    0x1
        .byte    0x1
        .byte    0x1
        .byte    0x0
        .section __DWARF,__debug_abbrev,regular,debug
        .byte    0x1
        .byte    0x11
        .byte    0x1
        .byte    0x25
        .byte    0x8
        .byte    0x13
        .byte    0xb
        .byte    0x3
        .byte    0x8
        .byte    0x11
        .byte    0x1
        .byte    0x12
        .byte    0x1
        .byte    0x10
        .byte    0x6
        .byte    0x0
        .byte    0x0
        .byte    0x2
        .byte    0x24
        .byte    0x0
        .byte    0xb
        .byte    0xb
        .byte    0x3e
        .byte    0xb
        .byte    0x3
        .byte    0x8
        .byte    0x0
        .byte    0x0
        .byte    0x3
        .byte    0x24
        .byte    0x0
        .byte    0xb
        .byte    0xb
        .byte    0x3e
        .byte    0xb
        .byte    0x0
        .byte    0x0
        .byte    0x4
        .byte    0xf
        .byte    0x0
        .byte    0xb
        .byte    0xb
        .byte    0x49
        .byte    0x13
        .byte    0x0
        .byte    0x0
        .byte    0x5
        .byte    0x26
        .byte    0x0
        .byte    0x49
        .byte    0x13
        .byte    0x0
        .byte    0x0
        .byte    0x6
        .byte    0x2e
        .byte    0x1
        .byte    0x3f
        .byte    0xc
        .byte    0x3
        .byte    0x8
        .byte    0x3a
        .byte    0xb
        .byte    0x3b
        .byte    0xb
        .byte    0x27
        .byte    0xc
        .byte    0x49
        .byte    0x13
        .byte    0x11
        .byte    0x1
        .byte    0x12
        .byte    0x1
        .byte    0x40
        .byte    0xa
        .byte    0x1
        .byte    0x13
        .byte    0x0
        .byte    0x0
        .byte    0x7
        .byte    0x5
        .byte    0x0
        .byte    0x3
        .byte    0x8
        .byte    0x3a
        .byte    0xb
        .byte    0x3b
        .byte    0xb
        .byte    0x49
        .byte    0x13
        .byte    0x2
        .byte    0xa
        .byte    0x0
        .byte    0x0
        .byte    0x8
        .byte    0x1
        .byte    0x1
        .byte    0x49
        .byte    0x13
        .byte    0x1
        .byte    0x13
        .byte    0x0
        .byte    0x0
        .byte    0x9
        .byte    0x21
        .byte    0x0
        .byte    0x0
        .byte    0x0
        .byte    0xa
        .byte    0x34
        .byte    0x0
        .byte    0x3
        .byte    0x8
        .byte    0x49
        .byte    0x13
        .byte    0x3f
        .byte    0xc
        .byte    0x34
        .byte    0xc
        .byte    0x3c
        .byte    0xc
        .byte    0x0
        .byte    0x0
        .byte    0x0
        .section __DWARF,__debug_pubnames,regular,debug
        .long    0x17
        .word    0x2
        .set L$set$8,Ldebug_info0-Lsection__debug_info
        .long L$set$8
        .long    0x1bd
        .long    0x147
        .ascii "main\0"
        .long    0x0
        .section __DWARF,__debug_pubtypes,regular,debug
        .long    0xe
        .word    0x2
        .set L$set$9,Ldebug_info0-Lsection__debug_info
        .long L$set$9
        .long    0x1bd
        .long    0x0
        .section __DWARF,__debug_aranges,regular,debug
        .long    0x1c
        .word    0x2
        .set L$set$10,Ldebug_info0-Lsection__debug_info
        .long L$set$10
        .byte    0x4
        .byte    0x0
        .word    0x0
        .word    0x0
        .long    Ltext0
        .set L$set$11,Letext0-Ltext0
        .long L$set$11
        .long    0x0
        .long    0x0
        .section __DWARF,__debug_line,regular,debug
        .set L$set$12,LELT0-LSLT0
        .long L$set$12
    LSLT0:
        .word    0x2
        .set L$set$13,LELTP0-LASLTP0
        .long L$set$13
    LASLTP0:
        .byte    0x1
        .byte    0x1
        .byte    0xf6
        .byte    0xf5
        .byte    0xa
        .byte    0x0
        .byte    0x1
        .byte    0x1
        .byte    0x1
        .byte    0x1
        .byte    0x0
        .byte    0x0
        .byte    0x0
        .byte    0x1
        .ascii "/Users/simon/Documents/Development/Assembly/Hello World"
        .byte    0
        .byte    0x0
        .ascii "main.c\0"
        .byte    0x1
        .byte    0x0
        .byte    0x0
        .byte    0x0
    LELTP0:
        .byte    0x0
        .byte    0x5
        .byte    0x2
        .long    LM1
        .byte    0x16
        .byte    0x0
        .byte    0x5
        .byte    0x2
        .long    LM2
        .byte    0x15
        .byte    0x0
        .byte    0x5
        .byte    0x2
        .long    LM3
        .byte    0x16
        .byte    0x0
        .byte    0x5
        .byte    0x2
        .long    Letext0
        .byte    0x0
        .byte    0x1
        .byte    0x1
    LELT0:
        .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
    L_puts$stub:
        .indirect_symbol _puts
        hlt ; hlt ; hlt ; hlt ; hlt
        .subsections_via_symbols
    
    I assume that this is the main part of the program and the rest is just C bloat?
    Code:
    .globl _main
        .private_extern _main
    _main:
    LFB3:
    LM1:
    LVL0:
        pushl    %ebp
    LCFI0:
        movl    %esp, %ebp
    LCFI1:
        subl    $24, %esp
    LCFI2:
    LM2:
        movl    $LC0, (%esp)
        call    L_puts$stub
    LM3:
        xorl    %eax, %eax
        leave
        ret
    If I had a simple template to work with on an Intel Mac running Mac OS X Leopard it would help immensely. If anyone could just type the equivalent of an empty main() function in assembly I would be extremely grateful.
     
  8. macrumors 6502

    Joined:
    Jun 16, 2004
    #8
    You need the data section too (the part above the blob of code you gave that has .ascii "Hello, World!\0" in it)
     
  9. thread starter macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #9
    The bit with the LC0 label?

    I've been looking through the Intel developer manuals and they seem pretty comprehensive. I guess them combined with the NASM users guide, the Mac OS X assembly reference and a general X86 assembly book I should be able to work it out I guess.

    I'll probably have more questions later though :).

    Thanks for the help.
     
  10. macrumors 6502

    Joined:
    Jun 16, 2004
    #10
    Yes, the part with LC0 (which is referenced in the code blob by "movl $LC0, (%esp)").

    Keep in mind that GCC/GAS will produce AT&T style assembler, however NASM, MASM, TASM, etc use Intel style assembler.
     
  11. thread starter macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #11
    Right. Thanks for that, I think I have enough information now to get on with it over the Easter weekend.
     
  12. macrumors member

    Joined:
    Jan 25, 2007
    #12
    Just out of curiosity (as someone that has used x86 assembly on/off for over a decade) what do you hope to accomplish with assembly on Mac OSX?

    As with the others here, if you are attempting to learn x86 assembly, you will certainly have a far easier time using the extremely mature (and far better documented) assemblers found more prevalently on the Microsoft platforms (MASM in particular, but FASM or NASM might be good alternatives), and the general wealth of knowledge/examples for writing usable code that is available. On the other hand, you need to ensure you maintain a clear understanding of what is/is not available depending on what platform you are currently using...

    I would also highly suggest staying as far away from compiler generated assembly as humanly possible (especially if you are letting the compiler do any level of optimization). What you will end up with the majority of the time will look very non-sensical, will likely be attempting to take advantages of non-standard features (or even bugs in certain processor families), and that does not follow a normal "logical" flow.

    In the end however, assembly has really fallen out of favor so to speak, and outside of completely "stand-alone" code, or for optimizing specific sections of code that require absolute maximum speed (assuming you have the knowledge to even optimize it further then the compiler), it really doesn't provide much "benefit" persay.
     
  13. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #13
    The vast majority of what Xcode spit out is debug information. The default build includes all of that, so when you click a breakpoint in the IDE, etc. all of the debug info is there to achieve that for you.

    I would take a different tact if you want to get compiler-generated ASM.

    Take your hello world source:
    Code:
    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
      printf("Hello World!\n");
      return 0;
    }
    Then run this from the command line:
    gcc -S helloworld.c

    A file helloworld.s will be generated, mine looked like this:
    Code:
            .cstring
    LC0:
            .ascii "Hello World!\0"
            .text
    .globl _main
    _main:
            pushl   %ebp
            movl    %esp, %ebp
            pushl   %ebx
            subl    $20, %esp
            call    ___i686.get_pc_thunk.bx
    "L00000000001$pb":
            leal    LC0-"L00000000001$pb"(%ebx), %eax
            movl    %eax, (%esp)
            call    L_puts$stub
            movl    $0, %eax
            addl    $20, %esp
            popl    %ebx
            popl    %ebp
            ret
            .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
    L_puts$stub:
            .indirect_symbol _puts
            hlt ; hlt ; hlt ; hlt ; hlt
            .subsections_via_symbols
            .section __TEXT,__textcoal_nt,coalesced,pure_instructions
    .weak_definition        ___i686.get_pc_thunk.bx
    .private_extern ___i686.get_pc_thunk.bx
    ___i686.get_pc_thunk.bx:
            movl    (%esp), %ebx
            ret
    
    Perhaps not the MOST concise possible, but looks a lot nicer than the debug ridden output Xcode gave you (you may be able to turn this off and get nicer looking ASM, but I am not too familiar with all of the Xcode options).

    For comparison, here's gcc's output, adding -g to the above to add debug symbols:
    Code:
            .stabs  "/Users/lee/",100,0,2,Ltext0
            .stabs  "helloworld.c",100,0,2,Ltext0
            .text
    Ltext0:
            .stabs  "",102,0,0,0
            .stabs  "gcc2_compiled.",60,0,0,0
            .stabs  ":t(0,1)=(0,1)",128,0,0,0
            .cstring
    LC0:
            .ascii "Hello World!\0"
            .text
    .globl _main
    _main:
            .stabd  46,0,0
            .stabd  68,0,3
            pushl   %ebp
            movl    %esp, %ebp
            pushl   %ebx
            subl    $20, %esp
            call    ___i686.get_pc_thunk.bx
    "L00000000001$pb":
            .stabd  68,0,4
            leal    LC0-"L00000000001$pb"(%ebx), %eax
            movl    %eax, (%esp)
            call    L_puts$stub
            .stabd  68,0,5
            movl    $0, %eax
            .stabd  68,0,6
            addl    $20, %esp
            popl    %ebx
            popl    %ebp
            ret
            .stabs  "main:F(0,2)",36,0,3,_main
            .stabs  "argc:p(0,2)",160,0,3,8
            .stabs  "argv:p(0,3)",160,0,3,12
            .stabs  "int:t(0,2)=r(0,2);-2147483648;2147483647;",128,0,0,0
            .stabs  ":t(0,3)=*(0,4)",128,0,0,0
            .stabs  ":t(0,4)=*(0,5)",128,0,0,0
            .stabs  "char:t(0,5)=r(0,5);0;127;",128,0,0,0
    Lscope0:
            .stabs  "",36,0,0,Lscope0-_main
            .stabd  78,0,0
            .stabs  "",100,0,0,Letext0
    Letext0:
            .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
    L_puts$stub:
            .indirect_symbol _puts
            hlt ; hlt ; hlt ; hlt ; hlt
            .subsections_via_symbols
            .section __TEXT,__textcoal_nt,coalesced,pure_instructions
    .weak_definition        ___i686.get_pc_thunk.bx
    .private_extern ___i686.get_pc_thunk.bx
    ___i686.get_pc_thunk.bx:
            movl    (%esp), %ebx
            ret
    Good luck, hope this was helpful.

    -Lee
     
  14. macrumors 65816

    Joined:
    Jul 28, 2004
    #14
    True, but:

    Since CPU speeds have hit the wall, cases of single-thread performance bottleneck are everywhere, and they are only going away if the programmer sits down and does it. Becoming expert at assembly and algorithm performance (both single and parallel algorithms) is the one way to maximize the single-thread speed. SSE or custom instructions/cores is another approach. And if you are lucky enough to be dealing with a parallelizable problem, threading is there.

    No matter which way you go, software is being forced to take up the weight that rising CPU speeds can no longer pull.
     
  15. thread starter macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #15
    Because it is the best way to achieve my main interest in computing, which is operating systems, compilers and simulators. All three make use of assembly in one way or another. I'll have to learn it at some point, may as well start now.

    Yes, I was thinking that myself. The only problem is my iTunes library is stored on my OS X partition and I find it an essential aid while programming :).

    I've decided to try using NASM and then reading the Intel developer manuals linked earlier in this thread. Hopefully it won't be that hard.

    Personally I think this is a real shame. Although compilers are very good at producing optimised code, knowledge of assembly seems to give a huge advantage even when just doing C coding as it gives you a greater understanding of what is going on behind the scenes. At least that is what I am lead to believe and it seems like it is true from the little that I have looked into the subject.

    Thank you. That was some useful information.

    This is one of the primary reasons I'm interested in low level programming. High level languages promote bloated programs that waste computer resources and I am still not convinced by the arguments that say computers are fast enough for it not to matter.
     
  16. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #16
    Here is the code that gcc produced for me (I removed some debug information, and I used the C++ compiler, that shouldn't make a difference):

    Code:
    size_t my_strlen (char *p) {
    	char* q = p;
    	while (*q) ++q;
    	return (size_t) (q - p);
    }
    
    __Z9my_strlenPc:
    	pushl	%ebp
    	movl	%esp, %ebp
    	movl	8(%ebp), %edx
    	movl	%edx, %eax
    	jmp	L113
    
    L114:
    	incl	%eax
    L113:
    	cmpb	$0, (%eax)
    	jne	L114
    	leave
    	subl	%edx, %eax
    	ret
    
    
    __Z9my_strlenPc:
    	mr r2,r3
    	b L122
    L123:
    	addi r3,r3,1
    L122:
    	lbz r0,0(r3)
    	cmpwi cr7,r0,0
    	bne cr7,L123
    	subf r3,r2,r3
    	blr
    
     
  17. macrumors 65816

    Flynnstone

    Joined:
    Feb 25, 2003
    Location:
    Cold beer land
    #17
    I agree with Domain.

    Very little of an OS is written in assembler.
    Don't do assembly unless you have to.
    Programmers are notoriously wrong at optimizing code.

    You need to profile the code to find out where the "hotspots are".
    Once you know where the bottle neck code is, you work on the algorithm.
    Then you get it down to a small chunk of code that needs to be optimized, you then look to see if assembler will be any help.

    Assembler is very processor specific. Obviously assembler for x86 is not going to work on a PowerPC. But since you're going for speed, you also need to know what processor (x86) you're running. A specific set of instructions for one x86 may not be optimized for another x86 (Pentium vs Core vs ...).
    Optimized assembler is VERY CPU specific.
    You generally need to be very good at assembler to beat the compiler.

    Always profile before and after to see if you made an improvement.

    Did I say "Don't do assembler unless you have to" ?

    GCC isn't a great optimizing compiler. Its a great general compiler.
    Optimizing for x86, its probably wise to get the Intel compiler. But you must profile to compare.
     
  18. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #18
    I've done quite a bit of programming with code efficiency being the most important concern. Here is my experience:

    1. In bigger projects, trying to write efficient code is not what gives you the big gains. Finding bits of code that are completely brain damaged insanely stupid and wasting time, and replacing them with something that is not completely stupid, that gives you big gains (sad but true).

    2. Good C code is faster than bad assembler code. And there is some really bad assembler code around.

    3. When you are developing algorithms that need to be fast, the important thing is to start with something that works, then study its behaviour, get a mental grasp of the problem, find out what makes the algorithm take time, get ideas to make it faster and implement them. It is not uncommon to get a factor 100 in speed from the first, not really inefficient approach to the final result, going through many rounds of iterative improvement. That approach doesn't work with assembler, you get too soon stuck in the tiny details and lose the bigger picture.
     
  19. macrumors 65816

    Muncher

    Joined:
    Apr 19, 2007
    Location:
    California
    #19
    NASM - good choice. I think you can integrate it with xcode, but I'm not entirely sure since Gas uses AT&T syntax.

    I started out with Dark Basic about 5~6 years ago, making simple games and demos. I couldn't figure out why a program I made that struggled under Dark Basic would run 5x as fast when someone else made it. I then moved on to C, and found out why. Since then I've programmed for the PIC micro-controllers in ASM/C, and I really learned a lot from that. Maybe if you're interested in ASM, you should try micro-controllers. You can do a lot of cool things with them, and they may be slow, but the PIC instruction set is a whooping 35 instructions.

    No matter how you cut it though, I personally would never to write an entire program in assembly for OS X. Maybe linux, but just looking at the Mach-o file format gives me a headache.
     
  20. macrumors member

    Joined:
    Jan 25, 2007
    #20
    Learning assembly from a standpoint of an interest in computing is certainly admirable... I have always believed that it should be on the first languages taught from a programming perspective, not because of it's practical application, but it gives you great insight into what is actually going on at the lowest levels, and at the same time trains to you think differently when it comes to writing code in higher level languages.

    As for your iTunes dilemma, a very useful solution to said problem is to use a product like VMWare, which will let you work in a somewhat "clean" environment, while at the same time providing a safe place for a language that has the capabilities of doing actual destructive things (you'd be amazed how a simple typo in assembly can have some really *interesting* results :p)

    So to learn for learning sake is a good thing (TM), on the other hand assembly's place in todays computing is very very limited. As per your Operating System example, very little assembly comes into play beyond the boot-loader stage (initial load, a20 initialization, protected mode, setting up IVT, etc.), unless you look at some very specific designs (there are more then a few all-assembly Operating Systems out there, Menuet comes to mind).

    Also as some of the other posters have mentioned, the largest speed gains generally come from better algorithms, rather then hand optimized assembly. The general process is to find "problem areas", identify the algorithms involved, adjust/replace as necessary, and only then if it is still not fast enough move to assembly. That said (and I don't really care which you are using), compilers are very bad at optimizing... there are many many instances where the generated code has room for improvement, however if that segment of code isn't frequently called, then there is very little reason to do so.

    At any rate, if you decide to use the Microsoft platforms as a learning base, I suggest you Google a few resources... Win32asm and Masm32 (as a baseline), The Art of Assembly (the assembly bible but use the old DOS edition!), and articles by Agner Fog (a number of great articles/papers that will show you how painful but powerful optimization can be). Thats all I can think of at the moment... just keep in mind this information was largely relevant for Intel x86 many years ago... the concepts for newer chips will remain the same, but the methods can be quite different (look up Itanium assembly sometime :p)
     
  21. thread starter macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #21
    Considering this thread is now pretty high in Google page rank when searching for information about assembler for Mac OS X I thought I would link some useful information I have found.

    1) To call the kernel in Mac OS X use the same code as for FreeBSD (0x80).

    2) Mac OS X ABI Function Call Guide.

    http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/Introduction.html

    3) http://www.x86-64.org/

    All the information you need about 64bit programming.

    4) Use the version of NASM that Apple ship with Xcode.

    I'll update this post as I find more information.
     
  22. macrumors newbie

    Joined:
    Feb 27, 2008
    #22
    I have to disagree with those who have posted that asm has very limited use in the modern age. To give you some background, I am an embedded software engineer. My background ranges from set top boxes to raid controllers to traffic lights. In pretty much all the code I have seen, and at every office where I have worked, some proportion has been asm.

    From an OS perspective, yes asm may have limited use. However, in the embedded world it is very much still used and will continue to be!! The only problem is that less and less people know it, so anyone going out of their way to learn asm in this day and age should be congratulated and stick it prominently on their CV. They will be snapped up at lightning speed!

    Cromulent, I wish you well with your voyage of asm discovery!

    Mr StevieP
     
  23. thread starter macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #23
    Thank you all for the advice and encouragement. I've found it most useful.

    Now for the stupid noob questions :).

    Code:
    SECTION .data
    msg: db 'Hello World',10
    	
    len: equ $-msg ; get the length of the string
    
    SECTION .text
    	global start
    
    start:
    	
    	mov edx, len ; length of the string
    	mov ecx, msg ; the string
    	mov ebx, 1 ; write() 
    	mov eax, 4 ; stdout
    	int 0x80 ; kernel call
    	
    	mov ebx, 0 ; start exit procedure
    	mov eax, 1
    	int 0x80
    It assembles and links fine using the following commands:

    but does not work. Basically it runs but does not print anything at all. I'm fairly certain the code is correct as a number of tutorials use the same code for the Hello World program. Am I doing something completely stupid?
     
  24. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #24
    Give this a try:
    Code:
    SECTION .data
    msg db 'Hello World',0xa ;String to print
    len: equ $-msg ; get the length of the string
    
    SECTION .text
            global _start
    
    
    _start:
            enter 0,0 ; Entry
            pusha
            push dword len ; Push length onto the stack
            push dword msg ; Push address of msg onto the stack
            push dword 0x1 ; We want to write to file 1, stdout
            mov eax, 0x4 ; We want to call system function 4
            push dword eax ; This is for stack alignment
            int 0x80 ; Make the system call
            add esp,16 ; Realign the stack
            push dword 0; start exit procedure
            mov eax, 0x1; Set system exit call
            int 0x80 ; Make the system call
    
    The code example you found is for a different call style. It will work on linux, or BSD if you do:
    brandelf -f Linux <filename>

    I tried it on OS X and it wasn't in my path, so I tried the "unix style" calling, using the stack for arguments based on a different example.

    It took me a while to get it going, but this seems to be working for me.

    -Lee
     
  25. macrumors member

    Joined:
    Jan 25, 2007
    #25

Share This Page