inline asm: move signed chars

Started by
10 comments, last by Kwak 17 years, 8 months ago
I tried to convert a little function to assembler: I keep having errors

char _fPlaceFallthrough[64];

MoveMessage putPion(char move)
{
    __asm
    {
        xor eax, eax                        //eax = 0
        movs al, move                       //al = move
        movs bl, 4                          //bl=4
        imul bl                             //ax = move*4           // now is   eax = move*4

        add eax, offset _fPlaceFallthrough  //eax = &_fPlaceFallthrough[move*4]
        movs bl,[eax]                       //bl = _fPlaceFallthrough[move*4]
        cmp bl,-3                           //if (getFallthrough(move*4)!=-3)
        jnz validMove                       //      goto validMove
        mov message, INVALID_MOVE
        jmp endAsm

    validMove:  
        dec [eax]                           // _fPlaceFallthrough[move*4]--;
        dec [eax +1]                        // _fPlaceFallthrough[move*4 + 1]--;
        dec [eax +2]                        // _fPlaceFallthrough[move*4 + 2]--;
        dec [eax +3]                        // _fPlaceFallthrough[move*4 + 3]--;
    }
    if (message==INVALID_MOVE)
        return INVALID_MOVE;
    else
        return VALID_MOVE;
}




should be the same as

MoveMessage putPion(char move)
{
    char place = move*4;
    if (getFallthrough(place)==-3)
        return INVALID_MOVE;

    _fPlaceFallthrough[place]--;
    _fPlaceFallthrough[place + 1]--;
    _fPlaceFallthrough[place + 2]--;
    _fPlaceFallthrough[place + 3]--;
        return VALID_MOVE;
}







I know the problem must be something with the sign of a char, but i don't know when a char is interpreted signed or unsigned. I think that after asm line 4 (imul bl //ax=move*4): ax is a signed 2 byte value. I guess i have to make it an unsigned 4 byte value? I've also read that to return a value you can do: asm mov eax, RETURN_VALUE asm ret Because eax is used for returning data. But how is the difference made between a pointer and a value? if a function gets a value, it must know what type it is. and I guess asm xor eax, eax asm movs al, INVALID_MOVE asm ret is wrong again (trying to load signed byte into unsigned 4-byte var [Edited by - Kwak on August 17, 2006 7:11:54 AM]
Advertisement
honestly, the function is so simple, unless you wanted to try to convert the last 4 lines to an sse instruction,
I doubt that your code is any faster than what the compiler generates. You should look at the output of the
compiler, and profile the code to be sure this is your bottleneck.
This is actually only a part of the function. I only posted this because i know there is going something wrong in that piece of code, and I don't want to dump all the code. (function is about 50 lines of code in c++)

And i know speed optimization must be done here. This function is called over a million times each time i decide where to put my pion.
I have a recursive function that keeps calling this code. Besides calling putPion() and comparing the returned value (INVALID_MOVE/WIN/LOSE/FORCE/DOUBLE_FORCE) it does nothing.

I have an idea how i could guess when it is not necessary to check that much possibilities, but i would probably be wrong 1% of the time. I want to keep this AI routine correct.

I made this code already 3! times faster by changing value getValue() functions into #define getValue() (value)

If the asm would make it another 5 times faster i would be happy :)
and after all its only 2 functions that must be converted (putPion() and undoPutPion() for a total of 60 lines

[Edited by - Kwak on August 16, 2006 5:44:20 PM]
Forgive my ignorance, but why are you using
movs bl, 4 //bl=4
and not
mov bl, 4?
MOVS: Move with Sign Extension; Intel 80x86; moves data from a register or memory to a register, with a sign extension (conversion to larger binary integer: byte to word, byte to doubleword, or word to doubleword); does not affect flags
When I look in my big-ol'-book-of-asm, I read out this:

movs		; Move [si] to es:[di]movsx bx, cl	; bx = sign extend cl


Isn't movs a string function (like "rep movs")?
I've checked my code. I've used mov instead of moves. moves generates an error: invalid combination of opcode and operands. I thougt i could use it to convert signed 1 byte integers (chars) to two byte integers (shorts)
Well written C(++) is worth more than any lame attempt at assembly that you can make. For example:
Quote:I made this code already 3! times faster by changing value getValue() functions into #define getValue() (value)
You could've gotten the same result by marking the method inline, or just asking the compiler to consider all functions for inlining.

In any case, making your crude assembly work won't make it any faster. It might even make it slower. Try to make algorithmic improvements, code level improvements, and compile setting tweaks.


In unrelated news, don't prefix your variable names with an underscore. Really bad idea. (Technically your identifiers are legal, as only __identifer and _Identifier are reserved, not _identifier, but it's still a bad idea. Use m_ or something instead.)
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Although the argument to the function is a char, it gets pushed as a dword in order to maintain stack alignment. Also note that on 32 bit systems, 32 bit registers are faster. So, you'll be better off using them rather than just the low byte parts of them.

xor eax, eax //eax = 0
mov eax, move //al = move
mov ebx, 4 //bl=4
imul ebx

There is likely an addressing mode that would simplify decrementing those array values, but I'd have to dig out my notes and think about it a bit to comment.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Quote:Original post by NisseBosseLasse
When I look in my big-ol'-book-of-asm, I read out this:

*** Source Snippet Removed ***

Isn't movs a string function (like "rep movs")?


Yes, if I recall correctly, MOVS moves DS:SI to ES:DI. It shouldn't take an operand, and uses the direction flag, and CX stores the length of the memory to copy. He's trying to move an immediate into a register, which is what MOV is for, not MOVS. (Unless for some reason he's not using the X86 instruction set, but that's what it appears to be).

*Edit*

As for the sign extention, mov doesn't care. That's what the Sign Flag is for, and you're not going be manipulating that.

Take the following binary

10101011

What does this equal should you put it in an unsigned char vs a char? And if you MOV that value to a register, you're not going to chop off the significant bit.

Even more edit:

Alright, I dug out my ASM books. IBM PC Assembly Language and Programming by Peter Abel

MOVSX: Move with Sign Extend (80386+)
Copies an 8 or 16 bit source operand into a larger 16 or 32 bit destination operand. MOVSX fills the sign bit into the leftmost bits.

This topic is closed to new replies.

Advertisement