Blogging about our lives online.


Evaluating My Direction

My studies have spiralled out of control a bit lately because I have been running in too many different directions. Building a new programming language from the ground up is a lot bigger job than I should be taking on right now. I think it is conceptually a good idea, but a bit too specific to take on right now. My schooling needs to be general enough to be widely applicable with manageable project goals.
So, stepping back a bit, I need to refocus on my primary tasks right now.
  1. Network+: I have begun to work through the Network+ manual and I think I should be ready for the exam in about 3 months.
  2. Assembly Language: I have worked through "Professional Assembly Language" (Blum 2005), and have come up with a small practical project to implement in assembly language. I will be working on a command-line programmable RPN calculator, details to follow.
  3. Writing: The MIT open courseware is not heading in the right direction since it only has the assignments online. I think I need something that provides more of a framework of how and what I should be trying to accomplish.
  4. Linear Algebra: I have begun the MIT video course on Linear Algebra (18.06) and I think the video series is a good way to engage with the material. It's interesting how differently we learn from lectures vs. learning from books. I have always thought that I learn better by reading, but there is a certain way that we learn how to work through a problem when we participate in working through the problem with a teacher.


Assembly Language - Command line parameters


I ran into a problem with the way that command line parameters are passed in Assembly Language. The book I'm working through has a couple example programs illustrating how to access the command line arguments and none of these examples worked on my system. The simple solution was that, at some point between this book being written and me reading it, this convention had changed. Instead of the stack looking like it does in the book, with all the command line arguments on the stack, we have the number of parameters first and then a pointer to a pointer to all the parameters in null terminated strings.

This is how it looks in the old style:
number: 3
*p1: program name
*p2: param1
*p2: param2

And this is how it looks in the new style:
number: 3
*p: *params
*params: param1, param2, ...

I should have guessed this from the C calling convention **args, but it took a fair bit of digging with GDB to analyze what exactly was going on with the stack. So, the end result: A program to print all the command line arguments:

.section .data
    .asciz "parameter: %s\n"
.section .bss
.section .text
.globl main

    movl    (%esp), %ebx
    movl    4(%esp), %ecx      # Num parameters
    movl    8(%esp), %ebx      # This is a pointer to the string pointer
    movl    (%ebx), %edi       # This should be the string pointer
        pushl   %ecx
        pushl   %edi
        pushl   $output
        call    printf
        addl    $8, %esp
        movl    $0x255, %ecx
        movb    $0, %al 
        repne   scasb
        popl    %ecx
        loop    loopargs
    movl $1, %eax
    movl $0, %ebx
    int $0x80


px Language - Speed Tests


In order to more fully understand how I'm going to implement the translator from my imaginary programming language, I have written a few direct translations from px to assembly. My thinking is that if the language doesn't rely on the abstractions provided by the "compile to C" interpreted languages, I should be able to end up with a systems level language with the clean syntax of python, ruby, et al.

My first example is to calculate the sum of a large list. Here are two versions in python.

UPDATE!!! After trying a few more versions, I realized that my loop counters were off in every example. I had made the silly python mistake of forgetting the range of range. range(0, 123456789) = 0,1,2...123456788. And I had subsequently propagated that mistake into my C and Assembly versions, producing the wrong answer in every case, sometimes very fast! Lesson learned: Check your math!

# - calculate 1 + 2 + ... + 12,345,678 = listsum

listsum = 0
for f in range(0,12345678):
    listsum = listsum + f
print "The result is " + str(listsum)

listsum = sum(range(0,12345678))
print "The result is " + str(listsum)

And here's what it might look like in px.

print listsum buildlist 12345678

But, of course, no library functions exist yet, so I'll spell out how the functions listsum and buildlist would be defined.

n... buildlist size, next 0:
    next next + 1
    n next if next < size
n listsum list...:
    break if not list
    n n + list
    continue True

buildlist is defined as taking one argument, size and producing a list, one item at a time. Listsum consumes these items and produces a final value when the whole list has been read. All items are passed as two 32-bit values, [type/status] and [value/pointer]. Each operation checks the status flag to check if it is receiving a valid object and what that object is exactly. The buildlist function uses this fact to push a false object onto the stack when it reaches "size". This tells listsum that there are no more values to be read. In assembly this is what the code structure looks like in simplified form:

list_size:  .int 12345678
l_sum:     .int    0

push $1
push list_size

pop list_size
pop edi            #using edi as the status flag
mov 0, ecx    #and ecx for the counter
    compare list_size, ecx
    cmovae 0, edi   #if above, set edi to 0 (false)
    add 1, ecx
    push edi
    push ecx
        pop eax
        pop edi
        cmp 0, edi
        je end_listsum
        add eax, l_sum
        jmp buildlist
    print l_sum

In the actual implementation, I changed the add to support a quadword because the results get large quite fast, but this gives you the idea.

Is It Fast?

Well, I knew it would be fast, but this is a pretty large list, the code between buildlist and end_listsum has to run over 12 million times to calculate the sum, this is what I got when comparing the two python versions and my assembly version:

$ time python
The result is 76207876467003

real 0m15.379s
user 0m14.819s
sys 0m0.557s

$ time python
The result is 76207876467003

real 0m8.123s
user 0m7.476s
sys 0m0.647s

$ time ./listsum
The result is 76207876467003

real 0m0.275s
user 0m0.273s
sys 0m0.000s

That's pretty blazing fast if you ask me! But I was put in my place when I ran the C version which produced these results:

time ./f_sum3
The answer is 76207876467003.000000

real 0m0.123s
user 0m0.120s
sys 0m0.000s

I used a floating point double for the list sum, so maybe that's why C was faster. Still, if we use C as the baseline we have:

C       1
px      2.2
Py2     66.04
Py1     125.03

Not bad for a start. Now I'm off to dig through the compiled C code to see how it should be done...

UPDATE #2 - I've realized that there is a quite simple algorithm to solve this particular problem and that is: (n/2) * (n+1). This simple equation eliminates the loop completely making the calculation trivial. The updated python version runs in 0.038s and the C version runs in 0.002s producing the, now correct sum, 76207888812681.


px Language - Parsing Challenges


After spending most of the day investigating parsers, lexers and compiler compilers, I've come to the conclusion that my language doesn't really need these just yet. I've really only outlined three syntactic rules and two structural ones, and these cover all the ground I can see in front of me.


1. Right to left evaluation, except inside parentheses:

z  y if (y > x)
z  x if (y 
2. Right to left definition of block header line:
z function z, y:
   z do_something y
3. Comma seperated values are globbed together into an array.
process_list x, y, 12, 72, "Hello World!"

That's basically it for the syntax, where it gets interesting is namespaces and typing.


Every code block defines it's own namespace by default. This means that every block of code is explicit in defining what values it is using. Here's a trivial block which takes two operands and produces another:

.z a_function .z, y:
   .z y + .z

The ".", and the lack thereof, are the essential parts when it comes to namespaces. You might have seen the dot syntax in other languages (my_array.append()) and it's not really that different in px, except that referencing variables is a two way street. a_function is declaring it's own namespace under the main program and thus becomes main.a_function. That's fine, everything in the main namespace can access it directly by it's bare name and we can keep stacking them just like in other languages.

But the trick here is the preceding '.' on the variable name z and the lack of it on y. What's actually going on here? What happens is that the function is defined with concrete references to the z in the parent namespace and one reference to a y which does not exist. This becomes a unary function, a partially applied function and is never called until it is supplied with a y. When it does get called with a value, the z in the parent namespace gets updated accordingly. This function might be more appropriately called "increment_z", let's see it in action:

.z 10
increment_z  1
print z             >>11
increment_z  8
print z             >>19

A standard for loop imports all names, but it does so explicitly in it's function definition. "Hold on," you might ask, "it's function definition???" How does a for loop have a function definition? Don't other languages define this as built in to the language? The answer is yes, but in px I have decided to expose all the gory details of language design to the programmer, and only hardcode the bare essentials. This is roughly how the standard loops are implemented as blocks:

.* loop .*, _start, _end:
   break _end condition
   continue _start condition

The _start and _end tags are handles for the final assembly language implementation. The * wildcard states that any and all of the parent namespace will be accessible. This block definition has no pre-determined outputs or effects and so it's considered a function template. If called, the break and continue expressions will only be included if their conditions are met. Here's how that might look:

   break if .x 

Loop doesn't actually control the looping, the statements within it do. We could have omitted the break statement and used the condition of the continue to control the loop. Notice again that this block is a fully defined namespace and all external references must be used accordingly.

To summarize namespaces, block = namespace = object = method = class = control mechanism = symbol. If a block has fully defined inputs and outputs, it is treated just like any other literal value in the flow.


I've stated that there are two structural elements to my language: Namespaces and Types. Well, I kind of lied: there's only one types are also implemented functionally, but I haven't worked out how and how much of the checking can be done in the final assembly code. The general idea is this: values that aren't known at compile time are put on the heap and indexed with a hash table. Values that are know (by single literal assignment, or explicit typecasting) are put on the stack / data segment. Type statements are just like any unary operator:

x number 225.993
y int 235
z string "Please assign me to z!"

They go right next to the value being assigned as a check for the correctness of the data being passed to it.


px Language

In my studies with assembly language, a couple of things have occurred to me: 1. Assembly syntax is SIMPLE. 2. Instructions, registers, stack pointers, etc. are incredibly confusing. What i mean by the syntax being simple, is that it is completely linear. If the code jumps around it explicitly tells you where it's jumping and why. All lines can be understood as self-contained statements and the only structure to the program is the structure you give it. With this in mind, I have set out to design a new language based on this syntax. The language will be functional and type-safe like Haskell, but it won't have ANY built in syntax. I have begun to build a parser in Python which does the px to asm conversion. It's very simple at this stage, but should work. The language is read, for the most part, right to left with the leftmost term(s) being the terminal element. The only exception to the rule might be infix operators, because I'm not sure if many would take up a language if they had to learn reverse-polish notation. The Basics Here's a simple example of naming symbols and comparing them.
x, y  20, 15
z 42
z x if x > y
z y if y > z
print z
x, y and z are assigned the values 20, 15 and 42. y and x are pushed onto the stack and '>' pops them and compares them, putting a 0 or 1 on the stack. The if statement takes two operands, the x and the boolean result of the '>' operation. It then pushes onto the stack x and [0/1] (secret rule #1). Secret rule#1: Values are always stored in two parts, a value and a flag. If the flag is false the assignment doesn't happen. I have chose to omit the assignment operator, because all evaluations logically flow right to left. You will see the benefit of using infix operators if you reduce this operation to it's RPN form, with parens added for clarity: z (if ( x (> y x))) The > and other mathematical terms can be understood with some practice in RPN, but the if statement is not very intuitive at all without infix notation. Another curiosity that needs addressing is that since this is stack-based assignment, the first assignment "x,y 20,15" just adds the numbers 15 and 20 onto the stack and then pops them off making y=20 and x = 15. Not the preferred functionality! Functions Simple enough for basic expressions, how do we implement more complex functions? I've carried the same logic into function expressions. Functions always produce the left-hand value based on the right-hand input, but you add a code block below the statement line. This is how it looks in practice:
x 15
y 12
.x some_function .x, .y:
   .x sum(.x, .y)
print x
I almost went with the Python-esque whitespace-significance, but have decided for now to close blocks with a final colon. The function's header defines it's inputs and outputs. The function takes two values, x and y, passes them through the function block and produces x. There are no return statements, because the output symbol is explicitly given in the header line. Okay, the syntax is simple enough, but what can you do with it, and what are the leading periods all about? That's where namespaces come into play... Namespaces Each block defines it's own namespace. The previous function declared inputs of .x and .y. These are concrete references to the parent namespace. The output was also a concrete reference, so the function was fully defined and executed to produce the new value of x. Here's an example that, although it looks very similar, is actually quite different:
x 15
y 12
m generic_function m, n:
  m sum(m, n)
x generic_function x, y
print x
This is more like normal function you would use, because it defines the function with generic inputs and outputs and then you use them on specific values. The function is only executed when called with some specific values. This opens the door for partially applied functions and the like. eg:
m part_func .x, m:
   m sum(.x, m)
y part_func y

m const_function .x, .y:
  print x, y
  m True
res const_function

.x defined_out m, n:
   .x sum(m, n)
defined_out 8 1024
print x
This is a simple but powerful way to implement a lot of the functionality of high level language with only one syntactic convention. One final note about namespaces is that the .* symbol references the entire parent namespace. This allows one to implement transparent code blocks like loops. Eg:
x 0
x_max 11
.* loop_block .*:
   continue .x < .x_max     print .x     .x .x + 1     loop True     : 
Because the input and output are fully defined, the code executes and can access any of the variables, functions etc. of the parent block via the dot syntax. The loop and continue functions control the flow of the block and can be used in any block. 'loop' is just a "goto $start if expression is true" statement and 'continue' is a "goto $end if expression is false" statement. This block first checks it's condition, breaking if it is false, does some more stuff and then loops back to the start unconditionally. Alternately, one might want to omit the 'continue' statement and do the condition check with the 'loop' statement. Every block will have a start and end tag that can be used in this manner. Objects Because blocks are self-contained namespaces, there is another possible use for them, classes and objects.
. some_object .:
   name "some_object"
   value 42
This block didn't specify any inputs or outputs. It is thus a concrete object which can be used as follows:
But maybe I'm getting ahead of myself! Stay tuned for more developments and please give suggestions on the name, I'm not sure how or why I came up with "px".


CompTia A+ - Exam Objectives

I've downloaded the exam objectives for the CompTia A+ certification, which includes two tests, 220-701 Essentials and 220-702 Practical Application.
I've also taken the practice tests on CompTia's site and got 6 out of 7 on the 701 exam and 5 out of 7 on the 702. As I guessed, my shortcomings are Microsoft centred. Since I have not owned and operated a Windows PC for several years now, this will have to be my primary study area in obtaining this certification. It's not that the subject matter is completely unknown to me, but the problem is that most of the time when I troubleshoot a PC I have no idea in the end how I solved the problem or if it was permanently fixed.
Maybe the better course would be going for the Linux+ certification instead...

Assembly Language - Development Environment

The development environment for assembly language outlined in this book is a bare bones, linux-based toolchain. There is no one-click "Build and Go" or "Build and Debug" options here. I have installed the tools on my Arch Linux backup system which I am using through ssh from my laptop.
Assembler: GAS (GNU Assembler, part of the GCC Package).
Linker: ld, included with gcc.
Debugger: gdb (wasn't installed, `pacman -S gdb` solved that).
Profiling Tools: objdump, gprof are included in the binutils package.
I also looked into setting up a development environment using Xcode on my mac. It is fairly trivial to set up a "Standard Tool" project and call assembly code, but the assembly code uses some different conventions on mac vs. Linux. I've decided to stick with the linux style used in the book, but there is a good overview of the basics of Mac assembler in the Mac developer reference.
Using The Assembler
So, a couple notes about using the tools. My first observation was that to know what a program is doing in assembly, you must learn to use the debugger, always compile with -gstabs. The book recommends two stage compilation, assemble and link, but I'm not sure why. A one stage gcc invocation guarantees(?) proper linking without having to explicitly name the library and the dynamic linker.
Example: Using as & ld when linking to a C library
as -o somefile.o somefile.s
ld -dynamic-linker /lib/ -o somefile -lc somefile.o
Compared to using gcc:
gcc -o somefile somefile.s
I think I'll stick with gcc for now. And including debugging symbols is straightforward as well:
gcc -gstabs -o somefile somefile.s
Using the Debugger
The debugger is not quite as mystical when used in assembly language. For the most part each line corresponds to a machine instruction, so you can follow along in the source code and view the results of each operation. When the debugger starts, it prepares the code for execution and then awaits your instructions. If you simply type 'run' it will execute the code to the end. To see what the program is doing, you must specify a breakpoint: 'break *main' stops execution at the start of the main block. From here we can step through the program with the 'step' instruction. Some interesting things to be looking at during execution are the registers 'info registers', data values 'x/d &value' and the stack 'info stack'.
Compiling C source to Assembly
Another good resource for studying assembly language is to write the program in C and compile it with the -S option which outputs the assembly equivalent of the C code. This may also be a good way to fine-tune your C code, but for the purposes at hand it's simply a learning exercise, and I don't plan on doing better than GCC any time soon!
Source Text: Professional Assembly Language (Blum, 2005)

Writing and the Environment - Exercise 2a

All Assignments
Tarbela Dam in Pakistan - Cost vs. Benefit
Water resources are one of the primary economic and social concerns in developing countries. The construction of large dams serves to manage flood damage, generate electricity and create stable water supplies for irrigation and general consumption. The construction costs of these massive projects are enormous, and the immediate benefits are great, but the hidden long term costs and benefits are harder to evaluate. The Tarbela dam faces the long term struggle with the diminishing returns of such a massive project.


Exercise 1b: Writing and the Environment

Previous post
The four summers I spent tree-planting were the closest I have been to nature in my adult life. I grew up on an acreage in small-town Saskatchewan but moved away at age 14 and have lived in a town or city ever since. In a way, the summers were an escape to a place that had the simplicity of my early years, but the location was more expansive and rugged and the work was backbreaking.
It was a situation that no one could remain detached from, it required you to fully engage in the work at hand to make it through the long days. Being piecework, it also required motivation and determination to make the time at work a profitable one. Many young college students would come out hoping to make amazing money only to run into the harsh reality that they simply didn't have what it takes, mentally and physically, to do well at the job.
But it wasn't all grueling labor, there was a great sense of camaraderie between coworkers. It was a struggle, but it was a struggle that we all shared. And then, of course, there were the moments when the setting commanded your attention; when the work and the worries would melt away in the face of some natural beauty. Waterfalls, rushing rivers, massive oak trees and, at times, the most profound isolation.
It is these times that stick with me when I think about those summers. Somehow by a trick of selective memory, all the toil and pain and lost wages melt away and you are left with some of the deepest friendships and profound encounters with the natural world.
My encounter with the moose is one of those memories that can't be easily summarized. It was not simply terror that I felt, nor complete awe at the power of the beast although I did feel these things. It was something else that is harder to describe. It was a moment where I was pulled out of myself. All of the day to day thoughts, feelings, opinions and ideas melted away and I stood before the moose as an empty shell. The moose, myself and the space in between us were the only thing that existed in that moment.
If there is one thing that this experience taught me, it's that I'm not alone in this world. There are forces greater and smaller than me that are continually in tension. My personal narrative may only be a tiny blip in the larger story, but it is a story that I am connected to and must be engaged in.

Assembly Language - Instruction Codes

Source Text: Professional Assembly Language (Blum, 2005) Chapter 1:
This book begins with a brief overview of CPU instruction code handling, which is still a bit of a mystery after reading it but I will try to describe it to the best of my abilities. Here's a quick sketch of how the CPU processes instructions:
Instruction code <- Instruction Pointer <- Memory 
   Data <- Instruction code (Data Element, opt.)
   Data <- Registers
   Data <- Data pointer <- Memory 
Each instruction code can perform operations on data from the registers, main memory, or it's own 1-4 byte data elements. The actual instruction code can be from 1 - 17 bytes long, the only required byte(s) being the opcode which tells the processor what operation to perform. The other bytes of the instruction code specify modifiers for the operation and data elements (0-4 bytes) for the operation. Data registers are essentially memory locations on the processor itself. This makes them the fastest way to store bits of information, but the space is very limited (x86 defines eight 32bit registers). Assembly language adds a layer of abstraction to this by adding mnemonics for the opcodes.
89 E5
83 EC 08
Translates to:
 push %ebp
mov %esp, %ebp
sub $0x8, %esp
It also lets you declare and name your data.
 .long 150
 .ascii "This is a test message."
 .float 3.14159
In summary, assembly language may look extremely cryptic, but it is at least human-readable and it gives the programmer access to the core of a CPU's processing. So here's my first assembly language program:
# cpuid.s Sample program to extract the processor Vendor ID
.section .data
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"

.section .bss

.section .text
.globl _start

movl $0, %eax
movl $output, %edi
movl %ebx, 28(%edi)
movl %edx, 32(%edi)
movl %ecx, 36(%edi)
movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $42, %edx
int $0x80
movl $1, %eax
movl $0, %ebx
int $0x80
Which I assembled and linked with the following commands:
$ as -o cpuid.o cpuid.s
$ ld -o cpuid cpuid.o
And the output:
$ ./cpuid
The processor Vendor ID is 'AuthenticAMD'


Bluebrain Project


This is not directly related to my studies at the moment, but I will be keeping my eye on this project.

Bluebrain | Year One from Couple 3 Films on Vimeo.

Although much more lofty and ambitions than what I would like to be involved in (for now, anyway!), the project is interesting in it's medical focus of the benefits of brain modeling. I have noticed that when the focus is computation, the immediate payoffs are better (ie. interesting algorithms, programming structures), but we always lose sight of the bigger pictures and run off into premature optimization. The pocket calculator does computation faster than any brain, but it will never get beyond its programming.

Exercise 1a: Writing and the Environment

In the northern communities of British Colombia, Canada, there are strong seasonal cycles at work and with them is a seasonal movement of workers moving through the territory. The logging industry is big business and the workforce associated with it is diverse, rough and above all, temporary.
I was working for a tree-planting company based in the town of Prince George, BC where we would move through the remote logging communities, setting up camp for days or weeks at a time in the middle of the wild. From these remote campsites we would drive to even more remote locations, and from these we would often hike to even more remote locations.
It was after one such hike that my planting partner, Scott, and I found ourselves in a completely secluded and silent valley. It was, of course, not completely silent but the sounds of the forest have a way of amplifying the lack of any human interference or habitation. This particular silence is one that tree-planters know well and must come to terms with if they are to maintain their composure and sanity through the long days and months of their work term. It is the silence that wilderness hikers crave in the moderation of a day or weekend hike, but that becomes something else entirely over the course of a summer.
Each group of planters has a "cache", a home-base where the boxes of trees are stored under a tarp which they return to many times a day to fill up their planting bags with trees and then return to their piece of land. This cache is usually on a road or track that is accessible by ATV or sometimes just a clearing that is accessible by helicopter.
On this particular day I was returning to my cache alone, having finished my work before Scott and ready to "bag up" and get back out there. As I was filling my bags with trees I heard a rustling in the trees, the kind of slight snapping and movement that could be wind or could be any number of forest creatures making their way through the dense vegetation.
But it was enough to get my attention. I looked towards the tree-line and caught sight of a large brown mass emerging into the clearing about 10 m. from me. I did the only thing that comes naturally in this situation and completely froze. I stood half hunched over, holding a bundle of trees with my eyes locked on this beast that emerged from the forest and it, as it stepped up onto the ATV track that I was standing on, had it's eyes locked on me.
Having seen many moose that summer already while driving, I had formed a mental picture of these creatures as being awkward and comical. Moose have very long legs and a gigantic head which makes them one of the least graceful creatures in the forest. Where a deer might leap a fence or gap with startling ease, the moose is forced to crash it's way through with little ease or grace. They tend to hang out in shallow swamps or vegetation and we thus coined the term "swamp donkey" to refer to them.
What I saw in front of me was nothing like a "swamp donkey", there was nothing comical or ungraceful about it. This was an animal of raw power and stature that commanded respect. In it's eyes there was no savagery or malicious intent, but instead something much more frightful and commanding: indifference. It made no threatening or defensive gestures, it simply stared me down. And in that stare I felt the fragility of my own defenses, the entirety of my physical inadequacy in the face of this dominating beast.
After moments that seemed to stretch into infinity, the moose gave a slight, snorting grunt and lumbered back into the dense forest with sure footedness and without hesitation or care. I finally took a breath and the world seemed to come back to life around me.
In that moment I knew that my experience of the world had become a bit more complex and a bit simpler at the same time. It is a general axiom of our media culture that detached observation is completely different than "being there", but the actual depth of the disparity is not truly felt until one has come face to face with it. When the object of curiosity and amusement becomes one of respect and humbling.

Course Planning

After some research and thought into the best course of study I've begun to sketch out the direction of my self-study. In keeping with the idea that the courses should start general and gradually move to more specific areas, I've outlined some general topics to begin with. These are not exactly the primers that university would begin with, but that's one of the benefits (and/or downfall) of choosing one's own path.
I would like to keep a fairly modular and flexible structure to my studies so I think that, for now, I will do three courses at a time. The first three I have decided on have been chosen for specific reasons to do with a well rounded education. Each course will be referenced by a tag in my subsequent blog posts.
Most technical degrees start with some humanities courses, and since I am blogging my education, it would be a service to myself and my readers to hone my writing skills.
I will be using the assignments from MIT OCW "Writing and the Environment" as the basis for this course. As the assignments will not be marked, it is essentially just practice but I will be watching the comments section, and if some kind readers would provide me with critiques, comments or suggestions, I will be forever grateful.
Again the starting point for most degrees of this kind is some general computer science course. Having a fairly good grasp of the basics, I have decided to go a bit different direction with my baseline programming course. I will be diving into programming with assembly language.
Assembly language is about as "bare metal" as you can get when it comes to programming and I think it will be a fruitful course in exposing the underlying architecture of computer systems. I plan to do a final project in this course, but I'm not quite sure what that will look like. My first steps will be to get through the assembly language text I already have and implement some of the algorithms that I have only done in higher level languages (python mainly).
Having identified documentation and notes as one of the possible downfalls of personal education, this blog will fulfill that role. Since google docs have enabled uploading of any file, I will publish all source code and notes from each project to this blog.
I haven't yet determined which certification to prepare for first, but I think that the CompTIA A+ is probably the best starting point. I would welcome any advice from people who have had experience with this as I'm into new territory on this one.


Studying Outside The Classroom

After 12 years of working in the construction industry and being a closet geek, I have resolved to work towards aligning my career with my passion. My passion being electronic systems and their theoretical and practical applications. But now that I've made that resolution, I have hit a roadblock in terms of what that looks like in reality.
The most sensible starting point would, of course, be a university degree. I wholeheartedly believe in the value of formal and structured education, but at this point I've run a successful business; dealing with clients and contractors and I've always been committed to having a well rounded knowledge of history, literature and arts in addition to my hobbies of computer programming, music and mechanical design. So, with this experience behind me, I'm having a hard time justifying spending four years and a considerable amount of money on something that may simply get me past an HR department one day.
Of course, it could always be the case that I am deluding myself: believing that my experience is far beyond what it actually is. In researching the value of degrees in technology, I have read many comments that a degree, while not a guarantee of specific practical capabilities, ensures commitment to a goal, team skills and a well rounded educational base to build on. Other comments stated that programmers without degrees are often "lone-wolf" type characters who, though intelligent and capable, are not suited to working well with people and produce unmaintainable code and/or undocumented code. I get this. But it is these types of comments that once again make me realize the value of my prior experience. I have dealt with employees, business partners and contractors where the very same issue is a prime concern though it looks different in another context.
That being said, I do not consider the issue of structured education to be closed at all. The ancient greek aphorism "Know Thyself", is of vital importance in how you navigate life and one of the best ways to explore your capabilities is through unbiased and objective assessments of your skill level in many domains. At age 21, I took a Level 3 First Aid course and I failed miserably. I had always relied on my intuitive intellectual capabilities to reason through any problem I was faced with. This course tested for the ability to memorize time-sensitive and very specific sequences and perform them instinctively in a high pressure situation. And in analyzing the wreckage that was my exam, I found that I was simply not capable of this skill. It was the first time that I have come up against a task that showed the depth of my inadequacy in a certain area and I caught a glimpse of what the greeks meant by "Know Thyself": everyone has shortcomings in some areas and if you don't know what yours are, you are living a fantasy.
And this is where certification courses come into the picture. Although I've heard mixed reviews of the value of these courses as well, I think that they would be a valuable tool in judging my competency and fluency in technical topics. I certainly won't use them as the absolute yardstick of my education, but more as a tool to gauge the effectiveness of my self-education.
Course Materials
The second goal of my studies is to gain a wide knowledge of subjects which may only be tangentially related to my primary goal. This is where the broad and intensive MIT Open Courseware curriculum comes into play. The courses that i have already begun in mathematics and logic have inspired me to continue on this path. Although they do not grant any kind of recognition of courses completed, I think that the practical benefits of broad knowledge base are their own rewards.
Research Goals
In addition to certification and general course studies, I plan to do research projects and papers, publishing my results to this blog. If this sounds like I'm just imitating schooling and pretending to be a grad student, you're right but I would suggest that it's the other way around. The way grad school is structured is to mimic the way "real" intellectual advancement and research is done. You don't have a specific list of requirements to check off or attendance schedules, but you will be judged on if it is and original and substantial contribution to the field.