Thread: inline asm question

  1. #1
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972

    inline asm question

    Code:
    __asm
         (
             "CLD;"               
             "MOV EAX, color ;"
             "MOV ECX, (SCREEN_WIDTH/2);"  
             "MOV EDI, video_buffer;" 
             "REP STOSD;"
             );
    After much searching, I found that the only way to do inline assembly in dev-cpp is to do it like that, but there seems to be a problem with this code (which I didn't write, since I know almost nothing about assembly). The author of the book I reading says this code is equivalent to:
    Code:
    for (DWORD ecx = 0, DWORD * edi = video_buffer; ecx< (SCREEN_WIDTH/2); ecx++)
       edi[ecx] = color;
    But my compiler has problems with his assembly code:

    [quote]
    c:\windows\TEMP/cclnyggb.s: Assembler messages:
    c:\windows\TEMP/cclnyggb.s:647: Error: too many memory references for `mov'
    c:\windows\TEMP/cclnyggb.s:647: Error: too many memory references for `mov'
    c:\windows\TEMP/cclnyggb.s:647: Error: too many memory references for `mov'
    c:\windows\TEMP/cclnyggb.s:647: Error: no such instruction: `STOSD
    [/code]

    Can any assembly programmers tell me whats wrong?
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  2. #2
    l'Anziano DavidP's Avatar
    Join Date
    Aug 2001
    Location
    Plano, Texas, United States
    Posts
    2,743
    Difficult question this is....Get back to you, I will....

    P.S. It sounds like STOSD is a label. If it is in fact a label, you should probably put a label STOSD at the beginning of your inline asm code.
    My Website

    "Circular logic is good because it is."

  3. #3
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Looking at my post now, I should probably have inserted the authors comments, but I don't remember what they are...When I get home today I'll add them..maybe that will help.

    [edit]
    Ok now that I'm finally at home, here's the original code from the book:
    Code:
    _asm
            {
            CLD                                          ; clear direction of copy to forward
            MOV EAX, color                         ; color goes here
            MOV ECX, (SCREEN_WIDTH/2) ; number of DWORDS goes here
            MOV EDI, video_buffer             ; address of line to move data
            REP STOSD                               ; send the Pentium X on its way...
             }
    Well, anyhow if someone can help me out that would be great, but if I have to I'll just use the C++ "version" of the code...I suppose it might compile with MSVC++ but I haven't set it up for direct X as of yet

    [/edit]
    Last edited by JaWiB; 10-06-2003 at 06:11 PM.
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Code:
    asm {
      cld
      les    edi,[ScreenAddress]
      mov  eax,[Color]
      mov  ecx,[ScreenWidth]
      shr    ecx,1
      rep    stosd
    }
    Should work fine. Sounds like your compiler is not recognizing the assembly and is trying to compile it as C code instead of assembly. DJGPP did this to me once and it was quite annoying. Try using NASM with your compiler and writing your assembly there and then link it in with your C module.

  5. #5
    Registered User whistlenm1's Avatar
    Join Date
    Jan 2002
    Posts
    124
    if your using the bloodshed Dev-C++ compiler, use the following syntax (AT&T style):

    %register
    $constant value
    [memory] reference
    l, w, b: operand size specification

    operand? source, destination

    movb %al, %bl
    movw $0x0000, %cx
    movl [eax], ebx

    I hope this helps you!
    Last edited by whistlenm1; 10-09-2003 at 06:18 PM.
    Man's mind once streched by a new idea, never regains its original dimensions
    - Oliver Wendell Holmes

    In other words, if you teach your cat to bark (output) and eat dog food (input) that doesn't make him a dog. It would have to chase cars, chew bones, and have puppies before I'd call it Rover ;-)
    - WaltP

  6. #6
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    if your using the bloodshed Dev-C++ compiler, use the following syntax (AT&T style):
    I'm sure that would help me, but since I know practically no asm I fail to understand completely . I got this code from the book I'm reading...Actually I discovered a way to use intel syntax:

    Add the following commands when calling compiler
    -masm=intel

    Well anyways, I entered that a couple days ago and only realized today that I didn't check the box next to it I got rid of those errors I was getting, but now I get linker errors, "Undefined reference to..." with the names of my variables...

    I'm basically using bubba's code:
    Code:
     asm
             (
             "cld;"
             "les edi, [video_buffer];"
             "mov eax, [color];"
             "mov ecx, [SCREEN_WIDTH];"
             "shr ecx, 1;"
             "rep stosd;"
             );
    I'm guessing shr is binary shift right? (>>, or is it << i forget lol)
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  7. #7
    Geo Geo Geo-Fry
    Join Date
    Feb 2003
    Posts
    116
    the code should be as follows
    Code:
    __asm {
            cld
            mov eax, color
            mov ecx, SCREEN_WIDTH/2
            mov edi, video_buffer
            rep stosd
    }
    "You can lead a man to Congress, but you can't make him think."
    "The Grand Old Duke of York
    -He had ten thousand men.
    -His case comes up next week."
    "Roses are red, violets are blue, I'm schizophrenic, and so am I."
    "A computer once beat me at chess, but it was no match for me at kick boxing."
    "More and more of our imports are coming from overseas."
    --George W. Bush
    "If it weren't for electricity, we'd all be wacthing TV by candlelight."
    --George W. Bush

  8. #8
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Code:
    the code should be as follows
    Wth you talking about? Did you not pay attention! I'm using dev-c++ and it wont accept that!
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    ...Well anyways, I entered that a couple days ago and only realized today that I didn't check the box next to it I got rid of those errors I was getting, but now I get linker errors, "Undefined reference to..." with the names of my variables...

    Sounds like your inline assembler does not allow references to file-scope variables. MS and Borland's inline assemblers allow references to any C variables/structures, etc. in inline assembler statements. Some, however, may not allow you to do this.

    So you might have to declare some temporary variables within the function so that it will work.

    Code:
    typedef unsigned char BYTE;
    
    BYTE far *Screen;
    unsigned int ScreenWidth;
    
    void SomeFunc(BYTE color)
    {
      //Cannot refer to global vars in asm
      BYTE *tempScreen=Screen;
      unsigned tempScreenWidth=ScreenWidth;
      asm {
        push   edi
        les      edi,[tempScreen]
        mov    ecx,[tempScreenWidth]
        shr     ecx,1
        mov    eax,[color]             ;this will be bp+6 in protected mode
        rep     stosd
        pop    edi
       }
       //tempScreen and tempScreenWidth are popped off of the stack
    }

    On a side note
    The statement mov eax,color will NOT work correctly. Since you are outputting bytes to the screen you must have the color value in each of the 4 bytes of the one DWORD. For instance if the color is 4 each byte should look like this.

    04 04 04 04

    or

    00000100 00000100 00000100 00000100


    mov eax,color looks like this

    00 00 00 04

    or

    00000000 00000000 00000000 00000100


    So you will have 3 black pixels followed by 1 red in mode 13h. Will produce red vertical lines spaced 4 pixels apart from one another. Not what you want.

  10. #10
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    None of that seems to apply since:

    A. All my variables, with the exception of SCREEN_WIDTH are declared within the function

    B. Color is defined as follows:
    Code:
     DWORD color = _RGB16BIT565(0,(index_y >> 3),0);
    With _RGB16BIT565:

    Code:
    #define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))

    Edit:

    Heres the full part of the function:
    Code:
    for (int index_y=0; index_y < SCREEN_HEIGHT; index_y++)
         {
         // build color word up
         DWORD color = _RGB16BIT565(0,(index_y >> 3),0);
         // replicate color in upper and lower 16 bits of 32-bit word 
         color = (color) | (color << 16);
    
         // now color has two pixel in it in 16.16 or RGB.RGB format, use a DWORD
         // or 32-bit copy to move the bytes into the next video line, we'll need
         // inline assembly though...
    
         // draw next line, use a little inline asm baby!
         asm
             (
             "push edi;"
             "les edi, [video_buffer];"
             "mov eax, [color];"
             "mov ecx, [SCREEN_WIDTH];"
             "shr ecx, 1;"
             "rep stosd;"
             "pop edi;"
             );
    
             
         // now advance video_buffer to next line
         video_buffer += (ddsd.lPitch >> 1);
         
         }
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Well that code from the book worked on my system. Perhaps a new compiler is in order.

  12. #12
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    I guess i should set up dx9 for msvc++ 6...It appears most people who know anything about inline asm don't use dev-c++...go figure
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  13. #13
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    You have to do a few extra things when using gas (gnu assembler) to generate inline code.

    You need to declare your variables as static using the "__asm__" keyword so that the assembler 'knows' about them.

    Consider the following simple example:
    Code:
    /*at&t inline assembly for mingw (gas)*/
    #include <windows.h>
    int main()
    {
    static char *pTxt __asm__( "pTxt" ) = "Hello World";
    static char *pTitle __asm__( "pTitle" ) = "Using inline assembly with gas (MinGW)";
    
    __asm__ 
      (
      "pushl	$0;"
      "pushl	pTitle;"
      "pushl	pTxt;"
      "pushl	$0;"
      "call _MessageBoxA@16;"
      );
    return 0;
    }
    Hope that helps.

    ps. - sorry for the AT&T syntax, Bubba.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  14. #14
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Well that got it to compile...now it just opens for a sec then closes again...I'm fairly confident its not any of the functions failing and causing the program to end, since I added a message box after each test (which should also play a sound MB_ICONEXCLAMATION) So I'm stumped


    I guess as a last resort I'll post the entire code...Although I don't expect anyone to read it...its a bit messy and I just copied and pasted a bunch of message boxes so the text within them wont correspond with the function
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  15. #15
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Hey Ken Fitlike - get your AT&T code out of here..

    I thought you were consigned to the fiery pit because of that. How'd you get out.



Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I need help to compile this code...
    By wise_ron in forum C Programming
    Replies: 17
    Last Post: 05-07-2006, 12:22 PM
  2. inline asm trouble
    By Jez in forum C Programming
    Replies: 2
    Last Post: 02-27-2005, 06:07 PM
  3. Seg fault with inline ASM
    By Thantos in forum C Programming
    Replies: 12
    Last Post: 04-28-2004, 11:43 PM
  4. Inline ASM ???????
    By datainjector in forum C Programming
    Replies: 5
    Last Post: 09-03-2002, 12:43 PM