Updating lecctures and readme for relevancy
This commit is contained in:
parent
04ec3696b8
commit
218d1c9d6c
@ -10,29 +10,76 @@ Most typically we deal with binary(when we do) in nibbles or 4 _bit_ chunks whic
|
|||||||
Ex:`0101 1100` is a basic random byte.
|
Ex:`0101 1100` is a basic random byte.
|
||||||
For most sane solutions this is essentially the only way we __ever__ deal with binary.
|
For most sane solutions this is essentially the only way we __ever__ deal with binary.
|
||||||
|
|
||||||
|
> Why can't we (((save bits))) and not use nibbles?
|
||||||
|
|
||||||
|
In truth you can totally do that; but not really.
|
||||||
|
To explain let's look at some higher level C/C++ code; say you had this structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct Point {
|
||||||
|
int x; // specifying width for clarity sake
|
||||||
|
int y;
|
||||||
|
unsigned int valid : 1;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
On a typical x86 system(and many x64 systems) with no compile time optimizations this structure might look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
32(int x) + 32(int y) + 1(unsigned int valid) + 7(bits of padding)
|
||||||
|
```
|
||||||
|
|
||||||
|
Why? Because while we can always calculate the address of a particular byte's address in memory we cant' or rather don't even try to do the same for bits.
|
||||||
|
The reason is simple: a 32bit CPU can calulate any number inclusively between `0` and `0xffffffff` or `4294967295`. That means we have an entropy pool large enough to have 1 number per byte but not enough to include the bits as well.
|
||||||
|
|
||||||
|
If we use that `valid` _bit-field_ in our code later like
|
||||||
|
|
||||||
|
```
|
||||||
|
if(point_ref->valid) {
|
||||||
|
/* do stuff */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The machine code instructions generated will really just check if that byte(which contains the bit we care about) is a non-zero value.
|
||||||
|
|
||||||
|
If the bit is set we have (for example) `0b0000 0001` thus a _true_ value.
|
||||||
|
|
||||||
## Two's Complement - aka Negate
|
## Two's Complement - aka Negate
|
||||||
|
|
||||||
To find the Negation of any bit-string:
|
To find the Negation of any bit-string:
|
||||||
|
|
||||||
|
i.e. `3 * -1=> -3`
|
||||||
|
|
||||||
1. Flip all bits in the bit-string
|
1. Flip all bits in the bit-string
|
||||||
2. Add 1 to the bitstring
|
2. Add 1 to the bitstring
|
||||||
|
|
||||||
|
The case for 3:
|
||||||
|
|
||||||
|
```
|
||||||
|
start off: 0011 => 3
|
||||||
|
|
||||||
|
flip bits: 1100 => -2
|
||||||
|
|
||||||
|
add one: 1101 => -3
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
### Signedness
|
### Signedness
|
||||||
|
|
||||||
> Why?
|
> Why?
|
||||||
|
|
||||||
Because this matters for dealing with `signed` and `unsigned` values. _No it doesn't mean positive and negative numbers._
|
Because this matters for dealing with `signed` and `unsigned` values. _No it doesn't mean positive and negative numbers._
|
||||||
Say we have 4 bytes to mess with. This means we have a range of 0000 to 1111. If we wanted pureley positive numbers in this range we could have 0000 to 1111... or 0 to 15.
|
Say we have 4 bytes to mess with. This means we have a range of 0000 to 1111. If we wanted purely positive numbers in this range we could have 0000 to 1111... or 0 to 15.
|
||||||
If we needed negative represenation however, we have to sacrifice some of our range.
|
If we needed negative representation however, we have to sacrifice some of our range.
|
||||||
Our new unsigned range is 0-7. We say it's unsigned because the first bit here is 0.
|
Our new unsigned range is then `0-7` _or in binary_: `0000 - 0111`. We say unsigned for this range because the largest number we can represent without setting the first bit is `0111` => `7`.
|
||||||
If it were 1 we would have a _signed_ number.
|
Our negative range is then `-8 -> -1` which in binary is `0b1000 -> 0b1111`
|
||||||
|
|
||||||
|
|
||||||
## Intro to hex
|
## Intro to hex
|
||||||
|
|
||||||
> Hex Notation 0x...
|
> Hex Notation 0x...
|
||||||
|
|
||||||
x86 assemblersi(masm) will typically accept `...h`
|
x86 assemblersi(masm) will typically accept `...h` as a postfix notation.
|
||||||
|
|
||||||
More convinient than binary for obvious reasons; namely it doesn't look like spaghetti on the screen.
|
More convinient than binary for obvious reasons; namely it doesn't look like spaghetti on the screen.
|
||||||
|
|
||||||
@ -41,24 +88,29 @@ More pedantically our new hex range is 0x00 to 0xff.
|
|||||||
|
|
||||||
> Binary mapped
|
> Binary mapped
|
||||||
|
|
||||||
It happens that 1 nibble makes up 0x00 to 0xFF.
|
It happens that 1 nibble makes up 0x0 to 0xF.
|
||||||
So for now just get used to converting {0000-1111} to one of it's respective values in hex and evetually it should be second nature.
|
So for now just get used to converting {0000-1111} to one of it's respective values in hex and eventually it should be second nature.
|
||||||
Then just move on to using hex(like immediately after these lessons).
|
Then just move on to using hex(like immediately after these lessons), because writing actual binary is actually awful.
|
||||||
Even the most obfuscated binary files out there don't resort to architectural obfuscation; until they do.
|
|
||||||
|
> Dude trust me hex is way better to read than decimal
|
||||||
|
|
||||||
|
It may seem convenient at first but after a while you'll realized that hex has really easy to understand uses and makes this super clear + concise, especially when dealing with bit masks and bitsets.
|
||||||
|
|
||||||
|
|
||||||
> Ascii in Hex Dumps
|
> Ascii in Hex Dumps
|
||||||
|
|
||||||
Kind of a side note but most ascii text is from 0x21 to 0x66ish[citation needed]
|
Kind of a side note but most ascii text values range from 0x21 to 0x66 so if you're looking for text in a binary look for groupings of that value.
|
||||||
|
|
||||||
## 32 v 64 bit
|
## 32 v 64 bit
|
||||||
|
|
||||||
For those with a 32 bit background know that these notes deal with 64-bit architecutres mostly. So some quick terminology which might randomly throw you off anyway.
|
In case you come from an x86_64 ish background know that in MIPS terminology changes a bit(bun intended).
|
||||||
|
|
||||||
> double-byte/ half-word
|
> x86 byte = mips byte
|
||||||
|
|
||||||
The latter is dumb but soemtimes used so wtever.
|
> x86 word = mips half word
|
||||||
|
|
||||||
> word = 4 bytes
|
> x86 dword = mips word
|
||||||
|
|
||||||
Etc onward with doubles, quads...
|
> x86/64 qword = mips mips dword
|
||||||
|
|
||||||
|
So just keep those translations in mind...
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
# lec3
|
# Lecture 3
|
||||||
|
|
||||||
## One's & Two's Complement
|
## One's & Two's Complement (in depth(or something))
|
||||||
|
|
||||||
_Previous lecture went over signedness of numbers so this section won't as much_.
|
In order to change recall from last lecture that we wanted to represent `3` with a single nibble like so `0b0011`.
|
||||||
|
|
||||||
First we'll deal with flipping bits: this is where you may hear the term _1's complement_.
|
To make this into a `-3` we:
|
||||||
While not very useful on it's own for most purposes it does help get closer to creating a seperation between _positive_ and _negative_ numbers.
|
|
||||||
|
|
||||||
The only other step after flipping all the bits is just adding 1.
|
1. Flipped all the bits : `value xor 0xff..`
|
||||||
|
|
||||||
`1001 1110` becomes `0110 0010`.
|
2. Added 1 to the result of step 1
|
||||||
|
|
||||||
> shouldn't that last 2 bits be 01?
|
> Ok, but like, why do I care? we're just multiplying things by -1 how does that matter at all?
|
||||||
|
|
||||||
Close, the reason why we have `b10` is because if we: `b01 + b1` the `1` will carry over to the next bit.
|
It matters because certain types operations _just suck_ on pretty much every general use platform.
|
||||||
The actual term for this is just __negate__; the other way around is essentially cannon fodder.
|
|
||||||
|
|
||||||
>Ok, but what does that look like _assembly_ the thing I came here to learn.
|
|
||||||
|
|
||||||
Most assemblers accept something like `neg targetValue` however you can also use an _exclusive or_[`xor targetValue, 0xFF`]. Keep in mind that the immediate value should be sign-extended to reflect the proper targetValue size.
|
Most assemblers accept something like `neg targetValue` however you can also use an _exclusive or_[`xor targetValue, 0xFF`]. Keep in mind that the immediate value should be sign-extended to reflect the proper targetValue size.
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# build up our heap to display info from
|
# build up our heap to display info from
|
||||||
heap = encode(frequencies)[0]
|
heap = encode(frequencies)[0]
|
||||||
#print(heap)
|
print(heap)
|
||||||
|
|
||||||
# decode the binary
|
# decode the binary
|
||||||
decode(heap, binary)
|
decode(heap, binary)
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
# Holy Moly
|
||||||
|
|
||||||
|
|
||||||
|
These notes are ancient but I like keeping them around because it reminds of
|
||||||
|
my college days when I didn't really know much :3
|
||||||
|
|
||||||
|
Not sure who will find value from these but here's some random tidbits of knowledge
|
||||||
|
|
||||||
|
|
||||||
# Everyone else
|
# Everyone else
|
||||||
|
|
||||||
To some degree these notes are personal so there are a few mistakes that I just can't be bothered dealing with.
|
To some degree these notes are personal so there are a few mistakes that I just can't be bothered dealing with.
|
||||||
|
Loading…
Reference in New Issue
Block a user