Compare commits

...

35 Commits

Author SHA1 Message Date
Piotr Fusik 9732817a0b Modernize the RPM spec. 2023-07-11 10:56:46 +02:00
Piotr Fusik 70c907bae6 Revert "Warn about a comment starting with a comma."
Breaks Jaskier's MPT player.
https://sourceforge.net/p/asap/bugs/32/

This reverts commit 7a666799ac.
2023-05-07 21:03:40 +02:00
Piotr Fusik 7a666799ac Warn about a comment starting with a comma. 2023-02-28 16:59:52 +01:00
Piotr Skamruk 95136d1546 Tune variable/func names after sequencing support added 2022-12-20 15:52:39 +01:00
Piotr Fusik ca5e88950f xasm 3.2.1 release. 2022-12-08 11:49:40 +01:00
Piotr Fusik 138331193a DMD seems to no longer append ".exe". 2022-12-08 09:53:32 +01:00
Piotr Fusik 30c96357bc Allow stdout for the listing and label table. 2022-12-08 09:27:19 +01:00
Jakub Husak 83d2f8ff1d Refactor LDA and STA with existing routines. 2022-12-02 15:23:07 +01:00
Adrian Matoga 9aae1ad4c4 Instruction pairing extended to more than two instructions. 2022-11-30 10:11:12 +01:00
Piotr Fusik f33c112ac6 Switch CI from Travis to GitHub Actions.
Close #10
2022-11-29 14:08:39 +01:00
Piotr Fusik 57661276c2 Fix "Error processing arguments: Missing value for argument --compiler=". 2022-11-29 14:04:51 +01:00
Piotr Fusik a4225b6128 GitHub Actions don't know gdc. 2022-11-29 14:01:33 +01:00
Piotr Fusik 1da9f77458 Add the missing part of GitHub Actions. 2022-11-29 13:59:41 +01:00
Piotr Fusik 2b7d21ae43 Continuous Integration with GitHub Actions. 2022-11-29 13:51:14 +01:00
Adrian Matoga 2f67b3bab4 Allow stdin/stdout instead of files for source and object. 2022-11-29 11:22:55 +01:00
Piotr Fusik afb9f7830e Update DEB packaging. 2022-07-23 11:45:14 +02:00
Piotr Fusik 95cb5ae592 install-scite non-executable. 2021-12-23 16:43:11 +01:00
Piotr Fusik 8f6621f079 Update DEB packaging. 2021-12-23 16:41:52 +01:00
Piotr Fusik 52982169df xasm 3.2.0 release. 2021-06-22 21:20:00 +02:00
Piotr Fusik 8c7ef1a922 Reword the manual. 2021-06-21 22:44:34 +02:00
Piotr Fusik 1a90ca04d3 Bump the copyright year. 2021-06-21 22:42:13 +02:00
Piotr Fusik 73b382f9b7 Fix macOS notarization. 2021-06-21 22:40:50 +02:00
Piotr Fusik 7ba3f9f597 Signed the Windows binary. 2021-06-20 19:01:53 +02:00
Piotr Fusik b815a448cd Migrate to travis-ci.com. 2021-06-16 09:11:04 +02:00
Piotr Fusik 274dda9dd2 Wait for macOS notarization. 2021-06-04 21:50:23 +02:00
Piotr Fusik da58ad7950 Sign and notarize the macOS binary. 2021-06-04 21:38:25 +02:00
Piotr Fusik 52ef8c05d6 OPT ?+ for MADS compatibility. 2021-03-25 09:03:23 +01:00
Piotr Fusik 6f25038d95 On macOS install in /usr/local/bin.
Close #8
2021-03-24 10:49:14 +01:00
Adrian Matoga 57ef9b5c83 Fix failed assertion when opt l+ is used 2021-03-15 07:18:15 +01:00
Adrian Matoga 8f06fec50c Enable simple local labels. 2021-03-14 19:46:09 +01:00
Piotr Fusik d50d484e1f Update DEB packaging. 2020-10-29 20:07:35 +01:00
Piotr Fusik 65a2c1fbdd Deprecate DOS-style options. 2020-05-25 21:36:28 +02:00
Piotr Fusik d3908ec95e Don't report error deleting the object file on error.
Most likely the file doesn't exist.
2020-05-21 19:38:49 +02:00
Piotr Fusik 647cf9f3cf Don't cast to arrays of mutable bytes. 2019-12-04 23:23:47 +01:00
Piotr Fusik 819701b9be Optimize moving negative immediate word. 2019-12-04 23:16:21 +01:00
13 changed files with 340 additions and 221 deletions

16
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: tests
on: [push, pull_request]
jobs:
test:
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
dc: [dmd-latest, ldc-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@main
- uses: dlang-community/setup-dlang@v1
with:
compiler: ${{ matrix.dc }}
- run: dub build
- run: dub test

1
.gitignore vendored
View File

@ -7,3 +7,4 @@
/MANIFEST
/.dub
/.project
/signed

View File

@ -1,5 +0,0 @@
language: d
d:
- dmd
- gdc
- ldc

View File

@ -1,14 +1,17 @@
VERSION = 3.1.1
VERSION = 3.2.1
prefix = /usr/local
bindir = $(prefix)/bin
mandir = $(prefix)/share/man/man1
ifeq ($(OS),Windows_NT)
EXEEXT = .exe
endif
SEVENZIP = 7z a -mx=9 -bd -bso0
all: xasm xasm.html
all: xasm$(EXEEXT) xasm.html
xasm: source/app.d
xasm$(EXEEXT): source/app.d
dmd -of$@ -O -release $<
xasm.html: xasm.1.asciidoc
@ -25,7 +28,7 @@ uninstall:
$(RM) $(DESTDIR)$(bindir)/xasm $(DESTDIR)$(mandir)/xasm.1
install-scite: xasm.properties
mkdir -p $(DESTDIR)$(prefix)/share/scite && install $< $(DESTDIR)$(prefix)/share/scite/xasm.properties
mkdir -p $(DESTDIR)$(prefix)/share/scite && install -m 644 $< $(DESTDIR)$(prefix)/share/scite/xasm.properties
uninstall-scite:
$(RM) $(DESTDIR)$(prefix)/share/scite/xasm.properties
@ -38,25 +41,35 @@ srcdist: MANIFEST
MANIFEST:
if test -e .git; then (git ls-files | grep -vF .gitignore && echo MANIFEST) | sort | dos2unix >$@ ; fi
../xasm-$(VERSION)-windows.zip: xasm xasm.html xasm.properties
../xasm-$(VERSION)-windows.zip: xasm.exe xasm.html xasm.properties signed
$(RM) $@ && $(SEVENZIP) -tzip $@ xasm.exe xasm.html xasm.properties
signed: xasm$(EXEEXT)
signtool sign -d "xasm $(VERSION)" -n "Open Source Developer, Piotr Fusik" -tr http://time.certum.pl -fd sha256 -td sha256 $< && touch $@
deb:
debuild -b -us -uc
osx: ../xasm-$(VERSION)-macos.dmg
../xasm-$(VERSION)-macos.dmg: osx/xasm osx/bin
ifdef PORK_CODESIGNING_IDENTITY
codesign --options runtime -f -s $(PORK_CODESIGNING_IDENTITY) osx/xasm
endif
hdiutil create -volname xasm-$(VERSION)-macos -srcfolder osx -format UDBZ -fs HFS+ -imagekey bzip2-level=3 -ov $@
ifdef PORK_NOTARIZING_CREDENTIALS
xcrun altool --notarize-app --primary-bundle-id com.github.pfusik.xasm $(PORK_NOTARIZING_CREDENTIALS) --file $@ \
| perl -pe 's/^RequestUUID =/xcrun altool $$ENV{PORK_NOTARIZING_CREDENTIALS} --notarization-info/ or next; $$c = $$_; until (/Status: success/) { sleep 20; $$_ = `$$c`; print; } last;'
endif
osx/xasm: source/app.d
mkdir -p osx && dmd -of$@ -O -release -L-macosx_version_min -L10.6 $< && rm -f osx/xasm.o
mkdir -p osx && dmd -of$@ -O -release $< && rm -f osx/xasm.o
osx/bin:
mkdir -p osx && ln -s /usr/bin $@
mkdir -p osx && ln -s /usr/local/bin $@
clean:
$(RM) xasm xasm.exe xasm.obj xasm.html xasm.1
$(RM) xasm xasm.exe xasm.obj xasm.html xasm.1 signed
rm -rf osx
.PHONY: all install uninstall install-scite uninstall-scite dist srcdist MANIFEST deb osx clean

View File

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/pfusik/xasm.svg?branch=master)](https://travis-ci.org/pfusik/xasm)
[![GitHub Actions](https://github.com/pfusik/xasm/actions/workflows/test.yml/badge.svg)](https://github.com/pfusik/xasm/actions/workflows/test.yml)
xasm
====
@ -99,7 +99,7 @@ These rights, on this notice, rely.
Download
--------
[xasm 3.1.1](https://github.com/pfusik/xasm/releases) for Windows, macOS, Ubuntu and Fedora.
[xasm 3.2.1](https://github.com/pfusik/xasm/releases) for Windows, macOS, Ubuntu and Fedora.
Links
-----

12
debian/changelog vendored
View File

@ -1,3 +1,15 @@
xasm (3.2.1-1) UNRELEASED; urgency=low
* New release.
-- Piotr Fusik <fox@scene.pl> Thu, 8 Dec 2022 09:30:29 +0100
xasm (3.2.0-1) UNRELEASED; urgency=low
* New release.
-- Piotr Fusik <fox@scene.pl> Tue, 22 Jun 2021 20:59:45 +0200
xasm (3.1.1-1) UNRELEASED; urgency=low
* New release.

2
debian/compat vendored
View File

@ -1 +1 @@
9
10

6
debian/control vendored
View File

@ -2,13 +2,13 @@ Source: xasm
Maintainer: Piotr Fusik <fox@scene.pl>
Section: devel
Priority: optional
Standards-Version: 3.9.3
Build-Depends: debhelper (>= 7), dmd (>= 2), asciidoc
Standards-Version: 4.6.0
Build-Depends: debhelper (>= 7), dmd (>= 2), asciidoc-base
Package: xasm
Architecture: any
Depends: ${shlibs:Depends}
Description: A 6502 cross-assembler with original syntax extensions.
Description: 6502 cross-assembler with original syntax extensions.
Package: xasm-scite
Architecture: all

4
debian/copyright vendored
View File

@ -1,7 +1,7 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Name: xasm
Source: https://github.com/pfusik/xasm
Files: *
Copyright: 1998-2014 Piotr Fusik <fox@scene.pl>
Copyright: 1998-2021 Piotr Fusik <fox@scene.pl>
License: Poetic

View File

@ -1,5 +1,5 @@
name "xasm"
description "6502 cross-assembler with original syntax extensions"
authors "Piotr Fusik"
copyright "Copyright © 1998-2019, Piotr Fusik"
copyright "Copyright © 1998-2021, Piotr Fusik"
license "poetic"

View File

@ -1,6 +1,6 @@
// xasm 3.1.1 by Piotr Fusik <fox@scene.pl>
// xasm 3.2.1 by Piotr Fusik <fox@scene.pl>
// http://xasm.atari.org
// Can be compiled with DMD v2.089.0.
// Can be compiled with DMD v2.101.0.
// Poetic License:
//
@ -18,24 +18,23 @@
import std.algorithm;
import std.array;
import std.ascii;
import std.conv;
import std.file;
import std.math;
import std.path;
import std.stdio;
import std.string;
import std.exception : assumeUnique;
import std.range : empty, front, popFront;
version (Windows) {
import core.sys.windows.windows;
}
int readByte(File *file) {
char c;
if (file.readf("%c", &c) != 1)
return -1;
return c;
}
const string TITLE = "xasm 3.2.1";
const string TITLE = "xasm 3.1.1";
File messageStream;
string sourceFilename = null;
bool[26] options;
@ -43,6 +42,7 @@ string[26] optionParameters;
string[] commandLineDefinitions = null;
string objectFilename = null;
string[] makeSources = null;
immutable(ubyte)[][string] sourceFiles;
int exitCode = 0;
@ -84,6 +84,7 @@ class Label {
Label[string] labelTable;
Label currentLabel;
string lastGlobalLabel;
alias int function(int a, int b) OperatorFunction;
@ -138,7 +139,7 @@ bool repeating; // line
int repeatCounter; // line
bool instructionBegin;
bool pairing;
bool sequencing;
bool willSkip;
bool skipping;
@ -173,13 +174,14 @@ File objectStream;
int objectBytes = 0;
bool getOption(char letter) {
assert(letter >= 'a' && letter <= 'z');
return options[letter - 'a'];
}
void warning(string msg, bool error = false) {
stdout.flush();
messageStream.flush();
version (Windows) {
HANDLE stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
@ -260,21 +262,23 @@ void readSpaces() {
}
string readLabel() {
string label;
int firstColumn = column;
while (!eol()) {
char c = line[column++];
if (c >= '0' && c <= '9' || c == '_') {
label ~= c;
if (c >= '0' && c <= '9' || c == '_' || c == '?')
continue;
}
c &= 0xdf;
if (c >= 'A' && c <= 'Z') {
label ~= c;
if (c >= 'A' && c <= 'Z')
continue;
}
column--;
break;
}
string label = line[firstColumn .. column].toUpper;
if (label.startsWith('?')) {
if (lastGlobalLabel is null)
throw new AssemblyError("Global label must be declared first");
label = lastGlobalLabel ~ label;
}
return label >= "A" ? label : null;
}
@ -1081,8 +1085,10 @@ File openInputFile(string filename) {
}
File openOutputFile(string filename, string msg) {
if (filename == "-")
return stdout;
if (!getOption('q'))
writeln(msg);
messageStream.writeln(msg);
try {
return File(filename, "wb");
} catch (Exception e) {
@ -1323,7 +1329,7 @@ void directive() {
noOpcode();
if (repeating)
throw new AssemblyError("Can't repeat this directive");
if (pairing)
if (sequencing)
throw new AssemblyError("Can't pair this directive");
}
@ -1707,7 +1713,7 @@ void assemblyMoveWord(MoveFunction load, MoveFunction store, ubyte inc, ubyte de
}
switch (addrMode1) {
case AddrMode.IMMEDIATE:
int high = value1 >> 8;
int high = value1 >> 8 & 0xff;
value1 &= 0xff;
load(1);
store(2);
@ -1716,9 +1722,9 @@ void assemblyMoveWord(MoveFunction load, MoveFunction store, ubyte inc, ubyte de
value1 = high;
load(1);
} else {
if (inc != 0 && cast(ubyte) (value1 + 1) == high)
if (inc != 0 && (value1 + 1 & 0xff) == high)
putByte(inc);
else if (dec != 0 && cast(ubyte) (value1 - 1) == high)
else if (dec != 0 && (value1 - 1 & 0xff) == high)
putByte(dec);
else if (value1 != high) {
value1 = high;
@ -2156,7 +2162,7 @@ void assemblyOpt() {
break;
case 'L':
case 'l':
optionListing = readOption() && !pass2;
optionListing = readOption() && pass2;
break;
case 'O':
case 'o':
@ -2166,6 +2172,10 @@ void assemblyOpt() {
case 'u':
optionUnusedLabels = readOption();
break;
case '?':
if (!readOption())
throw new AssemblyError("OPT ?- not supported");
break;
default:
column--;
return;
@ -2293,7 +2303,6 @@ void assemblyIns() {
}
}
File stream = openInputFile(filename);
scope (exit) stream.close();
try {
stream.seek(offset, offset >= 0 ? SEEK_SET : SEEK_END);
} catch (Exception e) {
@ -2302,13 +2311,13 @@ void assemblyIns() {
if (inOpcode)
length = 1;
while (length != 0) {
int b = readByte(&stream);
if (b < 0) {
ubyte[1] b;
if (stream.rawRead(b).length != 1) {
if (length > 0)
throw new AssemblyError("File is too short");
break;
}
putByte(cast(ubyte) b);
putByte(b[0]);
if (length > 0) length--;
}
}
@ -2469,7 +2478,7 @@ void assemblyInstruction(string instruction) {
assemblyConditionalJump(0x50);
break;
case "LDA":
assemblyAccumulator(0xa0, 0, 0);
assemblyLda(0);
break;
case "LDX":
assemblyLdx(0);
@ -2592,7 +2601,7 @@ void assemblyInstruction(string instruction) {
assemblySkip(0x10);
break;
case "STA":
assemblyAccumulator(0x80, 0, 0);
assemblySta(0);
break;
case "STX":
assemblyStx(0);
@ -2642,32 +2651,38 @@ version (unittest) ubyte[] testInstruction(string l) {
}
unittest {
assert(testInstruction("nop") == cast(ubyte[]) hexString!"ea");
assert(testInstruction("add (5,0)") == cast(ubyte[]) hexString!"18a2006105");
assert(testInstruction("mwa #$abcd $1234") == cast(ubyte[]) hexString!"a9cd8d3412a9ab8d3512");
assert(testInstruction("dta 5,d'Foo'*,a($4589)") == cast(ubyte[]) hexString!"05a6efef8945");
assert(testInstruction("nop") == representation(hexString!"ea"));
assert(testInstruction("add (5,0)") == representation(hexString!"18a2006105"));
assert(testInstruction("mwa #$abcd $1234") == representation(hexString!"a9cd8d3412a9ab8d3512"));
assert(testInstruction("mwx #-256 $80") == representation(hexString!"a2008680ca8681"));
assert(testInstruction("dta 5,d'Foo'*,a($4589)") == representation(hexString!"05a6efef8945"));
assert(testInstruction("dta r(1,12,123,1234567890,12345678900000,.5,.03,000.1664534589,1e97)")
== cast(ubyte[]) hexString!"400100000000 401200000000 410123000000 441234567890 461234567890 3f5000000000 3f0300000000 3f1664534589 701000000000");
== representation(hexString!"400100000000 401200000000 410123000000 441234567890 461234567890 3f5000000000 3f0300000000 3f1664534589 701000000000"));
}
void assemblyPair() {
void assemblySequence() {
assert(!inOpcode);
string instruction = readInstruction();
if (!eol() && line[column] == ':') {
pairing = true;
string[] extraInstructions;
while (!eol() && line[column] == ':') {
sequencing = true;
column++;
string instruction2 = readInstruction();
extraInstructions ~= readInstruction();
}
if (!extraInstructions.empty) {
int savedColumn = column;
if (willSkip)
warning("Skipping only the first instruction");
assemblyInstruction(instruction);
checkNoExtraCharacters();
column = savedColumn;
wereManyInstructions = false;
assemblyInstruction(instruction2);
wereManyInstructions = true;
foreach (nextInstruction; extraInstructions) {
column = savedColumn;
assemblyInstruction(nextInstruction);
wereManyInstructions = true;
}
} else {
pairing = false;
sequencing = false;
assemblyInstruction(instruction);
wereManyInstructions = false;
}
@ -2686,6 +2701,8 @@ void assemblyLine() {
currentLabel = null;
if (label !is null) {
if (!inFalseCondition()) {
if (!label.canFind('?'))
lastGlobalLabel = label;
if (!pass2) {
if (label in labelTable)
throw new AssemblyError("Label declared twice");
@ -2742,7 +2759,7 @@ void assemblyLine() {
int savedColumn = column;
for (repeatCounter = 0; repeatCounter < repeatLimit; repeatCounter++) {
column = savedColumn;
assemblyPair();
assemblySequence();
}
checkNoExtraCharacters();
listLine();
@ -2778,17 +2795,23 @@ void assemblyLine() {
listCommentLine();
return;
}
assemblyPair();
assemblySequence();
checkNoExtraCharacters();
listLine();
}
void assemblyFile(string filename) {
filename = filename.defaultExtension("asx");
if (getOption('p'))
filename = absolutePath(filename);
File stream = openInputFile(filename);
scope (exit) stream.close();
immutable(ubyte)[] source = sourceFiles.require(filename, {
File stream = stdin;
if (filename != "-") {
filename = filename.defaultExtension("asx");
if (getOption('p'))
filename = absolutePath(filename);
stream = openInputFile(filename);
}
return stream.byChunk(65536).joiner.array.assumeUnique;
}());
string oldFilename = currentFilename;
int oldLineNo = lineNo;
currentFilename = filename;
@ -2796,16 +2819,18 @@ void assemblyFile(string filename) {
foundEnd = false;
line = "";
readChar: while (!foundEnd) {
int b = readByte(&stream);
if (source.empty)
break;
ubyte b = source.front;
source.popFront;
switch (b) {
case -1:
break readChar;
case '\r':
assemblyLine();
line = "";
b = readByte(&stream);
if (b < 0)
if (source.empty)
break readChar;
b = source.front;
source.popFront;
if (b != '\n')
line ~= cast(char) b;
break;
@ -2826,6 +2851,16 @@ void assemblyFile(string filename) {
lineNo = oldLineNo;
}
unittest {
sourceFiles[""] = " lda:sne:ldy:inx $1234".representation;
assemblyFile("");
pass2 = true;
objectBuffer.length = 0;
assemblyFile("");
writefln!"%(%02x%)"(objectBuffer);
assert(objectBuffer == [0xad, 0x34, 0x12, 0xd0, 0x03, 0xac, 0x34, 0x12, 0xe8]);
}
void assemblyPass() {
origin = -1;
loadOrigin = -1;
@ -2932,27 +2967,31 @@ int main(string[] args) {
else {
if (sourceFilename is null)
exitCode = 3;
objectFilename = optionParameters['o' - 'a'];
if (objectFilename is null) {
objectFilename = sourceFilename == "-"
? "-"
: sourceFilename.setExtension("obx");
}
messageStream = objectFilename == "-" ? stderr : stdout;
if (!getOption('q'))
writeln(TITLE);
messageStream.writeln(TITLE);
if (exitCode != 0) {
write(
`Syntax: xasm source [options]
/c Include false conditionals in listing
/d:label=value Define a label
/i Don't list included files
/l[:filename] Generate listing
/o:filename Set object file name
/M Print Makefile rule
/p Print absolute paths in listing and error messages
/q Suppress info messages
/t[:filename] List label table
/u Warn of unused labels
messageStream.write(
`Syntax: xasm SOURCE [OPTIONS]
-c Include false conditionals in listing
-d LABEL=VALUE Define a label
-i Don't list included files
-l [FILENAME] Generate listing
-o FILENAME Set object file name
-M Print Makefile rule
-p Print absolute paths in listing and error messages
-q Suppress info messages
-t [FILENAME] List label table
-u Warn of unused labels
`);
return exitCode;
}
objectFilename = optionParameters['o' - 'a'];
if (objectFilename is null)
objectFilename = sourceFilename.setExtension("obx");
try {
assemblyPass();
pass2 = true;
@ -2962,22 +3001,26 @@ int main(string[] args) {
} catch (AssemblyError e) {
warning(e.msg, true);
exitCode = 2;
objectStream.close();
remove(objectFilename);
if (objectFilename != "-") {
objectStream.close();
core.stdc.stdio.remove(toStringz(objectFilename));
}
}
listingStream.close();
objectStream.close();
if (listingStream != stdout)
listingStream.close();
if (objectStream != stdout)
objectStream.close();
if (exitCode <= 1) {
if (!getOption('q')) {
writefln("%d lines of source assembled", totalLines);
messageStream.writefln("%d lines of source assembled", totalLines);
if (objectBytes > 0)
writefln("%d bytes written to the object file", objectBytes);
messageStream.writefln("%d bytes written to the object file", objectBytes);
}
if (getOption('m')) {
writef("%s:", makeEscape(objectFilename));
messageStream.writef("%s:", makeEscape(objectFilename));
foreach (filename; makeSources)
writef(" %s", makeEscape(filename));
write("\n\txasm");
messageStream.writef(" %s", makeEscape(filename));
messageStream.write("\n\txasm");
for (int i = 1; i < args.length; i++) {
string arg = args[i];
if (isOption(arg)) {
@ -2989,9 +3032,9 @@ int main(string[] args) {
break;
case 'o':
if (arg[0] == '/')
writef(" /%c:$@", arg[1]);
messageStream.writef(" /%c:$@", arg[1]);
else {
writef(" -%c $@", arg[1]);
messageStream.writef(" -%c $@", arg[1]);
++i;
}
break;
@ -2999,18 +3042,18 @@ int main(string[] args) {
if (arg[0] == '-'
&& (letter == 'd' || letter == 'l' || letter == 't')
&& i + 1 < args.length && !isOption(args[i + 1])) {
writef(" %s %s", arg, makeEscape(args[++i]));
messageStream.writef(" %s %s", arg, makeEscape(args[++i]));
}
else {
writef(" %s", makeEscape(arg));
messageStream.writef(" %s", makeEscape(arg));
}
break;
}
continue;
}
write(" $<");
messageStream.write(" $<");
}
writeln();
messageStream.writeln();
}
}
return exitCode;

View File

@ -16,6 +16,7 @@ DESCRIPTION
'SOURCE_FILE' is the name of the source file
(you may omit the default `.asx` extension).
Using '-' as 'SOURCE_FILE' makes *xasm* read from standard input.
When invoked without any options, *xasm* assembles 'SOURCE_FILE'
and writes the result to an object file named 'SOURCE_FILE'
with the extension changed to `.obx`.
@ -23,56 +24,61 @@ with the extension changed to `.obx`.
OPTIONS
-------
*/c*::
Specifies that lines skipped due to a false condition
should be included in the listing file.
*-c*::
The listing should include conditionally skipped lines.
[[new_deflabel]]*/d:*'LABEL'='VALUE'::
[[new_deflabel]]*-d* 'LABEL'='VALUE'::
Defines a label.
'LABEL' should be a valid label name.
'VALUE' may be any expression (may reference to labels defined in source files).
You may use several */d* options to define many labels from the command line.
'VALUE' may be any expression (potentially referencing labels defined in source files).
You may use several *-d* options to define many labels on the command line.
*/i*::
Excludes included files from the listing file.
*-i*::
The listing file should exclude included files.
*/l*'[:LISTING_FILE]'::
Generates listing file.
*-l* '[LISTING_FILE]'::
Generates a listing file.
Using '-' as 'LISTING_FILE' makes *xasm* write to standard output.
If 'LISTING_FILE' is omitted, the listing filename
is 'SOURCE_FILE' with the extension changed to `.lst`.
[[new_makefile]]*/M*::
Prints a rule for use in a `Makefile`.
[[new_makefile]]*-M*::
Prints a `Makefile` rule.
First line of the rule lists 'OBJECT_FILE' as the target of the rule
and all source files (including the ones specified with `icl` and `ins` directives)
as dependencies. The second line contains the command line with `OBJECT_FILE`
replaced by the *make* macro `$@` and `SOURCE_FILE` replaced by the macro `$<`.
Dollars in the command line are doubled.
Your `make` or shell may require further escaping.
and all source files (including the ones specified with `icl` and `ins`) as dependencies.
The second line contains the command line with 'OBJECT_FILE'
replaced by the *make* macro `$@` and 'SOURCE_FILE' replaced by the macro `$<`.
Dollar signs in the command line are doubled.
Your *make* or shell may require further escaping.
*/o*':OBJECT_FILE'::
*-o* 'OBJECT_FILE'::
Sets output file name.
The default is 'SOURCE_FILE' with the extension changed to `.obx`.
Using '-' as 'OBJECT_FILE' makes *xasm* write to standard output.
The default is 'SOURCE_FILE' with the extension changed to `.obx`, or
standard output if standard input was specified as source.
[[new_fullpaths]]*/p*::
[[new_fullpaths]]*-p*::
Prints absolute paths in listing and error messages.
[[new_quiet]]*/q*::
[[new_quiet]]*-q*::
Quiet mode. Prevents *xasm* from printing its banner and compilation summary.
*/t*'[:LABEL_FILE]'::
Generates label table.
*-t* '[LABEL_FILE]'::
Generates a label table.
Using '-' as 'LABEL_FILE' makes *xasm* write to standard output.
If 'LABEL_FILE' is omitted then the table is appended at the end of the listing.
[[new_unlabels]]*/u*::
Issues a warning message for each label whose value is unused.
[[new_unlabels]]*-u*::
Issues warnings for unreferenced labels.
Alternatively, you may use Unix-style options, for example:
Alternatively, you may use DOS-style options, for example:
-----------------------------------------------------------
xasm -i -d DEBUG=1 -l listing.lst source.asx
xasm /i /d:DEBUG=1 /l:listing.lst source.asx
-----------------------------------------------------------
These are deprecated because they are incompatible with https://www.msys2.org[MSYS2].
SYNTAX
------
@ -81,19 +87,41 @@ LF, CR, CR/LF and Atari ($9b) line terminators are supported.
Labels and instructions are case-insensitive.
*xasm* is backward compatible with Quick Assembler.
To compile QA sources with *xasm*, simply replace ATASCII-specific characters
with their integer codes. You also have to update all `OPT` directives,
but usually you can simply remove them.
To compile QA sources with *xasm*, simply replace ATASCII characters
in string literals with the corresponding integers.
Also update all `OPT` directives, but often you can omit them.
'Label' is a symbol that represents a signed 32-bit integer.
A 'label' is a symbol that represents a signed 32-bit integer.
You define a label by putting its name at the beginning of a line
(with no spaces before).
The label will be assigned the current value of the 'origin counter'
(i.e. the address of the compiled instruction),
unless you use it with the `EQU` directive where it is assigned
the value of the `EQU` argument.
(that is, the address of the compiled instruction),
unless you use it with the `EQU` directive to assign the specified value.
Instructions and directives must be preceded with some whitespace.
[[new_locallabel]]
Any label name starting with a `?` (question mark) is a 'local label'.
It is implicitly prefixed with the name of the most recently defined
'global label' (that is, a label without any `?` in name),
and remains visible until another global label is defined.
It is still possible to access a local label from anywhere in the source
by specifying its full name.
Local labels provide a way to reuse common, short label names while keeping
them unique.
Example:
----
foo ldy #0
?loop lda data,y ; full label name is FOO?LOOP
beq ?ret
jsr sendByte
iny:bne ?loop
?ret rts
bar lda baz
beq foo?ret ; ok
bne ?loop ; ERROR: Undeclared label: BAR?LOOP
----
'Instructions' and 'directives' must be preceded with some whitespace.
Without leading whitespace they are treated as label names.
For example:
----
@ -106,7 +134,7 @@ nop
(without leading space) defines a label called `nop`.
Whole-line comments must start with a semicolon, an asterisk or a pipe,
with optional label definition and spaces before.
with an optional label definition and spaces before.
Here are examples of whole-line comments:
--------------------
; this is a comment
@ -120,12 +148,12 @@ To assemble a single line several times,
precede the repeat count with a colon, for example:
-----------------
:4 asl @
mask_lookup :32 dta $80,$40,$20,$10,8,4,2,1
mask_lookup :32 dta $80,$40,$20,$10,$08,$04,$02,$01
-----------------
In lines with instructions or directives, a comment starts immediately
after the instruction/directive has been successfully parsed.
That is, in such lines *xasm* does not require a special character
That is, in such lines *xasm* does 'not' require any special character
to start a comment.
-------------------------------------------------------------
lda foo ; this is a comment
@ -134,7 +162,7 @@ to start a comment.
-------------------------------------------------------------
[[new_pairing]]
You may put two instructions in one line so they share their operand.
You may put two or more instructions in one line so they share their operand.
For example:
------------
eor:sta foo
@ -147,9 +175,9 @@ is equivalent to
Note that
------------
lda:tax #0
lda:tax:tay #0
------------
is allowed because `#0` is treated as a comment for `tax`.
is allowed because `#0` is treated as a comment for `tax` and `tay`.
EXPRESSIONS
-----------
@ -159,14 +187,14 @@ for 6502 indirect addressing.
A number is:
- a 32-bit decimal integer, e.g. `-12345`
- a 32-bit decimal integer, e.g. `12345`
- a 32-bit hexadecimal integer, e.g. `$abcd`
- a 32-bit binary integer, e.g. `%10100101`
- an ASCII character, e.g. `'a'` or `"a"`
- origin counter: `*`
- the current value of the origin counter: `*`
- a hardware register (see below), e.g. `^4e`
- [[new_opcode]]an opcode (see below), e.g. `{lda #0}` is `$a9`
- [[new_linecnt]]the line repeat counter (see below): `#`
- [[new_linecnt]]the current value of the line repeat counter (see below): `#`
Abbreviations of Atari hardware registers are provided
to save two characters (`$d40e` vs `^4e`)
@ -234,7 +262,8 @@ The following 'unary operators' are supported:
- `<` Low (extracts the low byte)
- `>` High (extracts the high byte)
The operator precedence is following:
Although the operators are similar to those used in C, C++, C# and Java,
their precedence is different:
- first: `[]` (brackets)
- `+ - ~ < >` (unary)
@ -245,19 +274,16 @@ The operator precedence is following:
- `&&` (binary)
- last: `||` (binary)
NOTE: Although the operators are similar to those used in C, C++ and Java,
their priorities are different.
Compare and logical operators assume that zero is false and a non-zero
is true. They return 1 for true.
The compare and logical operators assume that zero is false
and a non-zero is true. They return 1 for true.
Expressions are calculated in signed 32-bit arithmetic.
"Arithmetic overflow" error signals overflow of the 32-bit range.
An overflow is signalled with an "Arithmetic overflow" error.
DIRECTIVES
----------
*EQU* - assign value of expression to label::
*EQU* - assign the value of an expression to a label::
Examples:
+
@ -270,31 +296,33 @@ here equ *
Six options are available:
- `F` - fill the space between memory areas with `$FF`
- `G` - Atari 5200 mode for hardware register abbreviations
- `F` - fill the space between noncontiguous memory areas with `$FF` bytes
- `G` - Atari 5200 mode for hardware register abbreviations (`^xx`)
- `H` - generate Atari executable headers
- `L` - write to the listing
- `O` - write to the object file
- `L` - write the listing
- `O` - write the object file
- `U` - warn of unused labels
+
You can turn any of these on or off.
The default (if no `OPT` specified) is `opt f-g-h+l+o+u+`.
The default (before the first `OPT`) is `opt f-g-h+l+o+u+`.
For compatibility with MADS, `opt ?+` is accepted and ignored.
Examples:
+
------------------------------------------------------------------------------
opt l- listing off
opt l+o- listing on, object file off
opt f+g+h- useful for Atari 5200 cartridges - raw output, 5200 hw regs
opt ?+ MADS compatibility, no effect
------------------------------------------------------------------------------
*ORG* - change value of the origin counter::
*ORG* - set the origin counter::
If Atari executable headers are enabled, you can include an operand prefix:
If Atari executable headers are enabled (`opt h+`), you can include an operand prefix:
- `a:` starts a new block even if it's superfluous
because the new address equals the current address.
- `f:` is same as `a:`, but additionally generates a double-`$FF` prefix
- `f:` is same as `a:`, but additionally generates a double `$FF` prefix
before the new header. This prefix is automatically generated
at the beginning of the file (no need to include `f:` in the first `ORG`).
@ -311,10 +339,10 @@ In the latter example `table` points to 100 bytes
of uninitialized data (label is assigned with `*`
before the `ORG` directive is executed).
+
[[new_orgr]]Starting with version 2.6.0, *xasm* supports code
that is relocated at run time. Let's say you want your code
to be located on page zero. You can't normally load it directly into this
place, so you load it at a different address and then move in your program.
[[new_orgr]]*xasm* supports code that is relocated at run time.
Let's say you want your code to be located on page zero for best performance.
You can't safely load it directly into this place,
so you load it at a different address and then move in your program.
`org r:` changes the address that it used for code generation
but not the address used for generating Atari executable headers.
Example:
@ -408,18 +436,18 @@ Examples:
icl 'lib/fileio'
-----------------
+
NOTE: for portability, use only relative paths and slash as the separator.
This way your sources will compile under Windows and Linux.
NOTE: For Windows/macOS/Linux portability use relative paths
and slashes as path separators.
*END* - end assembling file::
*END* - end this source file::
May be used if the source file ends with something which shouldn't
be read by *xasm* (e.g. your notes).
*INS* - insert contents of file::
*INS* - insert binary file contents::
Copies every byte of the specified file into the object file and updates
the origin counter, as if these bytes were written using `DTA`.
the origin counter, as if these bytes were specified in a `DTA`.
You may specify a range of the file to insert. The syntax is:
+
-----------------------------
@ -432,11 +460,11 @@ Examples:
+
-----------------------------------------------
ins 'picture.raw'
ins 'file',-256 insert last 256 bytes of file
ins 'file',10,10 insert bytes 10..19 of file
ins 'file',-256 ; insert last 256 bytes of file
ins 'file',10,10 ; insert bytes 10..19 of file
-----------------------------------------------
*RUN* - set run address in the Atari executable format::
*RUN* - set the Atari executable run address::
+
---------
@ -450,7 +478,7 @@ is equivalent to:
dta a(main)
------------
*INI* - set init address in the Atari executable format::
*INI* - set the Atari executable init address::
Example:
+
@ -458,7 +486,7 @@ Example:
ini showloadingpic
------------
*ERT* - generate error if expression evaluates to true::
*ERT* - abort the assembly with an error if an expression is true::
Examples:
+
@ -490,7 +518,7 @@ widescr equ 1
sta $22f
-------------
+
NOTE: The above example may be rewritten using the 'repeat line' feature:
NOTE: Alternatively, the above example can be written using the 'repeat line' feature:
+
--------------------------
noscr equ 1
@ -503,7 +531,7 @@ widescr equ 1
PSEUDO COMMANDS
---------------
'Pseudo commands' are built-in macros. There are no user-defined macros in *xasm*.
'Pseudo commands' are built-in macros. There are 'no' user-defined macros in *xasm*.
*ADD* - add without carry::
@ -514,7 +542,7 @@ to use a `CLC` before `ADC` for every simple addition.
*SUB* - subtract::
It is `SEC` and `SBC`.
It is `SEC` followed by `SBC`.
[[new_repskip]]*RCC, RCS, REQ, RMI, RNE, RPL, RVC, RVS* - conditional repeat::
@ -532,11 +560,11 @@ The above code copies a 256-byte memory block from $500 to $600.
Here is the same written with standard 6502 commands only:
+
--------------------
ldx #0
ldx #0
copy_loop lda $500,x
sta $600,x
inx
bne copy_loop
sta $600,x
inx
bne copy_loop
--------------------
*SCC, SCS, SEQ, SMI, SNE, SPL, SVC, SVS* - conditional skip::
@ -557,7 +585,7 @@ In the above example the 16-bit variable `ptr` is incremented by 40.
*JCC, JCS, JEQ, JMI, JNE, JPL, JVC, JVS* - conditional jump::
These are long branches. While standard branches (such as `BNE`)
have range of -128..+127, these jumps have range of 64 kB.
have range of -128..+127 bytes, these jumps have range of 64 KB.
For example:
+
---------
@ -586,7 +614,7 @@ is equivalent to:
sne:inc dest+1
---------------
*MVA, MVX, MVY* - move byte using accumulator, X or Y::
*MVA, MVX, MVY* - move a byte using the accumulator, X or Y::
Each of these pseudo commands requires two operands
and substitutes two commands:
@ -625,7 +653,7 @@ When `<immed` equals `>immed` and `immed` is not forward-referenced,
sta dest+1
----------------
+
If possible, `MWX` and `MWY` use increment/decrement commands.
If possible, `MWX` and `MWY` use increment/decrement instructions.
For example, `mwx #1 dest` expands to:
+
-----------
@ -638,11 +666,11 @@ For example, `mwx #1 dest` expands to:
ADDRESSING MODES
----------------
All addressing modes are entered in the standard 6502 convention
except for the accumulator addressing mode,
which should be marked with the `@` character (as in Quick Assembler).
Addressing modes are entered in the standard 6502 convention.
An exception is the accumulator mode marked with the `@` character
for compatibility with Quick Assembler.
For Quick Assembler compatibility, there are two extra immediate
Also for Quick Assembler compatibility there are two extra immediate
addressing modes: `<` and `>`, which use the low/high byte of a 16-bit word constant.
Unlike in Quick Assembler, you can alternatively use
the more common syntax: `#<` and `#>`.
@ -686,6 +714,20 @@ and pseudo commands, except for `MWA`, `MWX` and `MWY`:
HISTORY
-------
Version 3.2.1 (2022-12-08)
~~~~~~~~~~~~~~~~~~~~~~~~~~
- source can optionally be read from standard input, and object can be
written to standard output instead of files (by Adrian Matoga)
- <<new_pairing,any number of instructions in one line>> (by Adrian Matoga)
Version 3.2.0 (2021-06-22)
~~~~~~~~~~~~~~~~~~~~~~~~~~
- <<new_locallabel,local labels>> (contributed by Adrian Matoga)
- fixed emitted bytes not shown in the listing after `OPT L+` (by Adrian Matoga)
- emit shorter code for moving a negative immediate value with `MWX`/`MWY`
- Windows binary signed
- macOS binary signed, notarized, installed in `/usr/local/bin`
Version 3.1.1 (2019-11-20)
~~~~~~~~~~~~~~~~~~~~~~~~~~
- remove partial object file on error (requested by Bill Kendrick)
@ -699,7 +741,7 @@ Version 3.1.0 (2014-07-20)
- `INS` can be repeated (suggested by Marek Pavlik) and taken "opcode" of
- `OPT U-` disables <<new_unlabels,*/u*>> unused label warnings
(suggested by Marek Pavlik)
- if the file to be included cannot be opened, report error in the `ICL` line
- if the file to be included cannot be opened, report an error in the `ICL` line
(suggested by Peter Dell)
- removed duplicate filenames for <<new_makefile,*/M*>>
- implemented <<new_fullpaths,*/p*>> outside Windows
@ -712,7 +754,7 @@ Version 3.0.2 (2009-10-17)
for backward branches
- <<new_makefile,new command-line option */M* prints a Makefile rule>>
- command-line options are now case-insensitive
- on Windows error messages are printed in red, warnings in yellow
- on Windows, error messages are printed in red, warnings in yellow
Version 3.0.1 (2007-04-22)
~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -725,9 +767,9 @@ Version 3.0.0 (2005-05-22)
- rewritten from the x86 assembly language to the
http://dlang.org/[D programming language] - Linux version
is now available and DOS is no longer supported
- no limits for line length, number of `ICLs`, `ORGs`,`IFTs` and labels
- no limits on line length, number of `ICLs`, `ORGs`,`IFTs` and labels
- Unix-style command-line options are supported
- */e* option is no longer supported
- the */e* option is removed
- the label table is now sorted alphabetically
Version 2.6.1 (2005-05-21)
@ -756,8 +798,7 @@ Version 2.6.0 (2005-02-07)
- <<new_linecnt,line repeat counter>>
- label values are now 32-bit, not just 17-bit
- command-line options */n* and */s* are no longer supported
- fatal I/O errors (such as floppy not ready) no longer print the annoying
"Abort, Retry, Ignore" message
- fatal I/O errors no longer print the annoying "Abort, Retry, Ignore" message
Version 2.5.2 (2002-10-03)
~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -772,7 +813,7 @@ Version 2.5.1 (2002-08-21)
Version 2.5 (2002-07-08)
~~~~~~~~~~~~~~~~~~~~~~~~
- fixed another bug, very similar to the previous one, e.g.
- fixed another bug similar to the previous one, for example:
+
----------
ift 0
@ -804,14 +845,13 @@ Version 2.4 (2002-05-22)
~~~~~~~~~~~~~~~~~~~~~~~~
- fixed incorrect unary operator precedence
- fixed wrong label value after a skip pseudo command
- the assembler is .EXE (.COM caused problems with DJGPP *make* due
- the assembler is an .EXE (.COM caused problems with DJGPP *make* due
to a bug in the DJGPP runtime)
- the assembler executable is not compressed (so it occupies less space in the ZIP)
- improved command-line parsing: options may be used before source file name,
tab character is a valid separator, slash may be used as a directory separator
- the assembler executable is no longer compressed
- improved command-line parsing: options may be used before the source file name,
tab is a valid separator, slash may be used as a directory separator
- error and warning messages are written to stderr, not stdout
- added `==` (equals) operator, which is equivalent to `=`,
but more natural for C/C++/Java programmers
- added `==` (equals) operator, equivalent to `=`, but familiar to C/C++/Java programmers
- <<new_deflabel,added `/d:label=value` option: define a label>>
- <<new_fullpaths,added `/p` option: print full paths
in listing and error messages>>
@ -839,11 +879,11 @@ Version 2.2 (1999-09-10)
- fixed `ICL` in last line
- fixed `OPT H-H+`
- fixed first `ORG *`
- no need to set origin counter until it's used
- no need to set the origin counter until it's needed
- allow Unix, Macintosh and Atari EOLs
- value of 'true' changed to 1
- command-line option to set environment variables on error
- commane-line option to assemble only if source is newer than object file
- commane-line option to assemble only if the source is newer than the object file
- <<new_opcode,opcode extracting>>
- <<new_linerep,repeat line>>
- <<new_pairing,two instructions in line>>
@ -852,7 +892,7 @@ Version 2.2 (1999-09-10)
Version 2.0 (1998-11-12)
~~~~~~~~~~~~~~~~~~~~~~~~
- fixed: name of object file was truncated
- fixed: object filename was truncated
- fixed forward references in `EQU` and `DTA`
- fixed hex numbers
- `.OBX` is now the default extension for the object file

View File

@ -1,13 +1,11 @@
Name: xasm
Version: 3.1.1
Version: 3.2.1
Release: 1
Summary: 6502 cross-assembler
License: Poetic
Group: Applications/Programming
Source: http://pfusik.github.io/xasm/xasm-%{version}.tar.gz
URL: https://github.com/pfusik/xasm
BuildRequires: dmd >= 2, asciidoc
BuildRoot: %{_tmppath}/%{name}-root
%description
xasm is a 6502 cross-assembler with original syntax extensions.
@ -21,18 +19,19 @@ xasm is a 6502 cross-assembler with original syntax extensions.
make xasm xasm.1
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT prefix=%{_prefix} install
%clean
rm -rf $RPM_BUILD_ROOT
make DESTDIR=%{buildroot} prefix=%{_prefix} install
%files
%defattr(-,root,root)
%{_bindir}/xasm
%{_mandir}/man1/xasm.1.gz
%changelog
* Thu Dec 8 2022 Piotr Fusik <fox@scene.pl>
- 3.2.1-1
* Tue Jun 22 2021 Piotr Fusik <fox@scene.pl>
- 3.2.0-1
* Wed Nov 20 2019 Piotr Fusik <fox@scene.pl>
- 3.1.1-1