Thread: ASM w/ C++ issues

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    67

    ASM w/ C++ issues

    Alright so I decided to start dabbling in x86 ASM a bit because I'm new to the field (being 15).

    My code was simply as follows:

    Code:
    void outputstuff()
    {
         WORD i = 0;
    
         __asm{pop i}
         printf("%u",i);
    }
    int main(int nArgs,char*sArgs[])
    {
         WORD i = 0;
         
         __asm
         {
              jmp looping
              looping:
                   cmp i,256
                   je breaker
                   push i
                   call outputstuff
                   add i,1
                   jmp looping
              breaker:
         }
    }
    but it doesn't run properly (but compiles fine)
    I also tried putting WORD i as an argument:

    Code:
    void outputstuff(WORD i)
    ...
    
    push i
    call outputstuff
    ....
    but that didn't work either. Any idea?

    Also, the conditional jump gave me some trouble. It works fine now, but I want to say if i is greater than or equal to 256, quit, but jge just quit right away and jle quit at 129. what's with that?

    Thanks

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You probably don't want to "pop" something inside a function, because there are other things pushed onto the stack between the call and the assembler in your function (almost always ebp, and possibly other registers).


    Why not make "outputstuff" take an unsigned int argument (as that is what you are actually doing), and add 4 to esp after the call to outputstuff. Obviously, your first "jmp looping" is a waste of space - the next line is the label looping anyways.


    As to your conditional jump, if you want an unsigned compare, use JAE.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You can't really get portable with assembly, so I'll throw in another unportable concept.
    If you use Visual Studio, you can use __declspec(naked) to have the compiler strip the initialization code (and the "epilogue" code) from a function. That should allow you to pop whatever you just pushed on the stack.
    But this is much more of a hack than real programming.
    The real way would just be to add "WORD i" to the argument list and NOT pop the stack (but push the argument to the stack before calling).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Judging by what the code is doing, he is probably trying to learn assembler....

  5. #5
    Registered User
    Join Date
    Sep 2007
    Posts
    67
    I'm in the process of learning assembly. And yeah I know it's not very good code, I was just trying to get it to work. thanks for your help, I've combined it with other answers

  6. #6
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    This is why people never bet against me. I am good at pointing out the obvious.

  7. #7
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    I tried compiling this (for fun) and "WORD" is undefined. I'm on a Mac. Is there an include I need for inline asm?
    Mainframe assembler programmer by trade. C coder when I can.

  8. #8
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Just typedef unsigned short as WORD, though it is not necessarily the best platform independant definition of "WORD." You should not need any specific includes to compile this code other than maybe windows.h... Which you obviously do not have.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    It appears that printf gets upset if the stack is not aligned properly to 4 bytes, so I found this to work:
    Code:
    #include <stdio.h>
    
    typedef unsigned short WORD;
    
    void outputstuff(unsigned int i)
    {
         printf("%u ",i);
         fflush(stdout);
    }
    
    int main(int nArgs,char*sArgs[])
    {
         WORD i = 0;
         
         __asm
         {
              looping:
    	       movzx ecx, word ptr i
                   cmp ecx,256
                   jae breaker
                   push ecx
                   call outputstuff
    	       add esp,4
                   add word ptr i,1
                   jmp looping
              breaker:
         }
    	 return 0;
    }
    I added the fflush to make sure I would see the output immediately, rather than at the very end of the program.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It appears that printf gets upset if the stack is not aligned properly to 4 bytes, so I found this to work:
    And many things will be upset on x86-64 architectures if you don't align the stack to 16 bytes.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by CornedBee View Post
    And many things will be upset on x86-64 architectures if you don't align the stack to 16 bytes.
    Ehm, but that responsibility lies in the callee, not the caller. The caller can pass a single argument (8 bytes) and not adjust the stack, but the called function needs to pad to the next lower 16 bytes after saving its registers.

    In this case, the called function assumes that the stack is aligned to 4 bytes, and strange things happens [I have not figured out what goes wrong, just that it DOES].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Mats, if you don't mind...
    I don't know what the instructions movzx and jae does. Can you explain their function?
    Also you do "add word ptr i,1", as per the the OP, but hey, why not just stuff it into a register and use inc?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Chinese pâté foxman's Avatar
    Join Date
    Jul 2007
    Location
    Canada
    Posts
    404
    MOVZX stands for something like move with zero extend. JAE is for jump above or equal.

    Also, INC can work with a memory operand. You can
    Code:
    inc word ptr i
    if you really want.

    http://developer.intel.com/products/...uals/index.htm
    I hate real numbers.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    Mats, if you don't mind...
    I don't know what the instructions movzx and jae does. Can you explain their function?
    Also you do "add word ptr i,1", as per the the OP, but hey, why not just stuff it into a register and use inc?
    movzx - Move with Zero Extension: It loads the 16-bit value into a 32-bit register, and fills the remaining 16 bits with zero. It's counterpart for signed numbers is movsx, which fills the upper 16 bits with the content of bit 15 of the low 16 bits.

    jae - Jump Above or Equal. It's the same as JGE but for unsigned numbers.

    And I can't continue to use ECX after the call, since it's one of the registers that can be used in the callee without preservation, so it would require another load before inc can be used on it. Of course, I could have picked another register...

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    Quote Originally Posted by matsp View Post
    It appears that printf gets upset if the stack is not aligned properly to 4 bytes, so I found this to work:
    Code:
    #include <stdio.h>
    
    typedef unsigned short WORD;
    
    void outputstuff(unsigned int i)
    {
         printf("%u ",i);
         fflush(stdout);
    }
    
    int main(int nArgs,char*sArgs[])
    {
         WORD i = 0;
         
         __asm
         {
              looping:
    	       movzx ecx, word ptr i
                   cmp ecx,256
                   jae breaker
                   push ecx
                   call outputstuff
    	       add esp,4
                   add word ptr i,1
                   jmp looping
              breaker:
         }
    	 return 0;
    }
    I added the fflush to make sure I would see the output immediately, rather than at the very end of the program.

    --
    Mats
    I get the following error when running the above:
    Code:
    [Session started at 2008-09-19 17:16:13 -0500.]
    
    c_asm_misc has exited due to signal 4 (SIGILL).
    Intel Dual Core Xeon Mac.
    Mainframe assembler programmer by trade. C coder when I can.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. gcc asm code syntax
    By Uberapa in forum C Programming
    Replies: 4
    Last Post: 06-15-2007, 01:16 AM
  2. Understanding ASM
    By kuphryn in forum A Brief History of Cprogramming.com
    Replies: 26
    Last Post: 07-12-2002, 07:39 PM
  3. Inline asm
    By wavering in forum C Programming
    Replies: 2
    Last Post: 01-29-2002, 02:42 AM
  4. asm mov
    By manu in forum C++ Programming
    Replies: 1
    Last Post: 12-15-2001, 12:59 PM
  5. My graphics library
    By stupid_mutt in forum C Programming
    Replies: 3
    Last Post: 11-26-2001, 06:05 PM