News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Confusion over Bitwise NOT

Started by Crashish, March 26, 2007, 05:01:59 AM

Previous topic - Next topic

Crashish

I'm reading chapter 3.2.4 of pcasm-book.pdf. The NOT operation.

Quote
The NOT operation is a unary operation(i.e. it acts on one operand,
not two like binary operations such as AND).The NOT of a bit is the
opposite value of the bit as the truth table in Table 3.4 shows.
....
Note that the NOT finds the one's complement

I'm just messing around with the bitwise NOT looking at the output in the console, but the results are not what I expected.

For instance:

not 10     ; not 10 = 5
           ; 1010
           ; 0101 = 5


Now I'll list the actual code I compiled and show the output. I'll also comment on what I thought the result would be.


start:
  mov eax, 10
  not eax

  print str$(eax)     ; Thought the output would be 5
                      ; 1010
                      ; 0101 = 5


Output:

  -11




start:
  mov al, 1
  not al

  print str$(eax)     ; Thought it would be 14
                      ;  0001
                      ;  1110 = 14


Output:

254



What am I doing wrong here?





MichaelW

The instruction affects all of the bits in the operand, not just the lower 4. Also, when you are working with AL and displaying the result as the value in EAX, you need to ensure that the upper 24 bits of EAX are zeroed.

eschew obfuscation

hutch--

Here is a small test piece so you can experiment with various instructions. This one uses the NOT mnemonic.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    LOCAL pbuf  :DWORD
    LOCAL buffer[64]:BYTE

    mov pbuf, ptr$(buffer)

    mov eax, 12345678           ; decimal number input
    not eax                     ; operate on it

    invoke dw2bin_ex,eax,pbuf   ; convert it to ascii binary notation

    print pbuf,13,10            ; display result to console

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start


Result is,


11111111010000111001111010110001
Press any key to continue ...
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Crashish

[EDIT]

Thanks for the reply Michael. This output makes sense to me now (254)  based on what you said. I can't say that for the other
thing though.

start:
  xor eax, eax

  mov al, 1
  not al

  print str$(eax)     ; Thought it would be 14
                      ;  0001
                      ;  1110 = 14

Output:

254


Quote
One's complement

The second method is known as one's complement representation.The
one's complement of a number is found by reversing each bit in the number.
(Another way to look at it is that the new bit value is 1 - old_bit_value.) For
example, the one's complement of 00111000 (+56) is 11000111. In one's com-
plement notation, computing the one's complement is equivalent to nega-
tion
.Thus, 11000111 is the representation for -56. Note that the sign bit
was automatically changed by one's complement and that as one would ex-
pect taking the one's complement twice yields the original number. As for
the first method, there are two representations of zero:
00000000(+0) and 1111111( 0).Arithmetic with one's complement numbers is
complicated.

According to the above, "computing the one's complement is equivalent to negation."
"Thus, 11000111 is the representation for -56"

Lets compile this and look at the output.

start:
    xor eax, eax
   
    mov eax, 56
    not eax
               
    print str$(eax)   ;// From what I've read above, I'm thinking the result will be -56 (negative fifty-six)
    exit


Output:

-57


Why is it not -56?

Keeping these two things in mind:
Quote
Note that the NOT finds the one's complement.
Computing the one's complement is equivalent to negation.

Why is the output -57 and not -56 if computing the one's complement is equivalent to negation! *bangs head on wall*

Crashish

Thanks hutch-- I'll mess with this and keep reading till I understand it better.

MichaelW

The x86 processors use a two's complement representation for negative numbers, so the conversion procedures expect a two's complement value instead of one's complement. With two's complement, to convert a number from positive to negative, or from negative to positive, you invert all bits and add one, and ignore any carry out of the most significant bit. Going through the steps starting with 56:

00111000 ; 56
11000111 ; not 56, result is -57 in two's complement
00000001 ; add 1
11001000 ; -56 in two's complement (-57+1 = -56)

You can verify that 11001000 represents -56 by adding 56 to it:
11001000 ; -56
00111000 ; add 56
00000000 ; result is zero, carry ignored

In case you are not familiar with the rules for binary addition:
0+0 = 0
0+1 = 1
1+0 = 1
1+1 = 0 carry 1
eschew obfuscation

Crashish

Thanks Micheal for walking me through that.
Quote from: MichaelWThe x86 processors use a two's complement representation for negative numbers, so the conversion procedures expect a two's complement value instead of one's complement.
I must have read about two's complement 10 times and still forgot about that.  :red
Remembering that might have saved some frustration huh?

Thanks again for your explanation.



gabor

Hi!

I got very curious where did you read that about one's complement? I must admit that though I studied computer science I've never heard about the one's complement having 2 representations for zero (all bits cleard or set). Well, there are several number representations with different arithmetics. For x86 (but as I can remember for Commodore machines too) the arithmetic is exactly how MichaelW very well described.
Just a last thing that was not mentioned and could make the story whole:
The sum of a number and its one's complement give an odd  number, for 8 bit numbers the sum will be 11111111b, generally for n bit numbers 2^n-1. (0101 + 1010 = 1111 <-> 5 + 10 = 15)
It is quite simple to conclude that the sum of a number and its 2-complement give an even number, for n bits 2^n. (0101 + 1011 = 1|0000 <-> 5 + 11 = 16).

Greets, Gábor