Hey everybody!

Ok, first off, I'm new to this forum.

Second off, I read hiroshimator's sticky and I hope that this post

doesn't go against his principles for this forum (i.e., don't be like

"help me do this")

Third, the "beef" of my post:

I had read somewhere awhile ago that there is a way to do

absolute value without a jump. This is what I coded up:

absolute value of eax:

mov edx,eax

shl edx,1 ;or add edx,edx, or mul edx,2 ... jk :)

sbb edx,edx

add eax,edx

xor eax,edx

Is this good/bad? does someone have something better?

as far as I can tell, if eax is positive, it really doesn't do anything

except nuke edx. If negative, it'll do not (dec x) which is abs, right?

Anyways, see you all later :)

--Chorus

Ok, first off, I'm new to this forum.

Second off, I read hiroshimator's sticky and I hope that this post

doesn't go against his principles for this forum (i.e., don't be like

"help me do this")

Third, the "beef" of my post:

I had read somewhere awhile ago that there is a way to do

absolute value without a jump. This is what I coded up:

absolute value of eax:

mov edx,eax

shl edx,1 ;or add edx,edx, or mul edx,2 ... jk :)

sbb edx,edx

add eax,edx

xor eax,edx

Is this good/bad? does someone have something better?

as far as I can tell, if eax is positive, it really doesn't do anything

except nuke edx. If negative, it'll do not (dec x) which is abs, right?

Anyways, see you all later :)

--Chorus

For those with 686 & above, you can use this:

Basically use the conditional move instruction after a neg of your target number. As neg sets the sign flag, you know whether or not to move it based on that flag!

---- Edit ----

A variation on your code should be as fast as my code above, and work on all processors (only downside being it is slightly bigger):

Mirno

```
```

.686

mov edx, eax

neg edx

cmovns eax, edx

Basically use the conditional move instruction after a neg of your target number. As neg sets the sign flag, you know whether or not to move it based on that flag!

---- Edit ----

A variation on your code should be as fast as my code above, and work on all processors (only downside being it is slightly bigger):

```
```

mov edx,eax

; shl edx,1

; sbb edx,edx

sar edx, 31

add eax,edx

xor eax,edx

Mirno

```
absolute MACRO regmem:REQ
```

rcl regmem, 1 ; top bit

sbb eax, eax ; all bits like top bit

rcr regmem, 1 ; put it back

;nop

add regmem, eax

;nop

xor regmem, eax

ENDM

Hey! I like both versions :)

Mirno, the 686 version is pretty elegant, but to be honest

I don't know enough about the cmovcc instructions to say

if it's faster or just shorter. Does the instruction pair well?

I'll look it up I guess. Thanks for the idea :)

BitRake, I like the universality of the macro. I coded mine

assuming it's in eax, but that's where my values usually are.

I think I'll change my code. However, I might have to one up

you. I just thought of this:

(I'm gonna assume it's in eax again)

mov edx,eax

sar edx,31

add eax,edx

xor eax,edx

it's one less instruction, and I'm sure sar is fully pairable still

the macro would just go like so

mov eax,regmem

sar eax,31

add regmem,eax

xor regmem,eax

but won't it be faster to mov a mem into a reg, do all this stuff

and mov it back? i.e.,

mov edx,mem

mov eax,edx

sar eax,31

add edx,eax

xor edx,eax

mov mem,edx

or is it not worth it?

Anyways, that's my 2 bits :)

Thanks again

--chorus

Mirno, the 686 version is pretty elegant, but to be honest

I don't know enough about the cmovcc instructions to say

if it's faster or just shorter. Does the instruction pair well?

I'll look it up I guess. Thanks for the idea :)

BitRake, I like the universality of the macro. I coded mine

assuming it's in eax, but that's where my values usually are.

I think I'll change my code. However, I might have to one up

you. I just thought of this:

(I'm gonna assume it's in eax again)

mov edx,eax

sar edx,31

add eax,edx

xor eax,edx

it's one less instruction, and I'm sure sar is fully pairable still

the macro would just go like so

mov eax,regmem

sar eax,31

add regmem,eax

xor regmem,eax

but won't it be faster to mov a mem into a reg, do all this stuff

and mov it back? i.e.,

mov edx,mem

mov eax,edx

sar eax,31

add edx,eax

xor edx,eax

mov mem,edx

or is it not worth it?

Anyways, that's my 2 bits :)

Thanks again

--chorus

cmp regmem, 80000000h

cmc ; fixed *Thanks*

sbb eax, eax

add regmem, eax

xor regmem, eax

:grin:

cmc ; fixed *Thanks*

**Mirno**sbb eax, eax

add regmem, eax

xor regmem, eax

:grin:

Chorus, pairing is "old hat" :grin:

The Pentium architecture used two execution pipes, but the P6 core (the PPro/P2/PIII), uses a different method. Basically it breaks instructions down into RISC like components, and can execute several of these in one clock cycle (not only that it can do them in a different order to those of the instructions if there are no dependencies). As all the instructions involved are on registers, and are basic or arithmetic operations there should really be no delay in their execution.

Your original: 5 micro-ops (the RISC like components of instructions)

My variation: 4 micro-ops

My 686 variation: 4 micro-ops

As for running the code on the PPlain, the "SAR" version will pair better, as the

subtracting 0 from any number will never set the carry flag (which is what sbb uses) :grin:

I think you need to subtract max_neg_int from it to set the carry flag (8000 0000h), and this will have the effect of setting the carry flag in the wrong case :( so you need an extra not, or complement the carry flag.

Mirno

The Pentium architecture used two execution pipes, but the P6 core (the PPro/P2/PIII), uses a different method. Basically it breaks instructions down into RISC like components, and can execute several of these in one clock cycle (not only that it can do them in a different order to those of the instructions if there are no dependencies). As all the instructions involved are on registers, and are basic or arithmetic operations there should really be no delay in their execution.

Your original: 5 micro-ops (the RISC like components of instructions)

My variation: 4 micro-ops

My 686 variation: 4 micro-ops

As for running the code on the PPlain, the "SAR" version will pair better, as the

**shl**and the**sbb**can both only execute on the u pipe.**bitRAKE**:subtracting 0 from any number will never set the carry flag (which is what sbb uses) :grin:

I think you need to subtract max_neg_int from it to set the carry flag (8000 0000h), and this will have the effect of setting the carry flag in the wrong case :( so you need an extra not, or complement the carry flag.

Mirno

**Mirno**, thanks for clearing that up - I don't have any documentation

here, and only enough time to give bad advise. :tongue:

Just out of curiosity... why would you want to do an abs() without a jump? ;)

Normally I would just do:

test eax, eax

jns @F

neg eax

Is there something inefficient about this method?

Normally I would just do:

test eax, eax

jns @F

neg eax

Is there something inefficient about this method?

**iblis**, branch miss-prediction is very costly on newer processors - forward branches aren't predicted on first time execution.

bitRAKE, your updated code will always give the negative value!

Add a neg at the end, or cmc between the comparision and the sbb.

Subtracting 80000000h from a number gives NOT(sign) in the carry flag!

Mirno

Add a neg at the end, or cmc between the comparision and the sbb.

Subtracting 80000000h from a number gives NOT(sign) in the carry flag!

Mirno

This is one solution:

cdq

add eax,edx

xor eax,edx

cdq

add eax,edx

xor eax,edx

This seems to simple to be true -- so please explain what a negative number looks like:

`and eax, 0x7FFFFFFF`

eet, your method would work if the left most bit were merely a sign bit, it isn't though.

I will use 8bit to cut down on typeing, but this is the basic way binary numbers are stored:

Hence -1 = 1111 1111 (binary)

Anding it with 07Fh (0111 1111) will result in a value of 127.

The correct method to convert from signed to unsigned (and vice versa) is not, then add 1, or subtract 1, then not.

And to do this without a jump, you need to sign extend, add it (sign extend 1 (negative) gives -1, sign extend 0 (positive) gives zero. Add the -1 or zero, then xor with -1 or 0, xor with 0F...Fh gives the effect of a not, xor with 0...0h does nothing.

All the methods above did the same thing, and only varied in the way they get the sign extended register to add & xor with.

Mirno

I will use 8bit to cut down on typeing, but this is the basic way binary numbers are stored:

```
```

bit: 7 6 5 4 3 2 1 0

value: -128, 64, 32, 16, 8, 4, 2, 1

Hence -1 = 1111 1111 (binary)

Anding it with 07Fh (0111 1111) will result in a value of 127.

The correct method to convert from signed to unsigned (and vice versa) is not, then add 1, or subtract 1, then not.

And to do this without a jump, you need to sign extend, add it (sign extend 1 (negative) gives -1, sign extend 0 (positive) gives zero. Add the -1 or zero, then xor with -1 or 0, xor with 0F...Fh gives the effect of a not, xor with 0...0h does nothing.

All the methods above did the same thing, and only varied in the way they get the sign extended register to add & xor with.

Mirno

This seems to simple to be true -- so please explain what a negative number looks like:

`and eax, 0x7FFFFFFF`

This will not work with integer values, but it does work with floating point values.

like:

```
```

mov eax, [myFloat]

and eax, 07FFFFFFFh

mov [myFloat], eax

It does not work with integers because

-1 = FFFFFFFFh thus the result will be 07FFFFFFFh and not 1