⬆️ ⬇️

I8080 emulator on bash

Today they write xonix, and tomorrow they will write a separate operating system with a framework and a DBMS on the bash.



Finally, tomorrow has come. In bash (after some finishing) you can run a serious OS, for example, CP / M. And for CP / M there is definitely a DBMS, compilers, and more.





')

Why it is not necessary and why it is necessary to do emulators on bash, a working i8080 emulator on bash and a few tips to speed up the work of bash scripts -



Why not to do emulators on bash



Bash works leisurely. Even for a processor as simple as the i8080, the emulation rate is unlikely to be at least 1% of the real. On my Celeron with a frequency of 2.2 GHz, the emulator operates at a speed of about 100 operations per second, while the real i8080 processor at 2.5 MHz performs 600 thousand operations per second.



Another important problem: in bash it is impossible to work with binary data. If you want to output a symbol with the code 0x01 to the port or read from the file, then bash is clearly not the language you need.



The third problem. Developing an emulator is not an hour or two task. You should not write an emulator without an editor with syntax highlighting and without debugger. When I started “composing” my emulator, I thought: “Oh, you need to do only 84 teams! What nonsense! ". Reaching the 51st operation code, I finally realized that the command! = Operation code, and that another 200 codes had to be implemented. If I immediately took into account that the operation codes for two hundred, I would not write an emulator. And since I started writing, I had to finish it.



Why bash emulators



Then, that is a super duper mega cool. Because it gives you a lot of bash programming experience. Then, the programs in the emulator will be executed very, very slowly, and it will be possible to keep track of the change in flags and registers.



Tips for speeding up bash code



The speed of code execution for the emulator is critical. If you want your bash script to run as quickly as possible, then:



Calling expr or bc in a loop can slow down your program several times.

$ time ( for ((i = 0; i < 100000; ++i)); do echo `expr 1 + 2` ; done ) real 0m17.000s user 0m13.261s sys 0m8.061s $ time ( for ((i = 0; i < 100000; ++i)); do echo "$(( 1 + 2 ))" ; done ) real 0m3.980s user 0m2.371s sys 0m0.237s 




Reading files into an array with the readarray command sometimes gives a huge gain compared to the read command in a loop (depending on the file length), and certainly looks much nicer.

 $ time ( for ((i = 0; i < 10; ++i)); do while read line ; do rom[${tmpcnt}]=$line ; (( ++tmpcnt )) ; done < bas.e80 ; done ) real 0m6.888s user 0m5.516s sys 0m0.336s $ time ( for ((i = 0; i < 10; ++i)); do readarray -t rom < bas.e80 ; done ) real 0m0.146s user 0m0.048s sys 0m0.004s 




The increment command is faster than the addition command.

 $ time ( for ((i = 0; i < 100000; ++i)); do a=$(( a + 1 )) ; done ) real 0m4.489s user 0m3.692s sys 0m0.108s $ time ( for ((i = 0; i < 100000; ++i)); do (( ++a )) ; done ) real 0m4.053s user 0m3.296s sys 0m0.140s 




To translate numbers from hexadecimal to decimal, I used my function:

 hex2dec () { uw=`expr index "0123456789ABCDEF" "${1:0:1}"` lw=`expr index "0123456789ABCDEF" "${1:1:1}"` res=$(( ( ${uw} - 1 ) * 16 + ${lw} - 1 )) } 


Given what I said about expr, you can guess: this function did not work very quickly. Good mkot told me a simple way to transfer numbers from one number system to another:

 hex2dec () { define -i res res="16#$1" } 


Thanks to this replacement only, the emulation speed has increased three times. Therefore, read the Advanced Bash-Scripting Guide more carefully, and do not invent brake bikes.



Final advice. Try not to use $ signs where it is possible, because US dollars negatively affect the free shell:

 $ time ( for ((i = 0; i < 100000; ++i)); do a=$(( $a + 1 )) ; done ) real 0m5.155s user 0m4.828s sys 0m0.088s $ time ( for ((i = 0; i < 100000; ++i)); do a=$(( a + 1 )) ; done ) real 0m4.489s user 0m3.692s sys 0m0.108s 




I8080 emulator



The development of the emulator took about 8 hours. Probably, it was not without bugs (I am especially worried about logical functions), but in general it works, and quite successfully. I applied some optimization tips in the emulator, and some did not, with the hope that additional changes would speed up the execution of programs in the emulator slightly. Unfortunately, the emulator does not support work with ports and interrupts, but it does have the function “Display a character on the screen” from the Monitor program for Radio 86RK .



Unfortunately, the emulator source code for today (June 1, 2017) is lost.



Run as follows:

 $ ./emu.sh program.e80 




The screen will display the contents of the registers and flags.



Programs should be written in hexadecimal, one byte per line.

An example of a program that performs an empty loop 256 times:

 3D C2 00 00 76 




Lovers of programming in machine codes will certainly help a brief guide from the virtual computer museum.



Oh yeah, about CP / M. Of course, you can launch it. But loading the OS and printing an invitation to the screen can take a few minutes.



That's all for today. Happy all hacking.

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



All Articles