Author Topic: 8085 Assembler?  (Read 10713 times)

0 Members and 1 Guest are viewing this topic.

Offline jesuscf

  • Frequent Contributor
  • **
  • Posts: 504
  • Country: ca
Re: 8085 Assembler?
« Reply #25 on: December 30, 2019, 02:02:21 am »
I have an 8085 training kit. Is there any free assembler for 8085?




Apparently 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.pdf

and here:

http://www.microlab.teipat.gr/docs/micro1/Fylladio-Micro1-2017-18.pdf

The documents above have examples using the board and point to GNUsim8085:

http://gnusim8085.srid.ca/download

which is "A graphical simulator, assembler and debugger for the Intel 8085 microprocessor".   This maybe the easiest rout to get started with the board.




Homer: Kids, there's three ways to do things; the right way, the wrong way and the Max Power way!
Bart: Isn't that the wrong way?
Homer: Yeah, but faster!
 

Offline firewalkerTopic starter

  • Super Contributor
  • ***
  • Posts: 2483
  • Country: gr
Re: 8085 Assembler?
« Reply #26 on: December 30, 2019, 01:18:49 pm »
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.

 
Become a realist, stay a dreamer.

 

Offline firewalkerTopic starter

  • Super Contributor
  • ***
  • Posts: 2483
  • Country: gr
Re: 8085 Assembler?
« Reply #27 on: December 30, 2019, 02:21:04 pm »
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/
« Last Edit: January 01, 2020, 12:00:47 pm by firewalker »
Become a realist, stay a dreamer.

 

Offline jesuscf

  • Frequent Contributor
  • **
  • Posts: 504
  • Country: ca
Re: 8085 Assembler?
« Reply #28 on: December 30, 2019, 05:06:13 pm »
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.

Ah, ok.  Now every one knows.  FYI I used the recreation of the original tools in https://github.com/ogdenpm/intel80tools to compile this assembly file from the documentation (lab9.asm) on Windows 10:

Code: [Select]
;*******************************************************************************
;LABORATORY EXERCISE 9
;FILE LAB9.ASM
;DATE: 30/09/2010
;*******************************************************************************

ORG 2000H       ; Address of first instruction

UPDDT EQU 039DH ; Display Subroutine Address

START:          ; program start label
  MVI A,02H     ; Load A with 02H
  OUT 40H       ; Initialize gates
MAIN:
  IN 41H        ; Read the Switch Status
  CPI 04H       ; D2 switch setting ON?
  JZ PROC1      ; Yes. Go to 1st procedure
  CPI 08H       ; D3 switch setting ON?
  JZ PROC2      ; Yes. Go to 2nd procedure
  CPI 0A0H      ; D5-D7 switch setting ON?
  JZ PROC3      ; Yes. Go to the 3rd procedure
  JMP MAIN

PROC1:          ; 1st procedure
  MVI A,00H     ; Load A with 00H
  OUT 42H       ; Off LEDs (address 42H)
  JMP MAIN      ; Jump to main Program

PROC2:          ; 2nd procedure
  MVI A,07H     ; Load A with 07H (leds L0, L1 & L2)
  OUT 42H       ; (address 42H)
  CALL DELAY    ; Call delay subroutine
  MVI A,18H     ; Load A with 18H (leds L3 & L4 )
  OUT 42H       ; (address 42H)
  CALL DELAY    ; Call delay subroutine
  JMP MAIN      ; Jump to main Program

PROC3:          ; 3rd procedure
  MVI A,6FH     ; Load A with 6FH
  SUI 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 245FH
  CALL UPDDT    ; Show the contents into the Display
  JMP MAIN      ; Jump to main Program

DELAY:          ; 1sec delay
  MVI B,0FFH    ; Load FFH to register ?
LABEL1:         ; Start of LABEL1
  MVI A,0FFH    ; Load FFH to register ?
LABEL2:         ; Start of LABEL2
  DCR A         ; Subtract 1 from register A
  JNZ LABEL2    ; Branch to LABEL2 if ZERO flag is 0
  DCR B         ; Subtract 1 from register B
  JNZ LABEL1    ; Branch to LABEL1 if ZERO flag is 0
  RET           ; Return from the subroutine

  RST 1
END             ; End of Program

The 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: [Select]
// 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[MAX_PATH]="";
    char OutName[MAX_PATH]="";

    printf("BIN to HEX converter\n");
    fflush(stdout);
   
    for(j=1; j<argc; j++)
    {
             if(EQ("-?", argv[j])) { print_help(argv[0]); exit(0); }
        else if((argv[j][0]=='-') && (toupper(argv[j][1])=='S'))
        {       
            sscanf(&argv[j][2],"%i",&Hex_Start);
        }
        else if((argv[j][0]=='-') && (toupper(argv[j][1])=='O'))
        {       
            strcpy(OutName, &argv[j][2]);
        }
        else strcpy(InName, argv[j]);
    }
   
    if(strlen(InName)==0)
    {
        print_help(argv[0]);
        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 record
    fclose(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: [Select]
set fname=%~n1
set 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 -S0x2000

And here is how the building process goes:

Code: [Select]
D:\Microkit_8085>do lab9.asm

D:\Microkit_8085>set fname=lab9

D:\Microkit_8085>set tools=D:\intel80tools\tools

D:\Microkit_8085>D:\intel80tools\tools\asm80 lab9.asm

ASSEMBLY COMPLETE,   NO ERRORS

D:\Microkit_8085>D:\intel80tools\tools\link lab9.obj to lab9.lnk
ISIS-II OBJECT LINKER V3.0

D:\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.0

D:\Microkit_8085>D:\intel80tools\tools\obj2bin lab9.bin lab9
Image:  2000H-2050H
Type:   0
Start:  00H:0000H

D:\Microkit_8085>D:\intel80tools\tools\bin2hex lab9.bin -Olab9.hex -S0x2000
BIN to HEX converter
Loaded 80 bytes from file 'lab9.bin'.
Creating output file 'lab9.hex'

This is how the generated Intel hex file looks like:

Code: [Select]
:102000003E02D340DB41FE04CA1820FE08CA1F204E
:10201000FEA0CA3020C304203E00D342C304203EA9
:1020200007D342CD42203E18D342CD4220C30420E4
:102030003E6FD62A325024F61F325F24CD9D03C353
:10204000042006FF3EFF3DC2462005C24420C9CF02
:00000001FF

Edit: Fixed error calculating checksum of hex file records

Edit 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: [Select]
// 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[0x10000];
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[0]);
        exit(0);
    }
    loadfile(argv[1]);
    dumphex(argv[2]);
}

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 record
    fclose(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);
    else
        skipRec(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); // Seg
        addr = 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: [Select]
set fname=%~n1
set 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



« Last Edit: January 03, 2020, 08:36:12 pm by jesuscf »
Homer: Kids, there's three ways to do things; the right way, the wrong way and the Max Power way!
Bart: Isn't that the wrong way?
Homer: Yeah, but faster!
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4668
  • Country: us
Re: 8085 Assembler?
« Reply #29 on: January 03, 2020, 02:22:23 am »
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)

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->