Skip to content

Commit

Permalink
Merge pull request #23 from Ho-Ro/master
Browse files Browse the repository at this point in the history
unique format; `mv *.cp *.cpp` (std ext for c++); update README.md
  • Loading branch information
sarnau authored Sep 16, 2024
2 parents 64688d4 + 26c161b commit 4ee7320
Show file tree
Hide file tree
Showing 13 changed files with 2,847 additions and 2,702 deletions.
94 changes: 94 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 132
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: true
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: true
SpacesInSquareBrackets: true
Standard: Cpp11
TabWidth: 8
UseTab: Never
...
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
CC=gcc
# CC=clang

CFLAGS=-I. -Wall

DEPS = z80_assembler.h kk_ihex_read.h kk_ihex_write.h Makefile

%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)

%.o: %.cp $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)

%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)

Expand Down
29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Z80 Disassembler

I created this small disassembler for a Z80 cpu at one afternoon. It is a commandline tool. The size of the ROM and entry points have to be coded directly in the sourcecode.

Every ANSI C++ compiler should compile this program. It only uses some ANSI C functions (look into `main()`).
Every ANSI C++ compiler should compile this program. It only uses some ANSI C functions (look into `main()`). Current program versions can be compiled successfully with `gcc` and `clang` w/o warnings.

The program has two parts:

Expand All @@ -33,7 +33,9 @@ I created the assembler for the Z80 a few days later to compile the changes code

This small assembler has some nice gadgets: it is a quite fast tokenizing single-pass assembler with backpatching. It knows all official Z80 opcodes and some undocumented opcodes (mainly with `IX` and `IY`). The Z80 syntax is documented in the Zilog documentation.

The assembler allows mathematical expressions in operands: `+`, `-`, `*`, `/`, `%` (modulo), `&` (and), `|` (or), `!` (not), `^` (xor), `<<` (shift left) and `>>` (shift right). Brackets are also available. The expression parser is located in `z80_calc.c`. Number can be postpended by a `D`, `H` or `B` for decimal, hexadecimal and binary numbers.
The assembler allows mathematical expressions in operands: `+`, `-`, `*`, `/`, `%` (modulo), `&` (and), `|` (or), `!` (not), `^` (xor), `<<` (shift left) and `>>` (shift right). Brackets are also available. The expression parser is located in `z80_calc.c`.
Numbers can be postpended by a `D`, `H` or `B` for decimal, hexadecimal and binary numbers.
Numbers prepended by a `$` are recognized as hex.

The assembler also knows the most commend pseudo opcodes (look into the sourcefile 'z80_tokenize.cp'):

Expand All @@ -45,17 +47,22 @@ The assembler also knows the most commend pseudo opcodes (look into the sourcefi
* `ORG` Set the PC in the 64k address space. E.g. to generate code for address $2000.
* `PRINT` Print the following text on the console. Great for testing the assembler.
* `EQU` or `=` Set a variable.
* `DEFB` Put a byte at the current address
* `DEFW` But a word at the current address (little endian!)
* `DEFM` But several bytes in the memory, starting at the current address. Seperated with a "," or a string.
* `DEFS` Set the current address n bytes ahead. Defines space for global variables that have no given value.
* `DEFB` or `DB` Put a byte at the current address
* `DEFW` or `DW` Put a word at the current address (little endian!)
* `DEFM` or `DM` Put a string or several bytes seperated with a ',' in the memory, starting at the current address.
* `DEFS` or `DS` Set the current address n bytes ahead. Defines space for global variables that have no given value.

The Sourcecode
--------------

* [z80_assembler.cp](z80_assembler.cp)
* [z80_assembler.cpp](z80_assembler.cpp)
* [z80_assembler.h](z80_assembler.h)
* [z80_calc.cp](z80_calc.cp)
* [z80_compile.cp](z80_compile.cp)
* [z80_disassembler.cp](z80_disassembler.cp)
* [z80_tokenize.cp](z80_tokenize.cp)
* [z80_calc.cpp](z80_calc.cpp)
* [z80_compile.cpp](z80_compile.cpp)
* [z80_disassembler.cpp](z80_disassembler.cpp)
* [z80_tokenize.cpp](z80_tokenize.cpp)
* [kk_ihex_read.c](kk_ihex_read.c)
* [kk_ihex_read.h](kk_ihex_read.h)
* [kk_ihex_write.c](kk_ihex_write.c)
* [kk_ihex_write.h](kk_ihex_write.h)
* [kk_ihex.h](kk_ihex.h)
105 changes: 52 additions & 53 deletions z80_assembler.cp → z80_assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
#include "kk_ihex_write.h"
#include "z80_assembler.h"

uint32_t PC; // current address
uint32_t nextPC; // remember address
uint8_t *RAM; // RAM of the Z80
uint32_t PC; // current address
uint32_t nextPC; // remember address
uint8_t *RAM; // RAM of the Z80
const uint32_t RAMSIZE = 0x10000;
uint32_t minPC = RAMSIZE;
uint32_t maxPC = 0;
bool listing = false;
uint32_t minPC = RAMSIZE;
uint32_t maxPC = 0;
bool listing = false;

static FILE *infile;
static FILE *outbin;
Expand All @@ -27,21 +27,20 @@ static FILE *outhex;

int verboseMode = 0;

long LineNo; // current line number
char LineBuf[MAXLINELENGTH]; // buffer for the current line
long LineNo; // current line number
char LineBuf[ MAXLINELENGTH ]; // buffer for the current line

/***
* print fatal error message and exit
***/
void Error(const char* s)
{
const char *p;

printf("Error in line %ld: %s\n",LineNo,s);
for(p = LineBuf;isspace(*p);p++)
;
puts(p);
exit(1);
void Error( const char *s ) {
const char *p;

printf( "Error in line %ld: %s\n", LineNo, s );
for ( p = LineBuf; isspace( *p ); p++ )
;
puts( p );
exit( 1 );
}


Expand All @@ -68,10 +67,9 @@ static void write_header( FILE *stream, uint32_t address );
/***
* …
***/
int main( int argc, char **argv )
{
int main( int argc, char **argv ) {
char *inputfilename = nullptr;
char outputfilename[PATH_MAX];
char outputfilename[ PATH_MAX ];

char *oneLine;
int i, j;
Expand All @@ -84,9 +82,9 @@ int main( int argc, char **argv )
bool no_outfile = false;


puts("TurboAss Z80 - a small 1-pass assembler for Z80 code");
puts("(c)1992/3 Sigma-Soft, Markus Fritze");
puts("");
puts( "TurboAss Z80 - a small 1-pass assembler for Z80 code" );
puts( "(c)1992/3 Sigma-Soft, Markus Fritze" );
puts( "" );


for ( i = 1, j = 0; i < argc; i++ ) {
Expand Down Expand Up @@ -114,7 +112,7 @@ int main( int argc, char **argv )
case 'n': // parse program flow
no_outfile = true;
break;
case 'o': // program offset
case 'o': // program offset
if ( argv[ i ][ ++j ] ) // "-oXXXX"
result = sscanf( argv[ i ] + j, "%x", &offset );
else if ( i < argc - 1 ) // "-o XXXX"
Expand Down Expand Up @@ -162,33 +160,34 @@ int main( int argc, char **argv )
MSG( 1, "Processing infile \"%s\"\n", inputfilename );

LineNo = 1;
InitSymTab(); // init symbol table
InitSymTab(); // init symbol table

RAM = (uint8_t*)malloc(RAMSIZE+256);// guard against overflow at ram top
memset(RAM, fill, RAMSIZE); // erase 64K RAM
PC = 0x0000; // default start address of the code
RAM = (uint8_t *)malloc( RAMSIZE + 256 ); // guard against overflow at ram top
memset( RAM, fill, RAMSIZE ); // erase 64K RAM
PC = 0x0000; // default start address of the code

while( true ) {
while ( true ) {
uint32_t prevPC = PC;
oneLine = fgets(LineBuf,sizeof(LineBuf),infile); // read a single line
if(!oneLine) break; // end of the code => exit
*(oneLine + strlen(oneLine) - 1) = 0; // remove end of line marker
TokenizeLine( oneLine ); // tokenize line
CompileLine(); // generate machine code for the line
listOneLine( prevPC, PC, oneLine ); // create listing if enabled
LineNo++; // next line
oneLine = fgets( LineBuf, sizeof( LineBuf ), infile ); // read a single line
if ( !oneLine )
break; // end of the code => exit
*( oneLine + strlen( oneLine ) - 1 ) = 0; // remove end of line marker
TokenizeLine( oneLine ); // tokenize line
CompileLine(); // generate machine code for the line
listOneLine( prevPC, PC, oneLine ); // create listing if enabled
LineNo++; // next line
}
list( "\n" );
fclose( infile );

// cross reference
for(i=0;i<256;i++) { // iterate over symbol table
SymbolP s;
for(s = SymTab[i];s;s = s->next)
if(s->recalc) // depend expressions on a symbol?
printf("---- %s is undefined!\n",s->name);
for ( i = 0; i < 256; i++ ) { // iterate over symbol table
SymbolP s;
for ( s = SymTab[ i ]; s; s = s->next )
if ( s->recalc ) // depend expressions on a symbol?
printf( "---- %s is undefined!\n", s->name );
else if ( !s->type )
list("%04X%*s\n", s->val, 20 + int( strlen( s->name ) ), s->name );
list( "%04X%*s\n", s->val, 20 + int( strlen( s->name ) ), s->name );
}

if ( minPC < 0x100 || maxPC <= 0x100 ) // cannot be a CP/M com file
Expand All @@ -204,28 +203,28 @@ int main( int argc, char **argv )
}

if ( !no_outfile && strlen( inputfilename ) > 4 && !strcmp( inputfilename + strlen( inputfilename ) - 4, ".asm" ) ) {
strncpy(outputfilename, inputfilename, sizeof(outputfilename));
strncpy( outputfilename, inputfilename, sizeof( outputfilename ) );

// create out file name(s) from in file name
size_t fnamelen = strlen( outputfilename );
// bin or com (=bin file that starts at PC=0x100) file
strncpy( outputfilename + fnamelen - 3, com ? "com" : "bin", sizeof(outputfilename) -fnamelen - 3 );
strncpy( outputfilename + fnamelen - 3, com ? "com" : "bin", sizeof( outputfilename ) - fnamelen - 3 );
MSG( 1, "Creating output file %s\n", outputfilename );
outbin = fopen( outputfilename, "wb" );
if ( !outbin ) {
fprintf( stderr, "Error: Can't open output file \"%s\".\n", outputfilename );
return 1;
}
// z80 file is a bin file with a header telling the file offset
strncpy( outputfilename + fnamelen - 3, "z80", sizeof(outputfilename) -fnamelen - 3 );
strncpy( outputfilename + fnamelen - 3, "z80", sizeof( outputfilename ) - fnamelen - 3 );
MSG( 1, "Creating output file %s\n", outputfilename );
outz80 = fopen( outputfilename, "wb" );
if ( !outz80 ) {
fprintf( stderr, "Error: Can't open output file \"%s\".\n", outputfilename );
return 1;
}
// intel hex file
strncpy( outputfilename + fnamelen - 3, "hex", sizeof(outputfilename) -fnamelen - 3 );
strncpy( outputfilename + fnamelen - 3, "hex", sizeof( outputfilename ) - fnamelen - 3 );
MSG( 1, "Creating output file %s\n", outputfilename );
outhex = fopen( outputfilename, "wb" );
if ( !outhex ) {
Expand All @@ -237,7 +236,7 @@ int main( int argc, char **argv )
exit( 0 );
}
if ( outbin ) {
if ( com )
if ( com )
fwrite( RAM + 0x100, sizeof( uint8_t ), maxPC + 1 - 0x100, outbin );
else
fwrite( RAM + offset, sizeof( uint8_t ), maxPC + 1 - offset, outbin );
Expand All @@ -264,8 +263,8 @@ int main( int argc, char **argv )
void checkPC( uint32_t pc ) {
MSG( 3, "checkPC( %04X )", pc );
if ( pc >= RAMSIZE ) {
Error("Address overflow -> exit");
exit(0);
Error( "Address overflow -> exit" );
exit( 0 );
}
if ( pc < minPC )
minPC = pc;
Expand Down Expand Up @@ -303,7 +302,7 @@ static void listOneLine( uint32_t firstPC, uint32_t lastPC, const char *oneLine
if ( !listing )
return;
if ( firstPC == lastPC ) {
printf( "%*s\n", 24 + int(strlen( oneLine ) ), oneLine );
printf( "%*s\n", 24 + int( strlen( oneLine ) ), oneLine );
} else {
printf( "%4.4X ", firstPC );
uint32_t adr = firstPC;
Expand All @@ -312,16 +311,16 @@ static void listOneLine( uint32_t firstPC, uint32_t lastPC, const char *oneLine
printf( " %2.2X", RAM[ adr++ ] );
if ( i == 3 )
printf( " %s", oneLine );
if ( (i & 3) == 3 ) {
if ( ( i & 3 ) == 3 ) {
printf( "\n" );
if ( adr < lastPC )
printf( "%4.4X ", adr );
}
++i;
}
if ( i < 4 )
printf( "%*s\n", 5+3*(4-i)+int(strlen( oneLine ) ), oneLine );
else if ( (i & 3) )
printf( "%*s\n", 5 + 3 * ( 4 - i ) + int( strlen( oneLine ) ), oneLine );
else if ( ( i & 3 ) )
printf( "\n" );
}
}
Expand Down
Loading

0 comments on commit 4ee7320

Please sign in to comment.