📜 ⬆️ ⬇️

Assembler Intel-4004 - for fun

intel-4004 cpu

Recently, I was shown assembler emulators for the Intel-4004, and I was stuck for a while. This is the "grandfather" of the current processors - if you believe the Wikipedia article - the first commercially common microprocessor.

It is unlikely that it can now be used for some serious purposes. But just to break my head (instead of brainf ** k) - well, that's what I did. The main thing is that it is 4-bit and the set of commands is rather small (before that I knew only a little bit of the x86, at the painful institute course).
')
Below is a free translation-retelling of this assembler instruction for the Intel-4004 - and brief remarks about my attempts to write something on it.





First about Emulators



I think to see the Intel-4004 alive, and even more so as part of some working device in our time is not easy. For experiments, therefore, emulators remain:


Immediately make a reservation - I got acquainted with this topic precisely by the guidance of the authors of the second emulator (and the translated instruction refers to it) - but I only tried its online form, so I apologize in advance for possible errors and inaccuracies in the translation. The first emulator is more convenient for me to debug (although the instruction to it would not hurt either).



About Architecture



From the point of view of me as a programmer, the architecture is very simple. We have:



In fact, there is still an invisible instruction counter, a pointer to read / write instructions to the RAM, and a small call stack.

Most logical and arithmetic instructions work either with a battery or with one of the registers.



First try



The first two instructions that offer to remember - ldm to load the number in the battery and xch - to exchange the battery and register.

Yes! It does not have instructions for copying the battery to the register (although the reverse ld instruction is present).

Here is the program of these two instructions:

ldm 5 ;  5   xch r2 ;    R2 


It is also proposed to see how this works in the emulator using such a link — all you need to do is to click the “Run” button — and the contents of the registers will appear in the Output field after the code is executed.



Arithmetic



This grandfather doesn’t know how to share something — even multiply. As I understood having played with him a little bit, because of this, even a translation between the 10th and 16th system becomes very difficult. Therefore, it seems that it is proposed to count in BCD - store decimal digits in 4 bits and perform special actions on them to correct decimal results.

Add add - adds the specified register to the battery. In addition, the carry flag is added (so it is useful to reset it first with clc ). After the addition, the carry flag is set if there was an overflow.

For counting in 10-hour numbers after the addition, you can execute the daa instruction - in fact, if the number in the battery is from 10 to 15, subtract 10 from it and set the carry flag.

 ;    R6:R7 fim r0 $67 ;  6  R0  7  R1 ld r0 ; 6    clc ;   add r1 ;  ,   13 daa ;    3      ;      R2:R3 xch r3 ;    R3 ldm 0 ;    ral ;      xch r2 ;    R2 


I do not know if there is a way to write down the transfer flag to the register. Check the code can be on the link .

Subtraction works like. In the Hex format there are no problems with it, the transfer flag is used as a loan. Unfortunately, subtraction in BCD requires a slight brain strain before the meaning of the instructions becomes clear - so I’ll skip it for now.

There are iac increment and dac decrement instructions for the battery, a separate inc increment for registers, and also instructions for battery inversion and cma and cmc transfer .



Branches, transitions



For structural organizations like conditions and cycles, we have a few instructions.

Unconditional transition jun - just to a given label.

The jms subroutine call is the same by the label (but the return address is pushed onto the stack). Return instruction bbl which takes a number as a parameter - writes it to the battery. We can not say that it was convenient - it turns out, an arbitrary result of calculations in the battery can not be returned.

The conditional jump instructions can determine whether the carry flag is set / cleared, or the battery is equal to / not equal to zero.

 jcn c0 ... ;    = 0 jcn c1 ... ;    = 1 jcn az ... ;    = 0 jcn an ... ;    <> 0 


There is another interesting isz instruction - it increases the specified register by one.

For the demonstration, I will write a program that squares the number loaded into the battery:

 ;      ACC,    R2:R3 ldm 5 ;   , , 5 xch r0 ;      R0 ld r0 xch r1 ;    R1 -     repeat: ld r0 ;      R0 clc add r3 ;      xch r3 ;     R3 jcn c0 nocarry inc r2 ;  R2     nocarry: ld r1 ;     1 dac jcn az finish ;     xch r1 ;      jun repeat ;      finish: nop 


Demonstration of the link .



Conclusion



There are several more instructions for loading data, working with RAM and code memory. In addition to them, the offline emulator has a couple of “magic” calls that allow you to read-write the console - this makes it possible to write something like scripts to handle strings, etc. - it is clear, however, that this does not apply to the original systems using this processor.

But I see that quite a lot of text has already happened, although I managed to retell only about half of what I read. It is probably better to stop at this and, if you are interested, write a supplement as a separate article.

Links to original instructions:

Source: https://habr.com/ru/post/269821/


All Articles