home comics writing pictures archive about

2022-09-03 - DataTypes: Numbers

So far we’ve only used bits to store logical values, true and false, but there’s limited information that can be represented with just true and false. How do you encode that a building has 5 floors? A series of boolean values encoding if the building has floor 1, floor 2, floor 3… ? That’s manageable for a few floors but will get very complicated if you have hundreds of them. Luckily bits or binary-digits as the name suggests can be used to represent binary, base-2, numbers.

To start let’s look at decimal, base-10, numbers which is how we typically think of numbers. If I showed you the number 824 you’d probably think of it as eight-hundred and twenty-four. Each digit position represents a power of 10. You’ve got 1s, 10s, 100s, 1000s etc or using powers of 10 we have 1 = 100, 10 = 101, 100 = 102, 1000 = 103 etc. We can think of 824 then as 8 x 102 + 2 x 101 + 4 x 100. This is actually how all bases work, the difference is the number you are multiplying the digits by.

Binary numbers are base 2 which means they have 2 digits (0 and 1) and the digit positions are powers of 2. So the first position is 20 = 1, the second is 21 = 2, then we have 22 = 4, 23 = 8, 24 = 16 etc. To convert the binary number 100101 to decimal we can use the same process we used for 824 but with powers of 2 instead of powers of 10. This gives us 1 x 25 + 0 x 24 + 0 x 23 + 1 x 22 + 0 x 21 + 1 x 20 which is 32 + 4 + 1 or 37 in base-10. Basically you add up the power of 2 for any position that has a 1 in it. The more bits we have the larger the number we can represent. With a byte we can represent numbers for 0 to 255, with 2 bytes we can go up to 65535 and with 4 bytes we can go up to 4,294,967,295.

To convert from decimal to binary you divide the value by 2, keep track of the remainders you get until you end up with 0 and then put the remainders in reverse order. For example 37 / 2 is 18 with a remainder of 1. 18 / 2 is 9 with no remainder. 9 / 2 is 4 with a remainder of 1. 4 / 2 is 2 with no remainder. 2 / 2 = 1 with no remainder. 1 / 2 is 0 with a remainder of 1. Working backwards our remainders are 1, 0, 0, 1, 0, 1 which is the binary version of 37. Each divisions determines if we need a bit set at the current position starting from the right-most bit. The first division determines the zeroth bit, the next division determines the oneth bit etc. 

There are two other bases that come up often in computing. Octal, or base 8, which uses the digits 0 to 7 and hexadecimal, or base 16, which uses the digits 0 to 9 and A to F (A = 10, B = 11, C = 12, D = 13, E = 14, F = 15). These bases are used because you can easily convert between them and binary by grouping bits. This gives use a more compact way to represent values without having to do complicated conversions. To convert from binary to octal we use groups of 3 bits and then write the value of those groups. The binary number 101100011010  split into groups of 3 bits would be 101|100|011|010 and if we take the values of those groups we get the octal number 5432. Hexadecimal works the same way but with groups of 4 bits. 101100011010 split into groups of 4 bits would be 1011|0001|1010 and if we take the values of those groups we get the hexadecimal number B1A. To convert back we simply expand the values back into 3 of 4 bit groups depending on our starting base. Converting from these bases to decimal works the same way as with binary but with powers of 8 and powers of 16 respectively.

All the arithmetic operations work the same with base 2 as they do with decimal numbers just with less digits. So instead of 1 + 1 equaling 2 we have 1 + 1 = 0 with a carry leftover to give us 10 which is the same as 2.

Next time we will look at how to represent negative numbers

2022-03-05 - An Incomplete History of Microprocessors

At the dawn of the computer age not only were they massive but their components were massive as well. Large collections of vacuum tubes or discrete transistors all wired together. A processor could fill a cabinet all by itself. The invention of integrated circuits allowed for all these components to be placed inside a single chip that could fit in your hand. Microprocessors are integrated circuits designed to process information and execute instructions. The shrinking of the processor lead in turn to the shrinking of the computer which allowed them to be used in homes and schools. Instead of needing a dedicated room computers could now fit on a desk. This list focuses on microprocessors used in consumer devices from the 70s and 80s.

1971 - Intel 4004

4-bit registers and data bus, 12-bit address bus (2048 bytes)

The 4004 was the first commercially produced microprocessor. Originally designed for calculators it soon became clear that it could be used to build a complete, if limited, computer

1974 – Intel 8080

8-bit registers and data bus, 16-bit address bus (64 kiB)

The 8008 was intel’s first 8-bit processor but it was the 8080 that really kicked off the microcomputer revolution. Computers like the Altair 8800 and the IMSAI 8080 were huge successes and lead to the standardization of the S-100 bus and CP/M as the first commercially available operating system.

1974 - Motorola 6800

8-bit registers and data bus, 16-bit address bus (64 kiB)

The 6800 found some use in early home computers like the Southwest Technical Products 6800 and the Altair 680 but it never caught on the way the 8080 did.

1975 - MOS Technology 6502

8-bit registers and data bus, 16-bit address bus (64 kiB)

Designed by former Motorola employees based on the 6800, the 6502 would go on to become one of the big players in the 8-bit micro generation. Used in computers like the Apple, the Apple II, the Commodore PET, the Atari 8-Bit family, and the BBC micro.

1976 - Texas Instruments TMS9900

16-bit registers, data bus and address bus (64 kiB)

Designed for use in TI own computer line-up the TMS9900 was one of the first 16-bit processors.

1976 - Zilog Z80

8-bit registers and data bus, 16-bit address bus (64 kiB)

Designed by former Intel employees and based in the 8080 the Z80 would become the other big microprocessor of the 8-bit era. It was used in computers like the TRS-80, Sinclair ZX80/ZX81/Spectrum and other business oriented computers. Being compatible with the 8080 it also ran CP/M.

1978 - Motorola 6809

16-bit registers, 8-bit data bus, 16-bit address bus (64 kiB)

The 6809 was similar to the 6800 but added some 16-bit features which gave it a step up over the other 8-bit processors of the time. It’s main use was in the TRS-80 Color Computer.

1979 – Intel 8088

16-bit registers, 8-bit data bus, 20-bit address bus (1 MiB)

The 8088 was used in the first-generation of IBM Personal Computers and is the grand-uncle of the modern x86 architectures which currently dominate the home computer market. It’s brother the 8086 had a full 16-bit data bus and was therefore faster but the 8088, with its smaller data bus, allowed for cheaper motherboards.

1979 - Motorola 68000

32-bit registers, 16-bit data bus, 24-bit address bus (16 MiB)

Although one of the first 32-bit processors the 68000 would become one of the main players in the 16-bit era of microcomputers with computers like the Apple Macintosh, Atari ST and Commodore Amiga.

1982 – MOS Technology 6510

8-bit registers and data bus, 16-bit address bus (64 kiB)

A modified version of the 6502 with I/O pins. The 6510 was used primarily in the extremely successful Commodore 64

1984 – Motorola 68020

32-bit registers, data bus and address bus (4 GiB)

A fully 32-bit version of the 68000 which found usage in revisions to the Apple Macintosh and Commodore Amiga lines.

1985 – Intel 80386

32-bit registers, data bus and address bus (4 GiB)

The first 32-bit implementation of the Intel x86 architecture that would become the mainstay of the PC world.

2022-01-23 - Programming Active Server Pages

Programming Active Server Pages was written by Scott Hillier and Daniel Mezick and published by Microsoft Press in 1997. This book discusses Active Server Pages (ASP), one of Microsoft’s early attempts at building a server-side website development platform. The idea is that you create .asp files with sections of VBScript or JavaScript code in them which is ran by the server and the resulting HTML page is then sent to the client. This is similar to ASP.net, JSP and PHP in both functionality and look. The main benefit of ASP like the other similar technologies is that you can have dynamic pages, pages where the content changes based on some condition, without needing to run code on the client machine. This has security advantages as the client has less of a chance to interfere with the operation and also means you aren’t reliant on the client supporting the technology you want to use. This book does some things I like and some things I don’t like so overall my opinion is very middling.

Starting with things I like. I like examples and this book has a lot of them. The practical examples are identified by numbered steps which helps to separate them from informational examples. They also go into quite a bit of detail which makes them easy to follow. The final few chapters of the book are entirely devoted to examples which is nice as it gives you an in-depth look at the things being talked about in the book.

As for things I don’t like, I don’t like books that aren’t clear what they are about. For a book about ASP this book spends a lot of time talking about non-ASP things like dynamic HTML and client side scripting. It’s a bit telling when you can make it to chapter 5 before the main topic of the book starts to get discussed. I don’t mind books that gives additional information but I feel like the the main topic should be the focus.

I also think the book should have focused more on the syntax of VBScript and JavaScript up-front. There’s an appendix dedicated to that topic but I think it would have been better if it was a part of the introduction. That might just be my preference for beginner books where the topic is explained from the ground-up and there isn’t a lot of assumed knowledge.

One final criticism is the reliance on pre-release technology. There’s a decent amount of ActiveX in the book, which is fine, but the book seems to have been written before all the ActiveX controls were finalized. This means that in some cases the GUID used to reference the control or the parameters used by the control in examples don’t actually work. It’s not clear to the reader if they did something wrong or if the book is wrong. I get the desire to have the book out in time for the launch of the functionality but It’s probably best to wait to write about things until you know they won’t change, otherwise you are just setting your readers up for issues.

Overall I enjoyed the book and found the writing and examples interesting. I think the book could have been a lot better if it focused more exclusively on ASP, has more introductory content about the languages used and didn’t reference things that were incorrect by the time the book was published but it’s by no means terrible.

2021-12-05 - In IL: C# Classes and Structs

Last time we looked at class definitions in IL, now let’s see how some compiled C# examples look. This program has a variety of class and struct definitions.

Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CsClass
{
class Program
{
static void Main(string[] args)
{
}
}
internal class InternalClass { }
public class PublicClass { }
public class NesteeClass
{
private class NestedPrivateClass { }
private protected class NestedPrivateProtectedClass { } //C# 7.2
internal class NestedInternalClass { }
protected class NestedProtectedClass { }
protected internal class NestedProtectedInternalClass { }
public class NestedPublicClass { }
}
public interface IInterface { }
public abstract class AbstractClass { }
public sealed class SealedClass : AbstractClass { }
public static class StaticClass { }
public class DerivedClass : AbstractClass { }
public class InterfaceClass : IInterface { }
public struct PublicStruct { }
public enum PublicEnum { }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

If we compile this we get a lot of code but let’s just focus on the classes starting with the internal and public classes.

.class private auto ansi beforefieldinit CsClass.InternalClass
extends [mscorlib]System.Object
78
79
.class public auto ansi beforefieldinit CsClass.PublicClass
extends [mscorlib]System.Object
93
94

InternalClass is marked as private and PublicClass is marked as public these correspond to the Visibility options we saw last time. Now let’s look at the nested classes.

.class auto ansi nested private beforefieldinit NestedPrivateClass
extends [mscorlib]System.Object
111
112
.class auto ansi nested famandassem beforefieldinit NestedPrivateProtectedClass
extends [mscorlib]System.Object
126
127
.class auto ansi nested assembly beforefieldinit NestedInternalClass
extends [mscorlib]System.Object
141
142
.class auto ansi nested family beforefieldinit NestedProtectedClass
extends [mscorlib]System.Object
156
157
.class auto ansi nested famorassem beforefieldinit NestedProtectedInternalClass
extends [mscorlib]System.Object
171
172
.class auto ansi nested public beforefieldinit NestedPublicClass
extends [mscorlib]System.Object
186
187

NestedPrivateClass is marked as nested private, NestedPrivateProtectedClass is marked as nested famandassem, NestedInternalClass is marked as nested assembly, NestedProtectedClass is marked as nested family, NestedProtectedInternalClass is marked as nested famorassemand NestedPublicClass is marked as nested public. These correspond to the Accessibility options. Note that on a nested class internal is compiled as nested assembly but on the non-nested class it’s private. Also note how private protected and protected internal get compiled down to famandassem and famorassem respectivly. C# is trying to limit its keyword usage which can lead to confusing situations where as IL is trying to be much more explicit and clear in what it’s doing. Trade-offs of the differing goals of the two languages. Now let’s look at the interface.

.class interface public abstract auto ansi CsClass.IInterface
213

IInterface is also declared using the .class directive but it has the interface attribute applied to it to mark it as an interface. It’s also marked as abstract which means you can’t declare an instance of this class, which makes sense for an interface. We can also see that option if we look at AbstractClass.

.class public abstract auto ansi beforefieldinit CsClass.AbstractClass
extends [mscorlib]System.Object
217
218

Now let’s look at the SealedClass.

.class public auto ansi sealed beforefieldinit CsClass.SealedClass
extends CsClass.AbstractClass
232
233

It's marked with the sealed attribute which means you can’t derive another class from it. So far these examples have mapped fairly easily from C# to IL but how does StaticClass map? There’s no static IL attribute. Well let’s see.

.class public abstract auto ansi sealed beforefieldinit CsClass.StaticClass
extends [mscorlib]System.Object
247
248

It combines several attributes to achieve the desired result. We have the abstract attribute to prevent instances of that type from being declared but it's also marked as sealed so you can't derive a class from it and declare an instance of that. So by combining these two attributes the C# compiler has created it's idea of static without that needing to be specifically specified in IL. Now let’s look at DerivedClass.

.class public auto ansi beforefieldinit CsClass.DerivedClass
extends CsClass.AbstractClass
252
253

It's marked with extends CsClass.AbstractClass. This is how base classes are specified in IL. Note how all the other classes, except IInterface, are marked as extending [mscorlib]System.Object. This is how everything can be treated as a derivation of Object because they are. This is implicit when defining C# classes but explicit in the generated IL. Now let’s see how InterfaceClass works.

.class public auto ansi beforefieldinit CsClass.InterfaceClass
extends [mscorlib]System.Object
implements CsClass.IInterface
267
268
269

It's also marked as extending Object but it has an aditional implements CsClass.IInterface which is how IL specifies the interfaces a class implements. Again notice the shift from implicit to explicit. In C# you simply list the base class and interfaces separated by commas but in IL you say it extends these base classes and implements these interfaces. Back to things that don’t seem to have options in IL, how do structs work? Well let’s see.

.class public sequential ansi sealed beforefieldinit CsClass.PublicStruct
extends [mscorlib]System.ValueType
283
284

PublicStruct is also declared using .class but instead of extending from Object we have extends [mscorlib]System.ValueType. System.ValueType is a special class in IL that tells the runtime to treat the class as a value type which means that instead of references being passes around the actual value is passed around. Also note that it’s marked as sequential instead of auto. This is because the default behaviour for structs is to have the fields laid out in memory the same way they are declared in the struct. But what about enums?

.class public auto ansi sealed CsClass.PublicEnum
extends [mscorlib]System.Enum
290
291

PublicEnum has extends [mscorlib]System.Enum with System.Enum being another special class. Note that System.Enum derives from System.ValueType which derives from System.Object so everything is still objects in the end.

So as you can see everything in IL is actually a class. Some classes just have more options applied than others. Now a quick note about namespaces, notice that there aren’t any namespace declarations. Whenever we declare a class or reference a class we use it’s fully qualified name. Namespaces are a C# concept for making it easier to specify these names but they don’t really exist at the IL level. IL is meant for computers and computers don’t mind a little extra typing.

Next time we’re going to look at Visual Basic .NET classes, structures and modules. I bet you can guess how those are going to look once compiled.

Prev page

2 3 4 5 6

Prev page