Procrastination

Code Comments Full Code Commentary
; procrast.asm
; Zach Tomaszewski, 01 May 2006

	.MODEL small
	.586
	.STACK 100h

	.DATA
to_do		DB	1, 2, 3, 4
list_end	DW	$
task		DB	?

	.CODE
Procrast PROC

CHECK_LIST:
	lea	ax, to_do	;If the to-do list is empty, we're DONE.
	cmp	list_end, ax
	jle	DONE

	cmp	[to_do], 0	;If the first item in the list is 0 (done),
	jmp	SHIFT_LIST	;shift it off the list.

DO_IT:
	movzx	ax, [to_do]	;Do the first item on the list by...
	push	ax
	call	complete	;passing it to the "complete" function...
	mov	[to_do], 0	;and then crossing it off the list (set to 0).

SHIFT_LIST:
	mov	al, [to_do]	;Save the first item of the list...
	lea	si, [to_do + 1]
	lea	di, [to_do]
SHIFT:	cmp	si, list_end	;then shift everything in the list down one...
	jge	REPLACE
	movsb
	jmp	SHIFT
REPLACE:
	mov	[di], al	;and put the first item back on the end.
	cmp	al, 0		;If the first item was done, cross it off
	jne	SHIFT_DONE	;(that is, shorten the list).
	dec	list_end

SHIFT_DONE:
	jmp	CHECK_LIST	;go back and check the list for more to do

DONE:

Procrast ENDP


Complete PROC
	;code to process a single-byte task here
	ret 2
Complete ENDP


Main	PROC
	mov	ax, @data
	mov	ds, ax
	mov	es, ax
	call	Procrast
	mov	ax, 4c00h
	int	21h
Main	ENDP

	END Main

Procrastination is written in MASM assembler. Assembler (or assembly code) is a very low-level language in that it is only a step away from machine code--the strings of 0s and 1s that the computer actually executes. There is nearly a 1-to-1 correspondence between the statements in assembler and the bytes created when the code is translated (or "compiled") into machine code.

The effect of running Procrastination is that the to_do list simply gets cycled through, like this:

1, 2, 3, 4
2, 3, 4, 1
3, 4, 1, 2
4, 1, 2, 3
1, 2, 3, 4
2, 3, 4, 1
...

This process doesn't stop. The list is never shortened, and the program never ends.

The reason for this behavior is because, in the CHECK_LIST section of code, we do this:

	cmp	[to_do], 0
	jmp	SHIFT_LIST

First, we compare the first item in the to_do list to 0. Then we jump to the SHIFT_LIST, regardless of the results of the comparison. This last line should actually be:

	je	SHIFT_LIST

That is, only jump to SHIFT_LIST if the previous comparison found the two operands to be equal. If they are not equal, then the code continues with the next instruction, which would be the DO_IT section of code.

What's interesting here is that the difference between an effective program and one that spends its time procrastinating is only a "bug" of a couple letters. At this low-level, fixing this bug changes the resulting executable program by only a single byte. There's not such a difference after all, perhaps, between us procrastinators and those productive people! It's only the difference of a byte that keeps us from getting down to what it is we're supposed to be doing.