FakeASM

From Esolang
Jump to navigation Jump to search

FakeASM (Fake Assembly) is an esoteric programming language in the past by User:CosmoConsole (in fact, so past that the original interpreter source is now thought to be lost). Made to resemble assembly languages of various processors, like the 65c816, code written with FakeASM may look like an assembly language at first. The original command-line interpreter was created in 2012 with VB.net.

FakeASM2

FakeASM2 is a VB.net mod for FakeASM, based on the existing VB.net code (which was stolen retrieved with the magic of decompilation). It adds some additional instructions, and was first released in 2014.

File format

The extension for FakeASM code is .asm, which is actually the same used for various actual assembly languages as well.

A comprehensive tutorial on FakeASM (in proper English)

FakeASM Interpreter

FakeASM's help can be seen by using the command flag -h.

>> usually means the program awaits user input (a number between 0-65535).

Debug mode

Debug mode prints every executed row of the program as such:

nnnnnnnn|A=aaaa,B=bbbb,C=cccc,X=xx,Y=yy,Z=zz,P=pp,ssss| THE LINE BEING RUN, USUALLY AN INSTRUCTION
nnnnnnnn = 32-bit program counter, basically the line number - 1 in hexadecimal
aaaa = 16-bit value of A (accumulator)
bbbb = 16-bit value of B
cccc = 16-bit value of C
xx = 8-bit value of X
yy = 8-bit value of Y
zz = 8-bit value of Z
pp = 8-bit value of P (processor status register)
ssss = Stack pointer (a.k.a the first free point in stack as a RAM address)

ECHO and all WBx, WRx and WXx are all noted in debug mode with a ========= title in front of the output.

Jump instructions are formatted as follows:

(title) PROGRAM_COUNTER=nnnnnnnn | OLD => NEW
nnnnnnnn = 32-bit program counter where the Jump function jumps to
OLD = The instruction which causes the jump
NEW = The instruction or row being jumped into by the instruction in OLD

====Cond. JMP FALSE==== means that a conditional jump instruction is ignored, because the condition was not met.

Error messages

  • Script ended. - No error.
  • Label x not found - The specified label was not found.
  • Label x many times - The specified label is ambiguous.
  • Illegal instruction - Something unexpected was found.

Ending details

Appear in debug mode.

A=aaaa,B=bbbb,C=cccc,X=xx,Y=yy,Z=zz,P=pp
PROGRAM_COUNTER=nnnnnnnn
MAX_COUNTER=mmmmmmmm
aaaa, bbbb, cccc, xx, yy, zz, pp = Same format as in the instruction row
nnnnnnnn = The program counter when the script stops. For example, location of STP instruction.
mmmmmmmm = Amount of lines in the script - 1 in hex. Basically the largest the program counter would ever go in this script.

Syntax

One needs to only know instructions and some additional values to master the language.

Numerical values are entered like normal. Hexadecimal values have a suffix of h and binary values have the suffix of b.

FakeASM is a 16-bit language with integers-only. Therefore, neither decimal values, nor values that are from either below 0 and above 65535, or below -32768 and above 32767 can be represented.

Constants are declared like !PI=3, and then used with !PI in-script.

Labels are simply any continuous string as a line followed with a colon, such as:

Label1: 

Comments are any line starting with a semicolon.

Both ROM and RAM are included. ROM can be either imported from a file or be written before the script with interpreter commands. Writing to ROM is impossible during the script itself, although reading is not RAM can be written from interpreter commands or read/written from the script. A third storage, SDS (shared data storage) is shared between scripts as a file named "fakeasm.sds" in the same folder as the interpreter. All three storage methods are exactly 65536 (0x10000) bytes long.

Interpreter commands are evaluated before the script, so writing the ROM isn't actually possible.

There are 8 built-in variables or 'registers'.

  • A: Main 16-bit register used in all computation operations.
  • B & C: Additional 16-bit registers
  • X, Y, Z: 8-bit registers for index
  • PC: 32-bit value, represents current line number.
  • P: "processor" status register, format as:
----xnzc
  • - = Unused and reserved for future flags.
  • X - RXY flag.
    • If X=1, RXY target = Argument + X + (Y * 0x100)
    • If X=0, RXY target = Argument + X + (Y * Z)
  • N - Negative. 1 when A's value is between 0x8000-0xFFFF and 0 when it's between 0x0000-0x7FFF
  • Z - Zero. 1 when A's value is zero and 0 otherwise. Other values than zero can be compared with compare instructions (1 means equality, 0 means inequality).
  • C - Carry. Used in ACC, ACR, RCL, RCR, SCC, SCR, SHL and SHR. Unconditionally affected by SEC (set carry) and CLC (clear carry).

Interpreter commands

  • incasm file - include another file in script
  • lblnf - disregard labels
  • romseek address - move the ROM address pointer
  • romwrite value1,value2,value3... - write data to ROM
  • ramseek address - move the RAM address pointer
  • ramwrite value1,value2,value3... - write data to RAM
  • incrom filename - import ROM contents from file (first 65536 bytes)
  • incram filename - import RAM contents from file (first 65536 bytes)
  • loadrom filename start length - load length first bytes from file and place them at the ROM, starting from start
  • loadram filename start length - load length first bytes from file and place them at the RAM, starting from start
  • saverom filename start length - replace or create a file with filename, and write length bytes, starting from start, from the ROM to the beginning of the file
  • saveram filename start length - replace or create a file with filename, and write length bytes, starting from start, from the RAM to the beginning of the file

Instruction list

  • ACC value - Calculates A + value with carry and stores to A.
  • ACR address - Calculates A + (RAM at address) with carry and stores to A.
  • AGAIN - Restarts program execution from the beginning.
  • ANC value - Calculates A AND value and stores to A.
  • AND address - Calculates A AND (RAM at address) and stores to A.
  • ANR address - Calculates A AND (ROM at address) and stores to A.
  • BEEP value - Play PC beep with A-frequency and length of value ms.
    • BEEPR address - Play PC beep with A-frequency and length of (RAM at address) ms.
    • BEEPR.w address - Play PC beep with A-frequency and length of (RAM at address + (RAM at address + 1 << 8)) ms.
  • CLC - Clears the carry (C) flag and goes on.
  • CLR value - Changes screen colors according to the 8-bit value given, top nibble controls background and bottom nibble controls foreground/text).
    • CLA - value set as (A AND 0xFF)
    • CLR.b value - Low nibble controls background, top nibble does nothing.
    • CLR.f value - Low nibble controls foreground, top nibble does nothing.
  • CMC value - Set P flags as: Z to 1 if A equals value, 0 otherwise; C to 1 if A is greater than value, 0 otherwise
    • CMP address - value = RAM at address
    • CMR address - value = ROM at address
    • CxC value - Compare x (B, C, X, Y or Z) to value.
    • CxA address - Compare x (B or C) to RAM at address.
    • CxR address - Compare x (B, C, X, Y or Z) to ROM at address.
    • CMx address - Compare x (X, Y or Z) to RAM at address.
  • CPB value - Set P as (P AND inverse of value), a.k.a. clear specified bits from P.
  • CRLF - Print a line change.
  • CRR - Move cursor down (value of Y) pixels and right (value of X) pixels.
  • CUR - Move cursor horizontally to (value of X) pixels, and vertically to (value of Y) pixels.
  • DCR - Return back to original colors.
  • DEC x - Decrease value of x (A, B, C, X, Y or Z) by one
  • DLAY - Delay further program execution for (value of A) milliseconds.
  • ECHO "string" - Print string to standard output, followed with newline.
    • ECHOW "string" - Same as ECHO, but do not affect the X position of the cursor.
    • ECHOX "string" - Same as ECHO, but do not affect the X or Y position of the cursor.
  • INC x - Decrease value of x (A, B, C, X, Y or Z) by one
  • JMP address - Jump to address unconditionally (if address is a label, must be followed with a colon).
    • JMx address - Before jumping, index address with the value of x (X, Y or Z).
    • JSL address - Push 32-bit return address before jumping (for RTL)
    • JSR address - Push 16-bit return address before jumping (for RET)
    • Jxx address - Conditional jump. Available conditions (all related to value of the P register):
      • xx = EQ: if Z flag is 0
      • xx = NE: if Z flag is 1
      • xx = CC: if C flag is 0
      • xx = CS: if C flag is 1
      • xx = PL: if N flag is 0
      • xx = MI: if N flag is 1
  • KEY - Waits for a keystroke from the user.
  • LAI - Read RAM address yyxx (yy is the value of the Y register, xx is the value of the X register) and store the value to A.
  • LxC(.w) value - Store the value to register x (A, B, C, X, Y or Z).
    • LxC.b value - Store the value to the lower byte if register is A, B or C.
    • LxC.B value - Store the value to the higher byte if register is A, B or C.
  • Lxy address - Load value to the register x (A, B or C) from RAM at address indexed with the value of register y (X, Y or Z) Supports LDA dot-suffixes.
    • Rxy address - ROM, instead of RAM
  • LDa(.b) address - Load value from RAM at address and store it to low byte of register a (A, B or C).
    • LDa.B address - Load value from RAM at address and store it to high byte of register a (A, B or C).
    • LDa.w address - Load value from RAM at address, and one following it, and store the value as little-endian to register a (A, B or C).
    • LDa.W address - Load value from RAM at address, and one following it, and store the value as big-endian to register a (A, B or C).
    • LRa(.x) - Same as LDx.x, but reads the value from ROM instead of RAM.
  • LDx address - Load value from RAM at address and store it to register x (X, Y or Z). Does not support dot suffixes.
  • LRI - Read ROM address yyxx (yy is the value of the Y register, xx is the value of the X register) and store the value to A.
  • LxA - Read value from RAM at address specified in A and store the value to register x (X, Y or Z).
  • NOP - Does nothing else than waste some actual CPU cycles and a line of source code.
  • ORC value - Calculates A OR value and stores to A.
  • ORR address - Calculates A OR (RAM at address) and stores to A.
  • PEA value - Pushes the 16-bit value to the stack as big endian.
  • PEI value - Pushes the 8-bit value to the stack.
  • PEL value - Pushes the 32-bit value to the stack as big endian.
  • PER value - Calculates a signed 16-bit value as a distance between the current PC and the value, pushing it to the stack as big endian.
  • PHx - Pushes the value of register x (A, B, C, X, Y or Z) to the stack.
  • PLx - Pops a value from the stack, storing it to the register x (A, B, C, X, Y or Z).
  • POP address - Pops a byte from the stack, storing it to the RAM at address.
  • PRINT "string" - Print string to standard output, without newline.
  • PSH address - Pushes the value of RAM at address to the stack.
  • PUNCH address - Pushes the value of ROM at address to the stack.
  • RAN value - Sets the value of register A to be a random number between 0 and value.
  • RCA - Reads a line from the stdin, storing the first character's Unicode code to A.
  • RCL - Rotates A one bit to the left, while carry (C flag) acts as 17th bit.
    • RCL.b - Rotates the lower byte of register A one bit to the left, while carry (C flag) acts as 9th bit.
  • RCR - Rotates A one bit to the right, while carry (C flag) acts as 17th bit.
    • RCR.b - Rotates the lower byte of register A one bit to the right, while carry (C flag) acts as 9th bit.
  • RDA - Reads a number from stdin, parses it as a number and stores the value to A.
  • RET - Return to last JSR call. (Theoretically: pop two bytes from the stack and jump there).
    • RTL - Return to last JSL call. (Theoretically: pop four bytes from the stack and jump there).
  • RKY - Reads a single character from the keybuffer. A will be set to be the Unicode character code of the given key, while X is set to 0, except if:
    • Key is UP ARROW; x = 1.
    • Key is DOWN ARROW; x = 2.
    • Key is LEFT ARROW; x = 3.
    • Key is RIGHT ARROW; x = 4.
    • Key is ENTER; x = 5.
    • Key is SPACE; x = 6.
    • Key is ESC; x = 7.
    • Y is set to 0. Lowest bit (bit 0) is set to state of Alt, bit 1 to the state of Shift and bit 2 to the state of Ctrl.
  • RND - Sets the lower byte of A to be a random value between 0x00 and 0xFF (0-255):
  • ROL - Rotates A one bit to the left, without a 17th bit.
    • ROL.b - Rotates the lower byte of register A one bit to the left, without a 9th bit.
  • ROR - Rotates A one bit to the right, without a 17th bit.
    • ROR.b - Rotates the lower byte of register A one bit to the right, without a 9th bit.
  • RSD address - Read SDS from address and store the value to A.
  • RXY - Read value from ROM at address as specified with the X flag, and store it to A.
  • Sxy address - Store value of the register x (A, B or C) to RAM at address indexed with the value of register y (X, Y or Z). Supports STA dot-suffixes.
  • SCC value - Calculates A - value with carry and stores to A.
  • SCR address - Calculates A - (RAM at address) with carry and stores to A.
  • SEC - Sets the carry (C) flag and goes on.
  • SHL - Shift A one bit to the left, store leftover bit to carry.
  • SHL.b - Shift low byte of A one bit to the left, store leftover bit to carry.
  • SHR - Shift A one bit to the right, store leftover bit to carry.
  • SHR.b - Shift low byte of A one bit to the right, store leftover bit to carry.
  • SPB value - Set P as (P OR value), a.k.a. set specified bits from P.
  • STa(.b) address - Store value to RAM at address from the low byte of register a (A, B or C).
    • STa.B address - Store value to RAM at address from the high byte of register a (A, B or C).
    • STa.w address - Store value to RAM at address as little-endian from the value of register a (A, B or C).
    • STa.W address - Store value to RAM at address as big-endian from the value of register a (A, B or C).
  • STx address - Store value to RAM at address from the value of register x (X, Y or Z). Does not support dot suffixes.
  • STP - Stops the execution immediately. Ending scripts with STP is a good practice for no apparent reason.
  • SxA - Store value to RAM at the address specified in A, taking the value from register x (X, Y or Z).
  • SZR address - Stores a zero value to the RAM at specified address.
  • TAS - Copy the value from A to the stack pointer.
  • TSA - Copy the value from the stack pointer to A.
  • Txy - Transfer value from one register to another. x and y may both be A, B, C, X, Y and Z. Transfer instructions to itself, such as TAA, are illegal instructions. 16-bit -> 8-bit handles as low byte of 16-bit value, and vice versa.
  • WCA(.b) - Write the value from the low byte of A as an ASCII character to the stdout.
    • WCA.w - Write the value from A as an Unicode character to the stdout.
  • WSD address - Write to SDS at address, taking the value from A.
  • Wxy - Write the value of register y (A, B, C, X, Y or Z) to the stdout with format x.
    • Format R: decimal number with newline
    • Format D: decimal number without newline
    • Format X: hexadecimal number with newline
    • Format H: hexadecimal number without newline
    • Format B: binary number with newline
    • Format A: binary number without newline
  • XBx - Exchange the low and high byte of a 16-bit register x (A, B or C).
  • XOR address - Calculates A XOR (RAM at address) and stores to A.
  • XRC value - Calculates A XOR value and stores to A.

Hidden instructions

  • 20 GOTO 10 - Rumors are circulating that it behaves exactly like AGAIN.

FakeASM2 instructions

Sample code

Hello World

ECHO "Hello, world!"
STP

99 bottles of beer

LXC 99
Bottle:
 WDX
 PRINT " bottle"
 CXC 1
 JCC SkipS:
 PRINT "s"
SkipS:
 ECHO " of beer on the wall,"
 WDX
 PRINT " bottle"
 CXC 1
 JCC SkipS_a:
 PRINT "s"
SkipS_a:
 ECHO " of beer."
 ECHO "Take one down, pass it around,"
 DEC X
 CXC 0
 JEQ NoMoreBottles:
 WDX
 PRINT " bottle"
 CXC 1
 JCC SkipS_b:
 PRINT "s"
SkipS_b:
 ECHO " of beer on the wall."
 CRLF
 CXC 0
 JMP Bottle:
NoMoreBottles:
 ECHO "No bottles of beer on the wall."
 CRLF
 ECHO "No bottles of beer on the wall,"
 ECHO "No bottles of beer."
 ECHO "Go to the store, buy some more,"
 ECHO "99 bottles of beer on the wall."

Quine (FakeASM 2)

QUI

Cat program (FakeASM 2)

 RSC
 JEQ End:
 WCA.w
 AGAIN
End:

Fibonacci sequence

Fibonacci:
 ; Calculates Fibonacci sequence
 ; Load X with the parameter, then call with 
 ; JSL Fibonacci:
 ; A will have the result.
 ; Uses 0x100-0x103 as scratch values.
 LAC 0
 CXC 0
 JCS Fibonacci_a:
 RTL
Fibonacci_a:
 CXC 1
 JNE Fibonacci_b:
 LAC.w 1
 RTL
Fibonacci_b:
 LAC.w 1
 STA.w 102h
 LAC.w 0
 STA.w 100h
Fibonacci_c:
 LDA.w 102h
 CLC
 ACR 100h
 CXC 2
 JEQ Fibonacci_d:
 DEC X
 LDC.w 102h
 STC.w 100h
 STA.w 102h
 JMP Fibonacci_c:
Fibonacci_d:
 RTL

Deadfish (FakeASM 2)

Deadfish:
 CBC 100h
 JNE Deadfish_Continue:
 LBC 0
Deadfish_Continue:
 RSC
 JEQ End:
 CMC 69h
 JEQ Deadfish_I:
 CMC 64h
 JEQ Deadfish_D:
 CMC 6Fh
 JEQ Deadfish_O:
 CMC 73h
 JEQ Deadfish_S:
 CRLF
 JMP Deadfish:
Deadfish_I:
 INC B
 JMP Deadfish:
Deadfish_D:
 DEC B
 JMP Deadfish:
Deadfish_O:
 WRB
 JMP Deadfish:
Deadfish_S:
 TBA
 JSL Square:
 TAB
 JMP Deadfish:
; A * A
Square:
 TAX
 JSR Multiply:
 RTL
; A * X
Multiply: 
 STA.w 0100h
 LAC 0
MultiplyLoop:
 CXC 0h
 JEQ MultiplyEnd:
 CLC
 ACR 0100h
 DEC X
 JMP MultiplyLoop:
MultiplyEnd:
 RET
End:

See also