You are on page 1of 9

Chapter 2: Numbers

2.1 Binary Numbers


2.2 Hexadecimal Numbers
2.3 Integers
2.3.1 Binary Addition
2.3.2 Binary Multiplication
2.4 Floating Point Numbers
2.4.1 Converting Decimal Numbers To Floats
2.4.2 Converting Floats To Decimal
2.4.3 Floating Point Addition
2.4.4 Floating Point Multiplication

Chapter 3: Computer Memory


3.1 Memory Mapping
3.2 Process Memory Model In Linux
3.3 Memory Example
3.4 Examining Memory With gdb
3.4.1 Printing With gdb
3.4.2 Examining Memory

Chapter 4: Memory Mapping In 64 bit mode


4.1 The Memory Mapping Register
4.2 Page Map Level 4
4.3 Page Directory Pointer Table
4.4 Page Directory Table
4.5 Page Table
4.6 Large Pages
4.7 CPU Support For Fast Lookups

In Detail

All information in computers are stored as bits. Bits can be interpreted in a


number of ways.

2.1 Binary Numbers

The bits of 8 bit binary numbers are numbered 0 to 7, with 0 being the least
significant digit, and 7 being the most significant.

The indices are labeled 0,1,2 etc above the binary digits, right to left. Then each
digit denotes the value digit * 2^index

10101111 binary = 1 * 2^7 + 1*2^5 + 1 + 1*2^3 + 1* 2^2 + 1 * 2^1 + 1*2^0 =


128 + 32 + 8 + 4 + 2 + 1 = 175

Converting integer to binary

741
= 512 + 229
= 512 + 128 + 101
= 512 + 128 + 64 + 37
= 512 + 128 + 64 + 32 + 5
= 512 + 128 + 64 + 32 + 4 + 1

= 2^9 + 2^7 + 2^6 +2^5 + 2*2 + 2^0


(just put 1s in index positions in the above string, zeros in others)
= 1011100101

(step)
A binary constant can be represented in the yasm assembler by appending b to a
string of 0s and 1s.

An alternative method is to keep dividing by 2. the reminder gives the binary digit

so
number /2 reminder binary number so far
741 370 1 1
370 185 0 01
185 92 1 101
92 46 0 0101
46 23 0 00101
23 11 1 100101
11 5 1 1100101
5 2 1 11100101
2 1 0 011100101
1 0 1 1011100101 = 741

The second method ==> you don't have to guess the closest power of 2, also easier
to program.

2.2 Hexadecimal Numbers

When the string is long, hexadecimal is more convenient than binary. As is decimal,
but it doesn't show us the pattern of 0s and 1s in the binary rperesentation
A hexadecimal number has base 16. It has digits 0--9 and then A,B,C,D,E,F.
Both yasm and C/C++ represent hexadecimal numbers with the prefix 0x.

Hex To Integer

0xa1a = a * 16 ^ 2 + 1 * 16^1 + a * 16^0 .


a is 10 so == 10 * 256 + 16 + 10 = 2560 + 16 + 10 = 2586

Conversion to convert decimal to binary follows the same pattern as with binary

(_ same methods as for binary)

2586 = _ * 16^2 + _
= 10 * 256 + 26
= 10 * 256 + 1 * 16 + 10
= 10 * 16^2 + 1 * 16^1 + 10 * 16^0
= A 1 A
= 0xA1A

similarly
number /16 reminder hex so far
2586 161 10 = A A
161 10 1 1A
10 0 10 = A A1A = 0xA1A

Converting between binary and decimal and binary and hexadecimal is painful. But
(KEY) why do this? Use whatever format is convenient. If you want to use 1027 in a
decimal context, use decimal. If you want a (Binary) pattern you can chose binary
(short strings) or hexadecimal (long binary string).

Binary and hexadecemial convert into each other easily

0xA1A = A 1 A = 1010 0001 1010 = 101000011010b


101000011010b = 1010 0001 1010 = 0xA 1 A

2.3 Integers

On the x86-64 architecture, integers can be 1 byte, 2 bytes, 4 bytes, or 8 bytes in


length. For each length, the numbers can be signed, unsigned. A table listing
minimum and maximum values for each type of integers

Variety Bits Bytes Minimum Maximum

unsigned 8 1 0 255
signed 8 1 -128 127

unsigned 16 2 0 65535
signed 16 2 -32768 32767

unsigned 32 4 0 4294967295
signed 32 4 -2147483648 2147483647

unsigned 64 8 0 large
number
signed 64 8 - large number large
number

The range of 64 bit integers is large enough for most needs (20! is larger!).

(KEY) Unsigned integers are precisely the binary numbers we saw earlier.

(KEY) (step) Signed integers are stored in a useful format called 2's complement.

(step)
The first bit of a signed integer is a sign bit - 0 ==> integer is positive. 1 ==>
number is negative.

attempt 1
The most obvious way to store the negative number would be to store the absolute
value of the number after the sign bit.

(_ KEY verification step: what we need is for the positive and negative numbers
with the same magnitude to add to zero. This fails with the scheme above as can be
seen from )

with the above scheme (8 bit) positive 1 is

0000 0001 and so negative number is (by the above scheme)


1000 0001 adding these two we get
1000 0010 == -2 decimal! . so 1 + -1 = -2 instead of 0

This scheme doesn't work so we try


(step) Scheme 2.

Corresponding negative number is 1 in the sign bit (For negative numbers) + bit
*complements* for the other bits in the positive numbers

so (by this scheme)


1 = 0000 0001
-1 = 1111 1110 adding these we get
0 = 1111 1111 this is negative zero by this inversion scheme. the leftmost bit
is 1 for negative number. the remaining numbers are complements of the positive
number which is 000 0000. which is (positive) zero

But does this -1 representation work (_ for other numbers). What is 4 + -1?

4 0000 0100
-1 1111 1110 (from above)
gives 0000 0010 = 2 (instead of 3 the correct answer)

so we need another scheme.

(step) Scheme 3:

We add 1 to the complement of the positive number

so -1 is 1111 1110 (from the above skin) +


1 is 0000 0001
-------------
1111 1111 (this is -1 in this scheme).

Try 1 + -1

0000 0001
1111 1111
10000 0000 . the leftmost 1 is in the 9th position, which is thrown away to
get

0000 0000 which is correct

Try 4 + -1

0000 0100
1111 1111
10000 0011 = throw away the leftmost 1 , 0000 0011. which is 3.

so this works

(step) what is the largest positive number in 8 bits


0 111 1111 which is 127 -- leftmost 0 indicates +ve number

what is the largest negative number in 8 bits?

the negative number


-1 is 1111 1111

-2 is 1 then [(000 0010 complement) + 1]


1 then [111 1101 + 1]
1 then 111 1110 which is
1111 1110

-3 is 1 then [ 000 0011 complement + 1]


1 then [ 111 1100 + 1]
1 then [ 111 1101]
1111 1101

-4 is 1 then [000 0100 complement + 1]


1 then [111 1011 + 1]
1 then [111 1100]
1111 1100

so for each multiple of 2 they have all ones till (and including) the position
which would indicate the number in the positive equivalent.

the largest possible negative number is 1000 0000. What is the magnitude of
this number?

(_ The largest negative number in 2's complement is the the negative equivalent of
the positive number represented by (unsigned binary number with) leftmost 1 and
rest 0s. see Patt for the reasoning)

so 1000 0000 == -ve 128.

(KEY) in two's complement representation the minimum (the largest negative)


number's magnitude is 1 more than the magnitude of the largest positive number.

(_ assuming a 16 bit word size)


convert -750 to a 2s complement binary representation

first derive the binary represenation for + 750

number /2 = quotient reminder binary number thus far


750 375 0 0
375 187 1 10
187 93 1 110
93 46 1 1110
46 23 0 01110
23 11 1 101110
11 5 1 1101110
5 2 1 11101110
2 1 0 0 1110 1110
1 9 1 10 1110 1110

padding to 15 bits (the 16th bit is for the sign bit)

this is 000 0010 1110 1110

complementing 111 1101 0001 0001


+1 000 0000 0000 0001
gives 111 1101 0001 0010 then add sign bit
to get 1111 1101 0001 0010 this is 2 complement representation -750

In hex this is 0xFD12

(step)
Convert 2's complement binary to signed decimal

start with 1111 1101 0001 0010 == the number given is negative so we need to
calculate the magnitutde
=== (+ 1 complement (positive binary)))
=== 1111 1101 0001 0001 == (complement (positive binary))
=== 0000 0010 1110 1110 == positive binary
=== convert to integer === 750

This gives the magnitude.

so the decimal number is -750

(step)
convert hexadecimal to signed binary.
start with 0xFA13

convert to binary to get 1111 1010 0001 0011


this is sign bit 1 (so negative) + 111 1010 0001 0011
invert the lowermoste 15 bits to get 000 0101 1110 1100
add 1 to get 2s complement 000 0101 1110 1101
this is 1024 + 256 + 128 + 64 + 32 + 8 + 4 + 1 = 1517 which is the magnitude of
the number

so 0xFA13 = -1517

2.3.1 Binary Addition

we add -750 and -1517 in binary

-750 1111 1101 0001 0010


-1517 1111 1010 0001 0011
---------------------------
1 1111 0111 0010 0101
---------------------------

Ignoring the carry bit, we have 1111 0111 0010 0101

To convert to decimal, invert the lower 15 bits and add 1 giving


000 1000 1101 1011 which converted to decimal is 2267 which is the magnitude.
-2267

mechanics of binary addition.

2.3.2 Binary Multiplication

is like decimal multiplication. multiply one bit at a time and stagger to the left

1010101 *
10101
-------
1010101
1010101 <-- staggered two places because 2nd digit from right is 0
1010101
----------
11011111001
-----------
_none of these numbers are decrypted_

2.4 Floating Point Numbers

The x86-84 architecture supports 3 different varieties of floating point numbers -


32 bit, 64 bit, 80 bit numbers, stored in IEEE 754 bit format.

Type Name Bits Exponent ExponentBias Fraction


Precision
float 32 8 127 23 ~7
digits
double 64 11 1023 52 ~16
digits
long double 80 15 16383 64 19
digits

the IEEE format deals with all these numbers in the same way (?) but with different
lengths for fields.
in each format the highest order bit is the sign bit.

A negative number has the sign bit set to 1 and (KEY) all the other digits are just
like the corresponding positive number.
Each number has a binary exponent and a fraction.

We focus on the float type to reduce the number of bits involved

total number of bits = 32.

bits 0 - 22 (23 bits) = (the fraction)


bits 23- 30 (8 bits) = (the exponent)
bit 31 = leftmost bit = sign bit.

The exponent (??) for a float is an 8 bit field. To allow for large numbers or
small numbers (_ which need negative exponents) the exponent is interpreted as
positive and negative. The actual value of the exponent is the value of the 8 bit
field minus 127. (_ this) 127 is the "exponent bias" for 32 bit floating point
numbers.

The fraction field of a float holds a small surprise.


Since all bits of 0.0 is defined as all bits were set to 0, there is no need to
worry about representing 0.0 as an exponent field equal to 127 (??) as and a
fraction field set to all zeros.

All other numbers have at least 1 bit, so the IEEE 754 format uses an implicit
1 bit to save space. (_ iow) if the fraction field is < 23 zeroes> it is
interpreted as 1. < 23 bits > . which allows the fraction field to be effectively
24 bits (??). This is made possible by making exponent fields 0x00 and 0xFF
special.
A number with exponent field == 0x00 is defined by 0. An exponent field value
of 0xFF is used to mean either positive or negative infinity. Many more details
exist for IEEE 754,but this is sufficient for our needs.

To illustrate floating point data consider the following data file

segment .data
zero dd 0.0
one dd 1.0
neg dd -1.0
a dd 1.75
b dd 122.5
d dd 1.1
e dd 10000000000.0

This is not a program it is simply a definition of 7 float values in the .data


segment.
The dd command specifies a double word data item. Other options include db (data
byte), dw (data word) - 2 bytes, and dq(data quad word) - 4 bytes,

Now consider the listing file produced by yasm

1 %line 1+1 fp.asm


2 [section .data]
3 00000000 00000000 zero dd 0.0
4 00000004 0000803F one dd 1.0
5 00000008 000080BF neg1 dd -1.0
6 0000000C 0000E03F a dd 1.75
7 00000010 0000F542 b dd 122.5
8 00000014 CDCC83CF d dd 1.1
9 00000018 F9021550 e dd 10000000000.0

The zero variable is stored as expecetde all 0 bits.


The other numbers might be a little more surprising.
Look at one - the bytes are backwards (?) - reverse them and you get 3F800000.
(note 8 bytes of bits for a total of 64 bits - half seem to be unused) The most
significant byte is 3F. the sign bit is 0. The exponent field consists of the other
7 bytes of the most significant byte and the first bit of the next byte. This means
that the exponent field is 127 and actual binary exponent is 0.

(_ work through
3F80 which is 0011 1111 1000 0000 .
so yes the sign bit = left most bit is 0.
exponent field = other 7 bits of the most significant byte + 1 bit from
the next byte = 0111 1111 which is 127 the exponent field value. and the actual
binary exponent is 0 (since it is exponent field value - 127, the "exponential
bias"). The remaining bits are the binary fraction field, all zeros.

Thus the value is 1.0 * 2^0 = 1.0


)

The remaining bits are the binary fraction field - all 0s. Thus the value is 1.0 *
2^0 = 1.0

negative 1 (_ is BF80 which is 1011 1111 1000 0000 and so) the sign bit is 1,
the exponent field is 0111 1111 the same as above so the number is -1 * 1.0 * 2^0 )

(step)
you will notice that 1.75 and 122.5 have a significant number of 0s in the fraction
field.
(_ 1.75 is 3FE0 .. which is 0011 1111 1110 0000 0000 0000 0000 0000 ) this is
because 0.75 and .5 are both expressible as sums of negative powers of 2)

0.75 = 0.5 + 0.25 = 2^-1 and 2^-2


(step)
1/11 = (in decimal) 0.090909.....

in binary, 1.1 is 1.0001100110011001100.....

in hex, 1.1 is 0x3F8CCCCD


the exponent is 0 (so 2^0) and the fraction is (_ the fraction field contains) 000
1 1001 1001 1001 1001 10 1 It looks like the last bit has been rounded up. It looks
like the repeated pattern is 1100

KEY : CPU stores least significant byte first.

4097 decimal is 0x 00 00 10 01 but the cpu stores the least significant byte
first .

In the ,data section we have

00 00 00 10 * 01 10 00 00 * b dd 4097

4097 is 0x1001 padding to 32 bits this is 0x00001001

2.4.1 Converting Decimal Numbers To Floats


We work on an example.
we convert -127.6875 to decimal.

The sign bit is 1 (_ to indicate negative)


Now we work on 127 is 0111 1001 b
Now we need to work on the fraction. 6875 which is to the right of the decimal
point.

2.4.2 Converting Floats To Decimal


2.4.3 Floating Point Addition
2.4.4 Floating Point Multiplication

You might also like