mirror of
https://github.com/pfusik/xasm.git
synced 2024-06-01 01:41:29 +00:00
Compare commits
36 Commits
xasm-3.1.1
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
8eb2a5ae6f | ||
|
9732817a0b | ||
|
70c907bae6 | ||
|
7a666799ac | ||
|
95136d1546 | ||
|
ca5e88950f | ||
|
138331193a | ||
|
30c96357bc | ||
|
83d2f8ff1d | ||
|
9aae1ad4c4 | ||
|
f33c112ac6 | ||
|
57661276c2 | ||
|
a4225b6128 | ||
|
1da9f77458 | ||
|
2b7d21ae43 | ||
|
2f67b3bab4 | ||
|
afb9f7830e | ||
|
95cb5ae592 | ||
|
8f6621f079 | ||
|
52982169df | ||
|
8c7ef1a922 | ||
|
1a90ca04d3 | ||
|
73b382f9b7 | ||
|
7ba3f9f597 | ||
|
b815a448cd | ||
|
274dda9dd2 | ||
|
da58ad7950 | ||
|
52ef8c05d6 | ||
|
6f25038d95 | ||
|
57ef9b5c83 | ||
|
8f06fec50c | ||
|
d50d484e1f | ||
|
65a2c1fbdd | ||
|
d3908ec95e | ||
|
647cf9f3cf | ||
|
819701b9be |
16
.github/workflows/test.yml
vendored
Normal file
16
.github/workflows/test.yml
vendored
Normal 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
1
.gitignore
vendored
|
@ -7,3 +7,4 @@
|
|||
/MANIFEST
|
||||
/.dub
|
||||
/.project
|
||||
/signed
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
language: d
|
||||
d:
|
||||
- dmd
|
||||
- gdc
|
||||
- ldc
|
26
Makefile
26
Makefile
|
@ -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,32 @@ 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 $@
|
||||
/Applications/Xcode.app/Contents/Developer/usr/bin/notarytool submit --wait --keychain-profile recoilnotarization $@
|
||||
|
||||
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
|
||||
|
|
|
@ -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
12
debian/changelog
vendored
|
@ -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
2
debian/compat
vendored
|
@ -1 +1 @@
|
|||
9
|
||||
10
|
||||
|
|
6
debian/control
vendored
6
debian/control
vendored
|
@ -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
4
debian/copyright
vendored
|
@ -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
|
||||
|
|
2
dub.sdl
2
dub.sdl
|
@ -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"
|
||||
|
|
215
source/app.d
215
source/app.d
|
@ -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;
|
||||
|
|
248
xasm.1.asciidoc
248
xasm.1.asciidoc
|
@ -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
|
||||
|
|
17
xasm.spec
17
xasm.spec
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user