what's the fastest way to sign extend from 24-bit to 32-bit?

what I can think of is like following:

mov eax,num24

mov ecx,eax

shl ecx,8 ;keep and move the sign bit

and eax,7FFFFFh ;keep the remaining bits

or eax,ecx

mov num32,eax

any better method?

what I can think of is like following:

mov eax,num24

mov ecx,eax

shl ecx,8 ;keep and move the sign bit

and eax,7FFFFFh ;keep the remaining bits

or eax,ecx

mov num32,eax

any better method?

24-bit "-1" is FFFFFF , while 32-bit "-1" is FFFFFFFF, so you can't just toggle the highest bit. And btw you'll lose that bit with a shl.

I guess this will work OK and as fast as possible:

I guess this will work OK and as fast as possible:

```
```

test eax,0800000h

jz @F

or eax,0FF000000h

@@:

jz is rarely optimal for speed : only well-predicted branches (Cf agner's doc)

shl ecx,31... buggy code, optimus, or else I did not understand u.

Take an example, please.

Here it is :

Say eax=03h

Output will be 03h

Say eax=0812345h

Output will be 0FF812345h

Correct ?

So I suggest :

mov ebx,0ff0000h

test eax,800000h

cmovz ebx,eax

or eax,ebx

Regards

shl ecx,31... buggy code, optimus, or else I did not understand u.

Take an example, please.

Here it is :

Say eax=03h

Output will be 03h

Say eax=0812345h

Output will be 0FF812345h

Correct ?

So I suggest :

mov ebx,0ff0000h

test eax,800000h

cmovz ebx,eax

or eax,ebx

Regards

May be this variant:

mov al,byte ptr num32+2

cbw

mov byte ptr num32+3,ah

mov al,byte ptr num32+2

cbw

mov byte ptr num32+3,ah

To sign extend a number in a register I'd do this (with some other instructions in between)

shl eax,8

sar eax,8

shl eax,8

sar eax,8

Sorry, it's a silly mistake.

I've modified it. See above.

shl ecx,31... buggy code, optimus, or else I did not understand u.

I've modified it. See above.

*Originally posted by valy*

shl ecx,31... buggy code, optimus, or else I did not understand u.

Your "corrected" code will still not yield proper results. Sephiroth3 provided the simplest solution to always get proper results (with or without some other instructions in between).

And, if you don't need to retain the 24-bit value in its memory variable, you can sign-extend it directly to its 32-bit value without using any register.

And, if you don't need to retain the 24-bit value in its memory variable, you can sign-extend it directly to its 32-bit value without using any register.

```
shl num24,8
```

sar num24,8

Raymondyes, i think his method is no doubt the fastest, and that's what i want.

actually, what i want is to do this job with C code. So I didn't use sar which cannot be done with C (with no in-line assembly)

Of course it can, just declare num24 as signed (which is the default)

Something like this? (num24 is unsigned, no meaning for it to be signed)

num32=((long)(num24<<8))>>8

num32=((long)(num24<<8))>>8

VC2003 + generated assembly. This function should of course be placed in a header so it can be inlined.

```
```

inline unsigned sign24to32(signed input)

{

return ((input << 8) >> 8);

}

/*

mov eax, DWORD PTR _input$[esp-4]

shl eax, 8

sar eax, 8

*/

In machines With sign shift most effective (in hence of instruction numbers) the way of Sephiroth3.

let x is bits in one size number (smaller in bits) y in another (bigger)

then (y-x) constant

code:

number_x shl (y-x) ;logical shift left

number_x sar (y-x) ;sign arithm. shifr right

like in Sephiroth3 code

shl eax,(32-24)

sar eax,(32-24)

If you don't like to use shl or sar then for 24-32 bits

yet want branchless code

extention you may use one of formulaes (in any machine)

((x+0080000h) and (00FFFFFFh)) - 800000h

((x and 00FFFFFFh) xor (0800000h)) - 800000h

instead of "+" you may you "xor" or "-"

The methods also can me more "math formal"

For example in 24 bits number sign bit is bit 23rd.

And the bit itself represent 2^23.

The for n-bits number it would be (n-1)th bit and would represent 2^(n-1)

Then for n-bits number 0800000h in above formulea we can replace by 2^(n-1) and 0FFFFFFh replaced by (2^n)-1

So for any n-bits number to be sign extended to current "machine word" we have

((x+2^(n-1)) and ((2^n)-1) - 2^(n-1)

((x xor 2^(n-1)) and ((2^n)-1) - 2^(n-1)

((x-2^(n-1)) and ((2^n)-1) - 2^(n-1)

((x and (2^n)-1)) xor (2^(n-1)) - 2^(n-1)

Both 2^(n-1) and (2^n)-1) - are some immeadiates:constants that calculated depending on "n"

let x is bits in one size number (smaller in bits) y in another (bigger)

then (y-x) constant

code:

number_x shl (y-x) ;logical shift left

number_x sar (y-x) ;sign arithm. shifr right

like in Sephiroth3 code

shl eax,(32-24)

sar eax,(32-24)

If you don't like to use shl or sar then for 24-32 bits

yet want branchless code

extention you may use one of formulaes (in any machine)

((x+0080000h) and (00FFFFFFh)) - 800000h

((x and 00FFFFFFh) xor (0800000h)) - 800000h

instead of "+" you may you "xor" or "-"

The methods also can me more "math formal"

For example in 24 bits number sign bit is bit 23rd.

And the bit itself represent 2^23.

The for n-bits number it would be (n-1)th bit and would represent 2^(n-1)

Then for n-bits number 0800000h in above formulea we can replace by 2^(n-1) and 0FFFFFFh replaced by (2^n)-1

So for any n-bits number to be sign extended to current "machine word" we have

((x+2^(n-1)) and ((2^n)-1) - 2^(n-1)

((x xor 2^(n-1)) and ((2^n)-1) - 2^(n-1)

((x-2^(n-1)) and ((2^n)-1) - 2^(n-1)

((x and (2^n)-1)) xor (2^(n-1)) - 2^(n-1)

Both 2^(n-1) and (2^n)-1) - are some immeadiates:constants that calculated depending on "n"

well, depending on how 24bits signed number is loaded in 32 bits register there might be even shorter way, if

upper 8 bits are unchanged (zeroes) in 24bits number image in 32 bits register and "and" instruction in formulea can be left out. Then it can be done by derivation of one of the above formula with 2 commands and without shifts (eax= image of 24bits number with zeroes in upper 8 bits):

The same if it in case on any n-bits number image in wider register

xor eax,2^(n-1)

sub eax,2^(n-1)

upper 8 bits are unchanged (zeroes) in 24bits number image in 32 bits register and "and" instruction in formulea can be left out. Then it can be done by derivation of one of the above formula with 2 commands and without shifts (eax= image of 24bits number with zeroes in upper 8 bits):

```
```

xor eax,800000h

sub eax,800000h

The same if it in case on any n-bits number image in wider register

xor eax,2^(n-1)

sub eax,2^(n-1)

very rewarding...