home comics writing pictures archive about

2021-08-27 - Goals

I’ve been contemplating goals a lot lately. It seems like goals can be both good and bad depending how you set them. They can help you get stuff done while at the same time discouraging you from doing things.

On the positive side, goals are good for making sure you know what to do. Having a plan for your career, hobbies, life etc. If your goals are short term they can provide with options when you are contemplating what to do with your spare time and then make you feel more accomplished when you complete them. If your goals are long term they can give you direction and tell you what to work for.

On the negative side, they can be discouraging if it’s not clear how to accomplish them. If a goal is difficult or requires a lot of luck it can be easy to not even try. They can also make your other accomplishments feel less impressive because they aren’t what you’re supposed to be doing.

It seems like the further out your goals are the more vague they need to be. Don’t set yourself an absolute target far away instead try to set a general direction you want to go in. Figure out a few things that you can do along that path but don’t set up too many things upfront. Complete those tasks, see where you are, figure out where you want to go and make some more tasks.

You may not end up where you originally planned to go but you should at least end up going somewhere.

2021-06-06 - In IL: Class Definitions

IL is a object oriented language like C# and Visual Basic .Net. This means that classes are a built in concept. Classes are defined with a class header describing the class followed by a class body enclosed in curly braces.

.class <attributes..> <Id> extends <baseClas> implements <interfaces…>{ }

A class is declared using the .class directive. This is followed by a set of attributes which describe how the class behaves. The Id is the name of the class. The extends keyword is used to specific the base class. If no base class is provided system.Object is assumed. The implements keyword is used to specify which interfaces the class supports.

There are a variety of attributes that can be set.

Visibility

The visibility attributes are used for non-nested classes to indicate if they are exported, available, outside the assembly or not.

Attribute Description
private Class is not exported outside assembly
public Class is exported outside assembly

Accessibility

The accessibility attributes are used for nested classes to indicate if they are available to other classes.

Attribute Description
nested private Visible only within the containing class
nested famandassem Visible to containing class and derived classes within the same assembly
nested assembly Visible to the containing assembly
nested family Visibility to containing class and derived classes
nested famorassem Visibility to containing class and derived classes or to the containing assembly
nested public Visible everywhere

Layout

The layout attributes control how the fields of the class will be laid out in memory

Attribute Description
auto Layout of fields in the class is determined by the runtime
sequential Layout of fields will be sequential based on order of the fields in the class
explicit Layout of fields in the class will be set explicitly

Type

The type attribute is used to specify what type of class is being defined

Attribute Description
interface Class is an interface

Inheritance

Inheritance attributes control how a class can be used

Attribute Description
abstract Class cannot be instantiated
sealed Class cannot be derived from

Interpolation

Interpolation attributes control how the class is handled when interacting with unmanaged code. Specifically it controls how strings contained in the class will be marshalled, packaged, before being sent to the unmanaged code.

Attribute Description
autochar string marshalling is determined by platform
ansi Marshalled using ansi strings
unicode Marshalled using UTF-16 strings

Special

Special attributes are used by the runtime or tool to control how the class will be treated

Attribute Description
beforefieldinit Don’t initialize fields before a static call
serializable fields can be serialized (reserved)
rtspecialname Name has special meaning to the runtime
specialname Name has special meaning to tools

2021-05-16 - Abstraction is Magic

In computing terms an abstraction is treating something like a magical box. You put certain things into the box and get certain things out of it but how the box actually works is irrelevant to you. Typically this magic box is a system, program or library provided to you by someone else that solves some general problem of computing or provides certain functionality that makes developing an application easier. Abstractions are the basis for a lot of the advancements in computing because they allow us to spend more time focusing on the problems that are specific to the thing we are trying to make. To see how this works I’m going to go through several levels of abstraction and show how they allow us to create more complicated programs.

The zeroth level of abstraction is hardware. The first computers were all hand assembled using components specifically built for those computers. This meant that every computer was unique and a lot of time was spent designing and building each one. Eventually companies started to mass-produce components, CPUs, memory managers, disk interfaces, video controllers etc, and when you can build a computer using off-the-shelf chips instead of specifically designed components it makes it a lot easier and faster to get a working computer. The trade-off is you have less control over the specification and characteristics of each individual component.

The first level of abstraction is machine language. Machine language programs are made up of a series of binary values that tell the computer what to do. A 120 might tell the computer to move a value from one register to another and a 195 might tell it to jump to an instruction at a specific address. Now that were are using mass-produced chips we no longer have to worry about how these codes control the computer and instead we can focus on what we want the computer to do. The trade off is that we are limited to the operations that were implemented in the chip we are using.

The second level of abstraction is assembly language. These are the textual mnemonics used to represent the machine language instructions available. Instead of a 120 we now have a MOV A,B instruction and instead of 195 we now have a JMP instruction. An assembler program provided to use takes this text and converts it into the binary machine language that the computer understands. Assembly languages usually also have directives and labels which allow the programmer to tell the assembler what they want it to do without having to specifically set things up. Some can even perform optimizations that improve performance or memory usage. Now we don’t have to memorize the binary value of each instruction or figure out which addresses we want to use. Instead we can focus more on what we want the program to do which is easier to describe using mnemonics. The trade off is we have less control over the set of operations that the computer actually executes.

The third level of abstraction are compiled or interpreted languages. These are more advanced programming languages which don’t try to represent the actual machine language operations available. Instead of MOV instructions we have variable assignment and instead of JMP instructions we have conditional statements. The compiler or interpreter takes the text you wrote and does the hard work of turning it into the machine instructions that the computer can actually execute. Now we don’t have to know anything about the instruction set of the computer we are running on or sometimes even which computer we are running on. Instead we can focus more on what we want the program to do which is a lot easier to describe using the keywords of the higher level languages. The trade off is we have even less control over what operations the computer is executing.

The fourth level of abstraction are frameworks and libraries. These are collections of code which have been written to handler UI or database operations for us. Instead of drawing a dialog box using box characters we just tell the framework that we want a dialog and where we want it and it draws it for us. Someone wrote the framework to have a dialog function in it and we simply have to call that function. Now we don’t have to worry how to draw dialogs or connect to databases. Instead we can focus more on what we want to do with the dialogs and the database. The trade off here is we don’t have any control over how these dialogs are implemented or what functionality they provide.

The further up we go the more we get to focus on our specific problem. A program is about getting information from a source and then doing something useful with that information. The less we need to focus on the operations of getting information, displaying information or storing information the more we can focus on what we specifically want to do with that information. The trade-off with abstraction is efficiency. If you do everything from scratch you can develop a solution that is extremely efficient at doing what you want it to do but will likely require a lot of work to complete. On the other hand using abstractions you can be more efficient at designing and implementing your solution because you are simply putting together magical boxes created by other people with a little bit of customization on top for your particular needs. The solution won’t be quite as optimized as all the magical boxes need to support a variety of situations which don’t all apply to you but it will be a lot quicker to design and implement.

As computers have gotten more powerful the need for efficiency has gone down. We no longer need to fit our programs in 1 MiB of memory or less so using a large library that we only need a small part of is less of a problem. The more abstractions we can use the less we need to worry about and the more we can focus on what we are trying to do.

Of course the downside of abstractions are when things don’t work the way you want them to. Then the magical box concept becomes a pain because you need to know how it works and hopefully change it to better suit your situation.

2021-04-17 - DataTypes: Bits

Binary Digits or Bits are the simplest data type used by computers. They are can either have a value of 0 or 1 and all digital data is based on them. How the data is actually stored depends on what you are storing it on. Inside of a computer bits are stored and transmitted using voltage levels. The actual voltages and which state represents which value are system and situation dependant but in all cases there are two states and one state is a 0 while the other is a 1. Hard drives, tape drives and floppy disks use magnetic polarity to encode bits. Optical media like CDs and DVDs use pits and the absence of pits to encode bits. As long as you have something that can have one of two states it can be used to store or transmit a bit.

but a bit on its own isn’t that useful as it only has two values so in most cases you have a series of bits. The combination of the states of these bits is used to encode data using a variety of formats. The number of possible states is calculated as 2 to the power of the number of bits you have. If you have 1 bit that’s 2 to the power of 1 or 2 states (0, 1). If you have 4 bits that’s 2 to the power of 4 or 16 states (0000, 00001, 0010, 0011, 0100, 0101, 0110, 0111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111). What meaning you give to these states depends on what you are using them to represent. We’ll get more into that in later parts. For now I want to talk about terms for groupings of bits.

Bytes

The meaning of a byte is determined by the system you are using but typically it’s the number of bits required to store a single character on the system and/or the minimum addressable number of bits. Typically on modern computers a byte is 8 bits but other systems may use different values. For example a large number of mainframe computers had 6-bit characters and so they used 6 bit bytes. The 8-bit byte comes from ASCII representations which use 8 bits and the use of 8-bit CPUs for early microcomputers.

The unambiguous term for 8 bits is an Octet

Words

Again the meaning of a word is determined by the system but it is typically the native size of the registers, single value memory locations, inside of the CPU. Usually but not always this is also the size of the data bus, circuit paths coming from the CPU used to send/receive data and the size of the address bus, circuit paths coming from the CPU used to specify which memory location is being written to or read from. For example modern 64-bit CPUs have 64-bit registers, excluding large multi-value registers, and 64-bit wide address and data buses. Although this isn’t universal, for example the Intel 8088 used in the original IBM PC has 16-bit registers but an 8-bit data bus and a 20-bit address bus.

The meaning of a Word can also be determined by the software environment you are running. For example in windows development a Word is always 16 bits even on 64-bit versions of the operating system. This is because windows started as a 16-bit OS and to maintain backwards compatibility the meaning hasn’t been updated.

Larger

Larger collections of bits are usually specified using prefixes although this can be confusing as historically two prefix schemes have been used.

The SI unit system uses a set of prefixes corresponding to powers of 10. k or kilo means 10^3 or 1000, M or Mega means 10^6 or 1,000,000, G or Giga means 10^9 or 1,000,000,000 etc. These prefixes with the standard meanings have been used for collections of bits and bytes but often a binary version is used. In the that version k = 2^10 or 1024, M = 2^20 or 1,048,576, G = 2^30 or 1,073,741,824 etc. Note that these values are close but not the same as their decimal counterparts. This can lead to confusion, for example Hard Drive manufactures often report sizes using decimal prefixes while windows reports them using binary prefixes. This is how a 250 GB hard drive can turn into a 232 GB drive.

To deal with this confusion an alternative prefix system has been developed that is exclusively binary. ki or kibi means 2^10, Mi or Mebi means 2^20, Gi or Gibi mean 2^30 etc. This system is slowly catching on as it removes confusion but it’s no where near universal.

When using abbreviated units a lowercase b means bits and an uppercase B means bytes. So MiB is a mebibyte while a Mib is a mebibit. You can multiply or divide by the size of a byte on your current system to convert between them.

Prev page

3 4 5 6 7

Prev page