8085 Assembler? - Page 1
Forum section: electronics / general

author: firewalker
author_rank: Super Contributor
timestamp: December 27, 2019, 11:03:16 am
content: I have an 8085 training kit. Is there any free assembler for 8085?

author: T3sl4co1l
author_rank: Super Contributor
timestamp: December 27, 2019, 11:33:37 am
content: Shrug, I've got a copy of TASM 3.1 that supports several instruction sets, 8085 and Z80 among others (I was using it for Z80 when I was). Seems a cromulent assembler, nothing special, no macros I think.Tim

author: tggzzz
author_rank: Super Contributor
timestamp: December 27, 2019, 12:04:10 pm
content: If you are keying it in on a hex keypad, you might as well convert the assembler to hex manually!

author: firewalker
author_rank: Super Contributor
timestamp: December 27, 2019, 12:06:30 pm
content: Yes I could!Alexander.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: December 27, 2019, 12:41:46 pm
content: A friend does exactly that, on his vintage dev board.Tim

author: firewalker
author_rank: Super Contributor
timestamp: December 27, 2019, 12:49:45 pm
content: The only one I found that seems promising is The Macro Assembler AS.http://john.ccac.rwth-aachen.de:8000/as/Alexander.

author: jesuscf
author_rank: Frequent Contributor
timestamp: December 28, 2019, 08:51:48 am
content: Baaaack in the day, I used asm80 and plm80 to write programs for the 8085 microprocessor in an Intel MDS running the ISIS II "operating system" (with 8" floppy disks!). Those compilers worked at some time under DOS. Apparently the tools are recreated/recompiled here for modern operating systems (I hadn't tested them):https://github.com/ogdenpm/intel80toolsBitsavers has documentation for all those tools:http://www.bitsavers.org/pdf/intel/ISIS_II/If you search deep enough, you may be able to find the original asm80 for ISIS together with an ISIS emulator that would probably run on DOSbox.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: December 28, 2019, 10:36:35 am
content: https://www.asm80.com/http://duckduckgo.com/?q=8085+online+assemblerFor the 6502, there's one online that can even upload to the Apple II via the cassette port :-)

author: rstofer
author_rank: Super Contributor
timestamp: December 28, 2019, 04:47:58 pm
content: There are CP/M 2.2 emulators around and they may include MAC, the Digital Research Macro Assembler. They will almost certainly include ASM80, the standard assembler.

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 28, 2019, 05:23:38 pm
content: Speaking of CP/M, some may like this:http://www.cpm.z80.de/source.html

author: westfw
author_rank: Super Contributor
timestamp: December 28, 2019, 07:01:17 pm
content: QuoteDon't forget that the 8085 is essentially just an 8080 internally, with only two extra instructions (RIM, SIM)8080 assemblers are pretty common.

author: legacy
author_rank: Super Contributor
timestamp: December 28, 2019, 10:46:56 pm
content: I haven't tried it. I cannot offer any feedback.If you dare experimental stuff, you can trythis

author: firewalker
author_rank: Super Contributor
timestamp: December 28, 2019, 11:05:30 pm
content: Quote from: westfw on December 28, 2019, 07:01:17 pmIf my understanding is correct, Z80 is binary compatible with 8080 and 8085. So any Z80 assembler can be used. Correct?Alexander.

author: oPossum
author_rank: Super Contributor
timestamp: December 28, 2019, 11:17:36 pm
content: Quote from: firewalker on December 28, 2019, 11:05:30 pmSame core binary instruction set, but some different mnemonics. LD instead of MOV for example.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: December 29, 2019, 12:01:14 am
content: Z80 has tons more registers, it is not backwards compatible. 80 is forwards compatible (and x86 is designed to be easy to migrate to, but is in no way binary compatible). If you carefully restrict yourself to use the compatible subset, you could use a Z80 assembler.Tim

author: obiwanjacobi
author_rank: Super Contributor
timestamp: December 29, 2019, 08:53:22 am
content: Over at the programming topic:https://www.eevblog.com/forum/programming/simple-python-based-8085-assembler/

author: David Hess
author_rank: Super Contributor
timestamp: December 29, 2019, 04:50:43 pm
content: Quote from: tggzzz on December 27, 2019, 12:04:10 pmThat was the first programming I did you insensitive clod!We had pads of lined paper forms specifically for doing the assembly manually. Then I typed the hex values directly into a Prolog PROM programmer.After a while, you know all of the important opcodes.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: December 29, 2019, 05:02:33 pm
content: Quote from: David Hess on December 29, 2019, 04:50:43 pmBut calculating the relative back/forward offsets isn't fun...

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 29, 2019, 05:35:05 pm
content: Quote from: GeorgeOfTheJungle on December 29, 2019, 05:02:33 pmIt's a pain.I also did this back when I had a Z80 single board to play with. Of course didn't have any other computer that could host a (cross-)assembler back then.When I got my first CP/M machine, it came with no assembler actually AFAIR (or maybe I just didn't know it did, I had very little documentation)... I wrote my own in Pascal (Turbo), and added a feature to automatically generate machine code that could be directly inlined in Pascal code. That was fun.

author: David Hess
author_rank: Super Contributor
timestamp: December 29, 2019, 06:27:30 pm
content: Quote from: GeorgeOfTheJungle on December 29, 2019, 05:02:33 pm8085 only uses absolute addresses.If you are not sure about instruction length, then use the longer form and insert NOPs as required later. Does anybody remember phase errors in assemblers?Notice that NOP is 00000000b so it can be later overwritten in an additional programming pass. This makes it possible to patch code which has already been burned to memory.

author: tggzzz
author_rank: Super Contributor
timestamp: December 29, 2019, 06:39:36 pm
content: Quote from: David Hess on December 29, 2019, 04:50:43 pmActually too acutely sensitive.The first computer I designed and made had binary switches. The first I bought had a hex keypad (an Acorn system 1), and I showed a proof of concept in 10% of the expected timeI then saw people using an 8086 with a hex keypad, which was far too heroic for me!Apart from that, the first computer I used had a 39-bit word.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: December 29, 2019, 06:39:52 pm
content: Quote from: David Hess on December 29, 2019, 06:27:30 pmI'm not sure if that makes it even worse yet... ?QuoteI don't, what's that?

author: David Hess
author_rank: Super Contributor
timestamp: December 29, 2019, 06:51:44 pm
content: Quote from: GeorgeOfTheJungle on December 29, 2019, 06:39:52 pmA phase error occurs when addresses do not match between passes. This could occur if the instruction length changes between passes. It is more common with ISAs which support short jumps:https://dfdeboer.github.io/S05/304/PH_ERROR.HTM

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: December 29, 2019, 07:17:35 pm
content: Quote from: David Hess on December 29, 2019, 06:51:44 pmHahaha, primitive tools!My favourite ISA back then only had 16 bit jump (absolute or indirect), and 8 bit relative conditional branch.

author: jesuscf
author_rank: Frequent Contributor
timestamp: December 30, 2019, 01:14:27 am
content: Quote from: David Hess on December 29, 2019, 04:50:43 pmSo did I for the Micro-Professor MPF-I board with a Z80 microprocessor! (https://en.wikipedia.org/wiki/Micro-Professor_MPF-I) After a while you get really good at it. In this videoBill Gates talks about Paul Allen doing exactly the same: writing a simple boot loader for the Altair 8800 (in assembly for the 8080 microprocessor) in a flight to Albuquerque New Mexico and later keying it by hand bit by bit. Funny how Bill Gates brags about writing a better boot loader than Paul Allen later on. The boot loader read the paper tape with the first basic interpreter for the Altair 8800 from Microsoft.

author: jesuscf
author_rank: Frequent Contributor
timestamp: December 30, 2019, 02:02:21 am
content: Quote from: firewalker on December 27, 2019, 11:03:16 amApparently the name of the board is the Microkit 8085 (google ΜΙΚΡΟΚΙΤ 8085 for better results). There is some documentation in Greek (I guess, with all the alphas and betas and such) here:http://www.microlab.teipat.gr/docs/micro1/Fylladio%20-%20Micro%20I%20-%202012-13.pdfand here:http://www.microlab.teipat.gr/docs/micro1/Fylladio-Micro1-2017-18.pdfThe documents above have examples using the board and point to GNUsim8085:http://gnusim8085.srid.ca/downloadwhich is "A graphical simulator, assembler and debugger for the Intel 8085 microprocessor". This maybe the easiest rout to get started with the board.

author: firewalker
author_rank: Super Contributor
timestamp: December 30, 2019, 01:18:49 pm
content: Yes, I know. It is a Greek made device. I have all the documentation, schematics, code of the EPROM, etc.AFAIK, GNUSim8085 can't produce machine code. The Assemble menu is just to save the assembly file.Alexander.

author: firewalker
author_rank: Super Contributor
timestamp: December 30, 2019, 02:21:04 pm
content: OK. It seems "The Macro Assembler AS" is the way to go. After 29 years a 2k lines 8085 assembly code it produced the same binary. Same with the one Microtec's Assembler Paragon ASM85 produced 19 years ago.http://john.ccac.rwth-aachen.de:8000/as/

author: jesuscf
author_rank: Frequent Contributor
timestamp: December 30, 2019, 05:06:13 pm
content: Quote from: firewalker on December 30, 2019, 01:18:49 pmAh, ok. Now every one knows. FYI I used the recreation of the original tools inhttps://github.com/ogdenpm/intel80toolsto compile this assembly file from the documentation (lab9.asm) on Windows 10:Code:;*******************************************************************************;LABORATORY EXERCISE 9;FILE LAB9.ASM;DATE: 30/09/2010;*******************************************************************************ORG 2000H ; Address of first instructionUPDDT EQU 039DH ; Display Subroutine AddressSTART: ; program start labelMVI A,02H ; Load A with 02HOUT 40H ; Initialize gatesMAIN:IN 41H ; Read the Switch StatusCPI 04H ; D2 switch setting ON?JZ PROC1 ; Yes. Go to 1st procedureCPI 08H ; D3 switch setting ON?JZ PROC2 ; Yes. Go to 2nd procedureCPI 0A0H ; D5-D7 switch setting ON?JZ PROC3 ; Yes. Go to the 3rd procedureJMP MAINPROC1: ; 1st procedureMVI A,00H ; Load A with 00HOUT 42H ; Off LEDs (address 42H)JMP MAIN ; Jump to main ProgramPROC2: ; 2nd procedureMVI A,07H ; Load A with 07H (leds L0, L1 & L2)OUT 42H ; (address 42H)CALL DELAY ; Call delay subroutineMVI A,18H ; Load A with 18H (leds L3 & L4 )OUT 42H ; (address 42H)CALL DELAY ; Call delay subroutineJMP MAIN ; Jump to main ProgramPROC3: ; 3rd procedureMVI A,6FH ; Load A with 6FHSUI 2AH ; Subtract from A 2?? (6F-2A)STA 2450H ; Save the result in location 2450?ORI 1FH ; OR with the result from subtraction and 1FH ({2450H} OR 1FH)STA 245FH ; Save the result in location 245FHCALL UPDDT ; Show the contents into the DisplayJMP MAIN ; Jump to main ProgramDELAY: ; 1sec delayMVI B,0FFH ; Load FFH to register ?LABEL1: ; Start of LABEL1MVI A,0FFH ; Load FFH to register ?LABEL2: ; Start of LABEL2DCR A ; Subtract 1 from register AJNZ LABEL2 ; Branch to LABEL2 if ZERO flag is 0DCR B ; Subtract 1 from register BJNZ LABEL1 ; Branch to LABEL1 if ZERO flag is 0RET ; Return from the subroutineRST 1END ; End of ProgramThe only thing I couldn't find was the program 'objhex.exe', but there is a obj2bin program whose output I pass to this program to generate an Intel hex file:Code:// bin2hex.c: Converts a bin file to hex//// Compile using Visual C:// cl bin2hex.c//// or compile using gcc for windows:// gcc bin2hex.c -o bin2hex.exe#include <windows.h>#include <stdio.h>#include <stdlib.h>#define EQ(X,Y) (_stricmp(X, Y)==0)#define NEQ(X,Y) (_stricmp(X, Y)!=0)void print_help (char * prn){printf("Usage examples:\n");printf("%s f1.bin -Of1.hex -S0x2000 (convert f1.bin to f1.hex, f1.bin starts at address 0x2000)\n", prn);fflush(stdout);}long fsize(FILE *stream){long curpos, length;curpos = ftell(stream);fseek(stream, 0L, SEEK_END);length = ftell(stream);fseek(stream, curpos, SEEK_SET);return length;}int main(int argc, char **argv){int j, k, n;FILE * fin, * fout;int filesize;unsigned char * bigbuff;int chksum, address;int Hex_Start=0;char InName="";char OutName="";printf("BIN to HEX converter\n");fflush(stdout);for(j=1; j<argc; j++){if(EQ("-?", argv)) { print_help(argv); exit(0); }else if((argv=='-') && (toupper(argv)=='S')){sscanf(&argv,"%i",&Hex_Start);}else if((argv=='-') && (toupper(argv)=='O')){strcpy(OutName, &argv);}else strcpy(InName, argv);}if(strlen(InName)==0){print_help(argv);return 1;}fin = fopen(InName, "rb");if (fin == NULL){printf("Invalid filename '%s'.\n", InName);exit(1);}filesize=fsize(fin);bigbuff = (unsigned char*) malloc(filesize);if(bigbuff==NULL){printf("Memory allocation for %d bytes failed.\n", filesize);exit(2);}n=fread(bigbuff, sizeof(unsigned char), filesize, fin);if(n!=filesize){printf("Error loading file.\n");exit(2);}fclose(fin);printf("Loaded %d bytes from file '%s'.\n", n, InName); fflush(stdout);if(strlen(InName)==0){strcpy(OutName, InName);strcat(OutName, ".hex");}printf("Creating output file '%s'\n", OutName); fflush(stdout);fout = fopen(OutName, "wb");if (fout == NULL){printf("Couldn't create file '%s'.\n", OutName);free(bigbuff);exit(1);}for(j=0; j<filesize; j+=16){address=Hex_Start+j;if((filesize-j)>=16){fprintf(fout, ":10%04X00", address);chksum=0x10+(address/0x100)+(address%0x100);}else{fprintf(fout, ":%02X%04X00", filesize-j, address);chksum=(filesize-j)+(address/0x100)+(address%0x100);}for(k=0; k<16; k++){if((j+k)<filesize){fprintf(fout, "%02X", bigbuff[j+k]);chksum+=bigbuff[j+k];}}fprintf(fout, "%02X\n", -chksum&0xff);}fprintf(fout, ":00000001FF\n"); // End recordfclose(fout);printf("\n");fflush(stdout);free(bigbuff);return 0;}To "compile" the code with the Intel tools one first use the assembler, then the linker, then the locator, and finally convert the object generated file to bin and then to hex. I did it with a simple batch file (do.bat) but a makefile should work as well:Code:set fname=%~n1set tools=D:\intel80tools\tools%tools%\asm80 %fname%.asm%tools%\link %fname%.obj to %fname%.lnk%tools%\locate %fname%.lnk CODE(2000H) DATA(2500H) ORDER(DATA,STACK) STACKSIZE(30H) MEMORY(0FFFFH) PURGE MAP PRINT(%fname%.map)%tools%\obj2bin %fname%.bin %fname%%tools%\bin2hex %fname%.bin -O%fname%.hex -S0x2000And here is how the building process goes:Code:D:\Microkit_8085>do lab9.asmD:\Microkit_8085>set fname=lab9D:\Microkit_8085>set tools=D:\intel80tools\toolsD:\Microkit_8085>D:\intel80tools\tools\asm80 lab9.asmASSEMBLY COMPLETE, NO ERRORSD:\Microkit_8085>D:\intel80tools\tools\link lab9.obj to lab9.lnkISIS-II OBJECT LINKER V3.0D:\Microkit_8085>D:\intel80tools\tools\locate lab9.lnk CODE(2000H) DATA(2500H) ORDER(DATA,STACK) STACKSIZE(30H) MEMORY(0FFFFH) PURGE MAP PRINT(lab9.map)ISIS-II OBJECT LOCATER V3.0D:\Microkit_8085>D:\intel80tools\tools\obj2bin lab9.bin lab9Image: 2000H-2050HType: 0Start: 00H:0000HD:\Microkit_8085>D:\intel80tools\tools\bin2hex lab9.bin -Olab9.hex -S0x2000BIN to HEX converterLoaded 80 bytes from file 'lab9.bin'.Creating output file 'lab9.hex'This is how the generated Intel hex file looks like:Code::102000003E02D340DB41FE04CA1820FE08CA1F204E:10201000FEA0CA3020C304203E00D342C304203EA9:1020200007D342CD42203E18D342CD4220C30420E4:102030003E6FD62A325024F61F325F24CD9D03C353:10204000042006FF3EFF3DC2462005C24420C9CF02:00000001FFEdit: Fixed error calculating checksum of hex file recordsEdit 2: Since the source code for the obj2bin program is provided with the intel80tools, it was easy to modify it to create a hex file instead. The source code is here:Code:// objhex.c: Convertes and absolute object file generated by the locator to an Intel hex file.//// compile using Visual C: cl objhex.c// or compile using gcc for windows: gcc objhex.c -o objhex.exe#include <stdio.h>#include <stdlib.h>#include <ctype.h>void readRec(FILE *fp);void skipRec(FILE *fp, int len);void read6(FILE *fp, int len);void read4(FILE *fp, int len);unsigned char mem;unsigned int low = 0x10000;unsigned int high = 0;void loadfile(char *s);void dumphex(char *s);int main(int argc, char **argv){printf("Object to Intel Hex converter\n");if (argc != 3) {fprintf(stderr, "usage: %s infile outfile\n", argv);exit(0);}loadfile(argv);dumphex(argv);}void loadfile(char *file){FILE *fp;printf("Loading: %s\n", file);if ((fp = fopen(file, "rb")) == NULL) {fprintf(stderr, "can't open input file %s\n", file);exit(1);}do {readRec(fp);} while (! feof(fp));fclose(fp);}void dumphex(char *file){FILE *fout;int chksum, j, k;printf("Creating: %s\n", file);if ((fout = fopen(file, "wb")) == NULL) {fprintf(stderr, "can't create output file %s\n", file);exit(1);}for(j=low; j<high; j+=16){if((high-j)>=16){fprintf(fout, ":10%04X00", j);chksum=0x10+(j/0x100)+(j%0x100);}else{fprintf(fout, ":%02X%04X00", high-j, j);chksum=(high-j)+(j/0x100)+(j%0x100);}for(k=0; k<16; k++){if((j+k)<high){fprintf(fout, "%02X", mem[j+k]);chksum+=mem[j+k];}}fprintf(fout, "%02X\n", -chksum&0xff);}fprintf(fout, ":00000001FF\n"); // End recordfclose(fout);printf("\n");fflush(stdout);}void readRec(FILE *fp){int type, len;type = getc(fp);if (type == EOF) return;len = getc(fp);len += getc(fp) * 256;if (type == 6)read6(fp, len - 1);else if (type == 4)read4(fp, len - 1);elseskipRec(fp, len - 1);(void)getc(fp);// crc}void skipRec(FILE *fp, int len){while (len-- > 0)(void)getc(fp);}void read6(FILE *fp, int len){unsigned short addr;if (len < 3) {fprintf(stderr, ">>>corrupt type 6 field\n");skipRec(fp, len);} else {(void)getc(fp);// Segaddr = getc(fp);addr += getc(fp) * 256;len -= 3;if (addr < low) low = addr;while (len-- > 0)mem[addr++] = getc(fp);if (addr > high)high = addr;}}void read4(FILE *fp, int len){unsigned modType, segId, offset;modType = getc(fp);segId = getc(fp);offset = getc(fp);offset += getc(fp) * 256;len -= 4;}char* skipSpc(char* s){while (*s == ' ' || *s == '\t')s++;return s;}char *gethex(char *s, unsigned *val){*val = 0;s = skipSpc(s);if (!isxdigit(*s))return 0;while (isxdigit(*s)) {*val = *val * 16 + (isdigit(*s) ? *s - '0' : toupper(*s) - 'A' + 10);s++;}return s;}The batch file to assemble a file looks now like this:Code:set fname=%~n1set tools=D:\intel80tools\tools%tools%\asm80 %fname%.asm%tools%\link %fname%.obj to %fname%.lnk%tools%\locate %fname%.lnk CODE(2000H) DATA(2500H) ORDER(DATA,STACK) STACKSIZE(30H) MEMORY(0FFFFH) PURGE MAP PRINT(%fname%.map)%tools%\objhex %fname% %fname%.hex

author: westfw
author_rank: Super Contributor
timestamp: January 03, 2020, 02:22:23 am
content: There is another trick that no one else has mentioned yet, useful for most "classic" microprocesor architectures:You take your favorite modern assembler (Gnu's gas, for example) and implement all of the classic instructions as macros that generate bytes in memory. This way you get the major assembler features (offset calculations, pseudo-ops and directives, macros, binary file handling, editor support) of the modern assembler "for free."Also, in the process of writing the macros, you probably learn a lot about the target...I wonder if there is a "blank" gas target that doesn't define any opcodes that might conflict?I did an 8085 assembler as a set of Macro-10 (DEC PDP-10 Assembler) macros, back in college.Of course it's a bit sucky when you type in a Forth implementation, assemble with you homemade assembler, and run it on your homemade emulator, and you have to figure out which piece has the bug that preventing things from working right :-(And it doesn't work so well on newer CPUs that got creative with their operand syntax - it's easy to have separate macros for MOV, MVI, LSI, LDA, STA, LHLD, etc, but not if they've all been collapsed into "MOVE", with the opcode varying depending on exact format of the operand(s)