Intel 4004 Microprocessor Assembler
source code:object code:


listing: $000 hex code:




What Is The as4004 Assembler?
The as4004 assembler is a very simple 2 pass assembler of the Intel 4004 microprocessor. The full code of this software is completely written in JavaScript, so it should be able to execute on whatever platform with the internet browser and implemented JavaScript interpreter.

Features Of The as4004 Assembler

Running The as4004 Assembler

Quick Start
This part of the desription is for those of you who want to see the as4004 assembler in action. It can be easy to realize. In the frame bellow is a simple examle of Intel 4004 microprocessor program - adding two 4bit numbers. The FIM instruction is used to initialize the pair of registers R0=2 and R1=A. The program then loads R0 into the accumulator, adds the contents of R1 to the accumulator, and then uses the XCH instruction to exchange the values of R1 and the accumulator, which stores the addition result into R1. The program then enters an endless loop, written as a JUN (jump unconditional) instruction that jumps to its own address. Just copy this code and paste it into the "source code" pannel. Next click the "generate code" button. If everything goes right in "object code" pannel should appears the result code in HEX format.

; add two 4bit numbers on the Intel 4004
;
	FIM P0, $A2	; initialize: R0=2 R1=A
	LD R0		; load R0 into accumulator
	ADD R1		; add R1 into accumulator
	XCH R1		; and store in R1

DONE
	JUN DONE	; endless loop as end of program


Syntax The Assembler
Instructions are mnemonics followed by an (optional) modifier:
	OP CODE	        MODIFIERS
	-------		---------
	OPC		none
	OPC D		data
	OPC R		register
	OPC RX		register pair
	OPC R, AA	register, address
	OPC P, DD	register pair, data
	OPC C, AA	condition, address
	OPC AAA		address

    Where 

	D   is a 4 bit data
	R   is a register address
	P   is a pair register address
	AA  is a 8 bit address
	AAA is a 12 bit address
	C   is a condition
  	[0-9] 	.... 	decimal
   	$[0-F] 	.... 	hex
  	%[01] 	.... 	binary
  	0[0-7] 	.... 	octal
Identifiers must begin with a letter [A-Z] and contain letters, digits, and the underscore [A-Z,0-9,_]. Only the first 6 characters are significant. All identifiers, numbers, opcodes, and pragmas are case insensitive and translated to upper case. Identifiers must not be the same as valid opcodes. The special identifier "*" refers to the program counter (PC).
  Examples:
    * = $100	    ....   Set start address (PC) to $100.
    LABEL1  LD R5   ....   Define LABEL1 with the address of instruction LD.
         JUN LABEL2 ....   Jump to address of label LABEL2.
    STORE = $080    ....   Define STORE with value $080.
    HERE = *	    ....   Define HERE with current address (PC).
    HERE2	    ....   Define HERE2 with current address (PC).
Pragmas start with a dot (.) and must be the only expression in a line:
    .BYTE BB 	.... 	Insert 8 bit byte at current address into code.
    .END 	.... 	End of source, stop assembly. (sign '$' is an option)
  ; comment 	.... 	Any sequence of characters starting with a semicolon
			till the end of the line are ignored.
The assembler doesn't need any special formatting with the following exclusion:
- there must be white space between a label and a opcode and any operands.
Only one instruction per line is permitted.


Code Example
This code example is taken from "MCS-4 Micro Computer Set" - Intel Corporation 1973
The example performs a logical "and" function on the data at two 4bit ROM input ports and display the result at a RAM output port. This program demonstrates how the i4004 accesses its ouput and input ports. It also shows several basic instructions (e.g. load immediate), subroutines, jumps, etc.

; four bit "AND" routine on the Intel 4004
;
START	FIM 4P, 0	; LOAD ROM PORT 0 ADDRESS
	SRC 4P		; SEND ROM PORT ADDRESS
	RDR		; READ INPUT A
	XCH 0		; A TO REGISTER 0
	INC 8		; LOAD ROM PORT 1 ADDRESS
	SRC 4P		; SEND ROM PORT ADDRESS
	RDR		; READ INPUT B
	XCH 1		; B TO REGISTER 1
	JMS AND		; EXECUTE "AND"
	XCH 2		; LOAD RESULT C
	WMP		; STORE AT MEMORY PORT 0
	JUN START	; RESTART
	NOP
*=104
;			"AND" SUBROUTINE
AND	CLB		; CLEAR ACCUMULATOR AND CARRY
	XCH 2		; CLEAR REGISTER 2
	LDM 4		; LOAD LOOP COUNT (LC)
AND_3	XCH 0		; LOAD A, LC TO REGISTER 0
	RAR		; ROTATE LEAST SIGNIFICANT BIT TO CARRY
	XCH 0		; RETURN ROTATED A TO REG 0, LC TO ACC
	JCN CZ, ROTR1	; JUMP TO ROTR1 IF CARRY ZERO
	XCH 1		; LOAD B, LC TO ACCUMULATOR
	RAR		; ROTATE LEAST SIGNIFICANT BIT TO CARRY
	XCH 1		; RETURN ROTATED B TO REG 1, LC TO ACC
ROTR2	XCH 2		; LOAD PARTIAL RESULT C, LC TO REG 2
	RAR		; ROTATE CARRY INTO PARTIAL RESULT MSB
	XCH 2		; LOAD LC, RETURN C TO REGISTER 2
	DAC		; DECREMENT THE ACCUMULATOR (LC)
	JCN ANZ, AND_3	; LOOP IF LC NON ZERO
	BBL 0		; RETURN
ROTR1	XCH 1		; LOAD B, LC TO REGISTER 1
	RAR		; ROTATE B
	XCH 1		; RETURN ROTATED B TO REG 1, LC TO ACC
	CLC		; CLEAR CARRY
	JUN ROTR2	; RETURN TO LOOP
CZ=10
ANZ=12
$