#### neilobremski

##### Experienced Member

Code:

`abs(x) = (x XOR y) - y`

Where y = 0xFFFF if x is negative and y = 0x0000 if x is positive. The problem here is obviously

*how to get y*. I mean this still sounds like branching is required in 16-bit. But then I disassembled the MSVC 5.1 code for abs() with /Ox and it revealed the following for ABS(AX):

Code:

```
CWD
XOR AX, DX
SUB AX, DX
```

Voila! By the way, what I did (for future reference to myself) to DEBUG this was to raise interrupt 3 (breakpoint) directly from within the C code and then trace from there ...

Code:

```
#include <dos.h>
#include <math.h>
int main(void) {
union REGS regs;
int x = 0xDEAD, y = 0xBEEF;
int86(3, ®s, ®s);
x = abs(y);
return 0;
};
```

Somehow I was under the impression that CWD wasn't even supported until the 286 ... whoops.

Using CBW and CWD can also be used to get the sign of a number as -1 or 1 (with zero counting as positive). The following tests the sign of the byte AL and puts a -1 or 1 into AH:

Code:

```
CBW
OR AH, 01
```

It's too bad I couldn't somehow use OR AL, 01 because that machine code instruction is only two bytes instead of three. If AL is to contain the result then an extra MOV AL, AH is needed.

To count zero as its own thing (so results could be -1, 0, or 1) then I don't see a clear way to do it besides adding a JZ branch. Maybe someone could enlighten me? Yes! See this thread: 16-bit X86 Trick to Multiply by a Number's Sign?

Footnotes:

[SUP][1][/SUP]. https://stackoverflow.com/questions/2639173/x86-assembly-abs-implementation