A rare language - coding without an IDE, but with convenience

You can argue until you turn blue on the topic of IDE vs Notepad / VIM / Emacs. Exactly as long as the IDE is. However, you can easily stumble upon a language (or dialect) that you will have to use, and the IDE for it either does not exist, or only paid and expensive, or is already so outdated that it only runs in an emulator of a rare OS. But you need to work. Fortunately, there are universal tools that you only need to select and "sharpen" on the arm. The following describes the use of the VIM bundle, translator, and a few ctags for today's rare version of assembler.

There is only a translator

Soon after starting my work in the development team, I came across an assembler for 1806BM2, roughly speaking, PDP-11. Moreover, the target device is a certain board with a handful of parts for converting and processing signals, and the instrumental machine is a Windows PC (without options). The devices under development are different, and the programs for them are from three hundred to three thousand lines of code.

When I joined this process, it turned out that the folder with the device name corresponds to the project. In the folder there is an assembler file (all asm files have the same name, compilation is so configured), a bat file without parameters, which calls another bat file with parameters, and that, in turn, runs an assembler exe file (lying naturally , right here). In addition, in the project folder you can find the binary and listing, as well as the program for converting the binary to the ROM firmware file and an auxiliary text file for conversion, another program for converting the firmware file to a format that is understandable to our programmer, the firmware file (outdated since the program began to be written in flash instead of ROM), plus dirinfo.txt, in which it was extremely rare for anyone to write anything.

The work went like this: in the console file manager, the program text was corrected by the built-in editor. After editing, the first batch file was launched (it is important not to mix it up!). Next, we look at the console output for errors. If there are no syntactical jambs - the program is poured into the ROM emulator, we check the operability on the hardware. So the program is added and checked until it starts to do what is expected of it. Then the generated firmware is written to the ROM (later, the ROM was replaced by flash).

At first, I worked as usual. It was not up to convenience - you need to understand the command system, the features of building a program, the hardware of the devices for which software is written. When something began to turn out, thoughts of improvement began to arise. First of all, I wanted syntax highlighting, starting the compiler from the editor and normal search with replacement.

Flour of choice

At first I tried to find an IDE on all kinds of Internet, because it’s PDP-11, that is, DCK, BC and UKSC, there must be something to find! And it was found, but it worked exclusively in the emulator of the UKSC. I did not like the console IDE, nor the emulator, nor the need to run the emulator for the environment, but this was not the most important thing. Worst of all, the resulting binary was different from the binary created in the "traditional way." I did not understand the reasons - I still did not have enough to finish the rarities in emulators, or, worse, write corrective software. I decided to organize my workspace, with preference and courtesans.

I began to look for a text editor more seriously. From what I came across during the search, I liked UltraEdit the most (especially in the UEStudio version). It had everything I wanted, plus some more goodies - comparing text files, transcoding, column selection, launching not only the compiler, but also other macros under construction using the name of the current file, toolbar extension. Everything is fine - but for a fee, and then my income is not cheap. I tried MiBEditor - an impressive product (for free and made in one helmet), but not that. An easy Linux craze helped. I learned about VIM, tried to use it, sensed its capabilities and discovered a version for Wndows.


The first thing I did was set up the appearance and behavior in vimrc: dark wombat color scheme (light gray on black, adjusted according to my preferences), line numbering, increased to 85 width by default due to line numbers, smart indents and tabs , disabled bak-files, auto-change of the working folder by the open file. He turned on a virtual call, which blinks rather than beeping, disables the toolbar (for some reason, has left the menu, although I do not use it), hid the mouse while printing, and hung up the Ctrl-Tab switch between open split buffers.

I chose a font that has Russian characters:
set guifont=Courier_New:h10:cRUSSIAN    " выбор шрифта

Added something for layout to make it convenient to work in Russian:
set keymap=russian-jcukenwin    " русская раскладка
set iskeyword=@,48-57,_,192-255	" добавка рус. симв. к ключевым словам
set iminsert=0                  " но по-умолчанию - английская
set imsearch=0                  " и при поиске — английская
lang ctype Russian_Russia.1251

I hung the layout switch on F12:
imap <F12> <C-^>
cmap <F12> <C-^>

Now, with the English layout, all keyboard commands work perfectly, and you need to switch the input language not with the system Ctrl-Shift, but with VIM F12, the current language is displayed in the bottom line: “- INSERT -” for English, or “- INSERT ( language) - " for Russian. A slight inconvenience - usually my keyboard layout is Russian, but here we must not forget to switch to English when starting VIM.

I recorded all of the above in a separate vimrc_rg, which I connected in the default settings file:
source $VIM/_vimrc_rg

I also installed several plugins, but I constantly use literally one - QuickBuf (qbuf.vim, script_id = 1910), which allows you to switch between open buffers in one window by F4. Now I don’t need tabs (which I got used to in UltraEdit), and even seem uncomfortable. Sometimes I remember the installed Visual mark (script_id = 1026), which makes selected bookmarks, as in UltraEdit.

So began using VIM as the main editor for plain-text files. One of my requirements - normal search and replacement - comes out of the box, just learn how to use it. Plus, the highlighting of many languages ​​and auto-indentation - it became very convenient to edit batch files, for example.

Setting the backlight and translator

Then he introduced a new file type - a1806, for highlighting and embedding compilation. Created the filetype.vim file in the root of the vimfiles folder:
	augroup filetypedetect
	au BufNewFile,BufRead *.msa	setf a1806
	au BufNewFile,BufRead *.a51	setf asm8051
	augroup END

Then for some time he began to give the appropriate extensions to the assembler files - msa for 1806, a51 for MCS-51 assembler, so as not to be confused with asm, the default for Intel assembler.

Then, in vimfiles \ syntax, he made the a1806.vim file, redone from the highlight file of some other language. Keywords found on the Internet, text information on PDP-11 in bulk. There are a couple of paper books on UKNTS and SM computers, but it is easier to copy from web pages.
Stuck in this file, among other things, this line:
syn match a1806Error        "#@.*\|[a-zA-Z0-9_$]\{7,}:"

When typing quickly and entering indirect addressing, I often confused @ # and # @, and this pattern highlights an error while typing. Other common typos can be identified in this way.

There is syntax highlighting. Now compilation. Understood with the utility make and ctags, it became clear that here they are not helpers. There is an assembler, but there is no linker - the project cannot be split into module files. There will be only one goal for make, the file for it, too, nothing to bother with. The same with ctags - there is only one file, there is nothing special to search for on it, labels are so easily found with an asterisk. Long files are more useful than bookmarks, which VIM also has. But the assembler in every project folder is fi! I make the bin folder in the root of the C: \ drive, I write it in PATH (then I put make and ctags for another assembler there). There I put the assembler and mk1806.bat, where in addition to the microhelp and checking the validity of the passed parameters, the binary and listing are erased, and then the assembler is called:
CD %2 %3 %4 %5 %6 %7 %8 %9
if not exist *.bin goto NOBIN
attrib -r *.bin
del *.bin
if not exist *.lst goto NOLST
attrib -r *.lst
del *.lst
if exist %1 C:\bin\cmplr1806\asm.exe %1 -m
if not exist %1 echo Error: File %1 not exist!

The batch file accepts two parameters - the name of the file and the path to it. In order not to spoil the output of make, the mode of displaying commands in the file is disabled (@ ECHO OFF).

In vimfiles \ ftplugin made the a1806.vim file:
" Language:	1806 assembler 
" Maintainer:
" Last Change:
" включает для данного буфера текущую директорию по директории открытого файла
lcd %:h
" устанавливает программу компиляции
setlocal makeprg=C:\bin\mk1806.bat\ %:t\ %:p:h
" устанавливает опцию автозаписи перед компиляцией
setlocal autowrite
nmap <buffer> <F9> :make<CR>
imap <buffer> <F9> <Esc>:make<CR>
" устанавливает формат строки ошибок
set efm=%-G,%-G\ BK-10/11%.%#,%-P\ Opened\ %f,%Eline\ %l\\,%.%#,%Z%m,%-GFile\ compiled%.%#

Errorformat was determined empirically (there is no documentation whatsoever on asm.exe), that is, it started assembling the file without errors and with various specially made errors, studied the console output, compiled a template for VIM help.
Error output example (line numbers added manually for clarity):
2   BK-10/11 Assembler 
4   Opened 1.ASM
5  Line 61,Address 000320:
6  Bad operator [AKSJDFH].
7   Opened 1.lst
9  File compiled 346 bytes.

Then the error format will consist of the following elements:
  • % -G, - ignore the empty line if it occurs. (“G” is general information, “% -” is excluded from the output, and the absence of anything after “G” indicates that an empty line is meant). Will be applied to lines 1, 3, 8, and 10.
  • % -G \ BK-10/11%.% #, Here '%.% #' Is used to create the regular expression pattern '. *', That is, a line starting with “BK-10/11” (space for the command “: set” is escaped by “\”), ignored. Will be applied to line 2.
  • % -P \ Opened \% f, - parses a single-line message (% -P) with the file name (% f) after the word "Opened", "% -P" says that the line is not displayed, but we remember the file name, the following errors relate to it. Will be applied to lines 4 and 7.
  • % Eline \% l \,%.% #, - the beginning of a multi-line error message (% E), where after the word “line” comes the line number (% l), then a comma (“\,” - the comma must be escaped a backslash, but it needs to be duplicated for the “: set” command), then some line (“%.% #” = “. *”) that is involved in the output (in our case, the address, although it will be displayed as a number errors - “320 error”, this is not a bug, but a feature).
  • % Z% m, - the end of the multiline message (% Z) with the actual error message (% m). The% E and% Z patterns work together for line pairs of types 5 and 6.
  • % -GFile \ compiled%.% # Again, general information ejected from the output, the rule for line 9.

According to the efm patterns, lines 1..4 and 7..10 are not output, although the file name is stored in 4 and 7. If there are no lines 5 and 6, the output is empty, there are no errors. Lines type 5 and 6 may be several pairs. Each of these pairs will form an error message list item.

Voilà! We have compilation with autosave on F9. When a syntax error is detected, VIM immediately places the cursor on the line of code corresponding to the first error from the list of found ones.

There is not enough debugger - but it will not help here, since too many things are tied to interrupts, direct access to memory and extraneous hardware. I have not yet mastered the full file comparison built into VIM, I mainly use WinMerge. And still it became much more convenient.


And then 1806 began to depart a little from us, and work began with devices based on the NM6403 processor. Also in assembler. And so as not to be perverted with coming up with the next extension for the source files, I added the asm.vim file to vimfiles \ ftplugin:
	if getline(1) =~ '^;.*a1806\>'
	  set filetype=a1806

	if getline(1) =~ '^//.*a6403\>'
	  set filetype=a6403

In assembler files with the extension .asm, I began to write the first line
“; a1806” or “// a6403”, respectively. Added the syntax highlighting vimfiles \ syntax \ a1806.vim (written very simply and quickly according to the "Description of the assembler language") and such vimfiles \ ftplugin \ a6403.vim:
" Language:	6403 assembler 
" Maintainer:	
" Last Change:
setlocal makeprg=c:\bin\make.exe
" включает для данного буфера текущую директорию по директории открытого файла
lcd %:h
" устанавливает опцию автозаписи перед компиляцией
setlocal autowrite
nmap <buffer> <F9> :make<CR>
imap <buffer> <F9> <Esc>:make<CR>
nmap <buffer> <F10> :make TAGS<CR>
imap <buffer> <F10> <Esc>:make TAGS<CR>
set efm=\"%f\"\\,%l\ :\ %m

For this to work, he wrote a Makefile, which lies in each project folder and is adjacent to the bat compiler launch file used by other developers. My Makefile has a TAGS target, as well as a call to this target from an ALL target.
	@c:/bin/ctags.exe --options=c:/bin/a6403.ctags $(SRC_ASM) *.asi

$ (SRC_ASM) lists ASM sources, and * .asi contains include files.

In the mentioned folder C: \ bin lies make.exe, ctags.exe, as well as a6403.ctags, passed as a parameter for ctags.exe:
--regex-a6403=/^[ \t]*const[ \t]+([a-zA-Z0-9_]+)/\1/C,consts/
--regex-a6403=/^[ \t]*#define[ \t]+([a-zA-Z0-9_]+)/\1/D,defs/
--regex-a6403=/^[ \t]*global[ \t]+([a-zA-Z0-9_]+)[ \t]*:[ \t]*(word|long)/\1/V,vars/

ctags out of the box has no idea about the NM6403. The first line defines the new language name. The second line talks about the file extension. Extensions are written in a row, for example, ".asm.asi.inc". A dot without a character behind it implies the use of files without an extension. However, this is not a particularly useful option - I did not specify the .asi extension here, however, I specified * .asi when calling ctags - and the utility scanned everything that was needed. The fourth line makes us use the above extensions specifically for this language, and not for the language built into ctags for the same extensions. The rest of the lines describe a label of the form “