Giter Site home page Giter Site logo

clownacy / clownassembler Goto Github PK

View Code? Open in Web Editor NEW
45.0 6.0 5.0 816 KB

Motorola 68000 assembler, clone of SN 68k (A.K.A. asm68k).

License: GNU Affero General Public License v3.0

CMake 0.56% Makefile 0.10% C 53.70% Lex 2.00% Yacc 4.92% Assembly 38.19% C++ 0.54%
ansi-c assembler assembly c89 motorola-68000 c90 68000 68k bison bison-flex

clownassembler's People

Contributors

clownacy avatar suppertails66 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

clownassembler's Issues

Support `def` for checking defined symbols

This is merely a feature request, not a bug report, but seeing how clownassembler already supports expressions in ifs I thought it shouldn't take too long to implement.

Basically, one of the most useful features for any project that supports build options (or multiple builds) in original ASM68K is to come up with "compile flags" defined in assembler arguments and use if def(...) in the source files to check for them, e.g.:

    if def(_DEBUG_)  ; is it debug build?
        ; Some extra logic here
    endc

    if def(_DEBUG_)=0 ; NOT a debug build?

    endc

As noted, "compile flags" can be passed to assembler arguments, but are otherwise completely optional:

    # DEBUG build (defines a "compile flag")
    $(ASM68K) /e _DEBUG_ main.asm, main.bin

    # RELEASE build (nothing)
    $(ASM68K) main.asm, main.bin

Basically, I've been looking into compiling at least least blobs for my MD Debugger using clownassembler and unlike actual debugger macros, they are relatively straightforward and I found out your assembler supports almost everything by now except for def function and /e option (it actually has two syntaxes: /e SYMBOL and /e SYMBOL=value)

Assembler segfault if macros recurse infinitely

So, I was writing a DMA macro and made a mistake:

DmaToVram: macro from, to, len, areg
    DmaToVram \from, \to, \len, 2, \areg
    endm

That second DmaToVram was supposed to be DmaToVramEx. Anyway, what happened is that the assembler crashed with a segfault because it recursed too much. Ideally there should be a macro nesting limit so the assembler has a chance to show a proper error message (even if the limit is something absurd like 50 or 100 nests, since the biggest concern is infinite recursion in practice).

Build files in subfolder

Hello,

I would like to have a folder structure where ".asm" files are located in a "src" subfolder. When I compile the code with clownassembler, I get an error because I include the files like this

include "header.asm

and not

include "src/header.asm

This makes sense, because the "main.asm" file is also in the "src" folder.

When I include the files by adding the "src" subfolder in the path, I get an error in VisualCode, but the program compiles correctly.

Is there any way of telling clownassembler where to work?

In my Makefile, I've added "cd $(SRC_DIR) to work in the src folder:

$(OUT_DIR)/$(BIN): $(SRC_DIR)/$(SRC)
	@cd $(SRC_DIR) && $(ASM) $(ASFLAGS) -i $(SRC) -o ../$(OUT_DIR)/temp
	@dd if=$(OUT_DIR)/temp of=$@ bs=128K conv=sync status=none
	@rm -f $(OUT_DIR)/temp

Thanks a lot!

Add a way to disable replaced instruction warnings

I tried building the SLZ decompressor as a test (https://github.com/sikthehedgehog/mdtools/blob/master/slz/md/slz.68k) and got these warnings:

Warning: AND should be ANDI.
On line 40 of 'slz.68k'...
    and.w   #$0F, d4

Warning: EOR should be EORI.
On line 52 of 'slz.68k'...
    eor.w   #$0F<<2, d4

There's probably a lot of old code written on the assumption that the assembler will pick the correct variant (like the above two, or move vs. movea, or writing movep with (an) instead of 0(an)). It would be useful to have a way to disable only these kinds of warnings without disabling all the other warnings.

Assembler permanently crashes with SEGFAULT, all tests fail

There's a serious bug in Clownassembler, where any output causes it to crash with SEGFAULT. This includes built-in tests. Literally every test fails on my system:

0% tests passed, 16 tests failed out of 16

Total Test time (real) =   1.18 sec

The following tests FAILED:
          1 - misc (SEGFAULT)
          2 - INSTURCTION_MOVE_TO_SR_VALID (SEGFAULT)
          3 - INSTURCTION_MOVE_TO_SR_INVALID_1 (SEGFAULT)
          4 - INSTURCTION_MOVE_TO_SR_INVALID_2 (SEGFAULT)
          5 - INSTURCTION_MOVE_TO_SR_INVALID_3 (SEGFAULT)
          6 - INSTURCTION_MOVE_TO_SR_INVALID_4 (SEGFAULT)
          7 - INSTURCTION_MOVE_TO_SR_INVALID_5 (SEGFAULT)
          8 - valid_instructions_assemble (SEGFAULT)
          9 - valid_instructions_compare (Failed)
         10 - sonic_1_assemble (Failed)
         11 - sonic_1_compare (Failed)
         12 - 68_katy_basic_assemble (SEGFAULT)
         13 - 68_katy_basic_compare (Failed)
         14 - sonic_spinball_assemble (Failed)
         15 - sonic_2_august_21st_assemble (Failed)
         16 - sonic_2_august_21st_compare (Failed)

Quick investigation shows that it's caused by fputc call with NULL instead of a proper stream.

For instance, assembling a simple "RTS" instruction crashes with the following backtrace:

(gdb) bt
#0  0x00007ffff7e3872d in fputc (c=32, fp=0x0) at ./libio/fputc.c:35
#1  0x0000555555559e87 in OutputByte (state=state@entry=0x7fffffffd660, byte=byte@entry=78) at semantic.c:369
#2  0x000055555555c9a1 in ProcessInstruction (state=state@entry=0x7fffffffd660, instruction=instruction@entry=0x7fffffffd468) at semantic.c:3629
#3  0x000055555555d164 in ProcessStatement (state=state@entry=0x7fffffffd660, statement=statement@entry=0x7fffffffd460, label=label@entry=0x0) at semantic.c:4100
#4  0x000055555555d6fa in ParseLine (state=state@entry=0x7fffffffd660, source_line=source_line@entry=0x7fffffffd6c8 " rts", label=label@entry=0x0, 
    directive_and_operands=directive_and_operands@entry=0x7fffffffd6c9 "rts") at semantic.c:4413
#5  0x000055555555db87 in AssembleLine (state=state@entry=0x7fffffffd660, source_line=source_line@entry=0x7fffffffd6c8 " rts") at semantic.c:4652
#6  0x000055555555e3c6 in AssembleFile (state=state@entry=0x7fffffffd660, input_file=input_file@entry=0x55555556e2a0) at semantic.c:5092
#7  0x000055555555e6d4 in ClownAssembler_Assemble (input_file=input_file@entry=0x55555556e2a0, output_file=output_file@entry=0x55555556e480, listing_file=listing_file@entry=0x0, 
    symbol_file=symbol_file@entry=0x0, input_file_path=input_file_path@entry=0x7fffffffe0d6 "test.asm", debug=<optimized out>, case_insensitive=0 '\000', equ_set_descope_local_labels=0 '\000')
    at semantic.c:5236
#8  0x000055555555750d in main (argc=<optimized out>, argv=0x7fffffffdcf8) at frontend_custom.c:189

This is the faulty code in question and it's related to rendering byte in a listing file:

clownassembler/semantic.c

Lines 368 to 371 in d0cc482

if (state->listing_counter % 2 == 0)
fputc(' ', state->listing_file);
fprintf(state->listing_file, "%02X", byte);

It's clearly missing state->listing_file != NULL check, so it attempts to write even if the file is NULL.

When explicitly setting a listing file path in assembler options, it works as expected.

Listing does not show value of EQU or RS

When defining an equ or rs label, the listing still shows the current PC value in its place. Since one of the most useful features of a listing is to be able to see where everything is, this may be a problem if somebody wants to see what value was computed (especially if it's intended to be an address in ROM or RAM, as you may not know where that ended up).

The suggestion would be to show the computed value instead of PC when the line defines a permanent label (in the case of rs, this also involves issue #13).

Note: this wouldn't apply to temporary labels (those that can change over time) or stuff like macros, as in those cases it's impossible to determine what value they're supposed to have.

Feature wishlist

These are some things I'd like to be added, listed from most important to least important.

  • String stuff (equs, strlen, strcmp, instr, substr) (asm68k)
  • Z80 (AS)
  • Functions (AS)
  • Default values for parameters in macros (AS)
  • Reference local labels from afar with Global_label.local_label (AS)
  • {curly_brackets} for variables (AS)
  • Variable containing iteration number in rept
  • Direct comparison of strings (instead of strcmp)
  • Current line number as a variable (e.g. _line)

I apologise in advance if any of these are nonsensical or difficult to implement.

Assembler pads output with zeros when setting ORG.

Issue

Assembling the following with clownassembler -i hello.s -o hello.pgx -l hello.lst produces a 64k binary pre-padded with zeros:

;;;
;;; Sample PGX Program
;;;

                org $010000

                dc.b "PGX", $02
                dc.l start

start:          move.l #$13,d0                      ; sys_chan_write
                clr.l d1                            ; Channel #0
                move.l #greet,d2                    ; Pointer to message
                move.l #greet_end-greet+1,d3        ; Length of message
                trap #15

done:           clr.l d0                            ; sys_exit
                clr.l d1                            ; Return value = 0
                trap #15

greet:          dc.b "Hello, world!"
greet_end:      dc.b 0

The same code assembled with vasmm68k_mot -Fbin -L hello.lst -o hello.pgx hello.s produces a 42b binary.

Request

Could an option be added to strip the pre-padding?

Listing formatting issues

The listing introduces some formatting errors when including files. Here are a couple of examples I found while trying the assembler (included file and resulting portion of the listing)

Example 1

;*******************************************************************************
; Hardware addresses
;*******************************************************************************

HwVersion:          equ $A10001     ; Console region and version
TmssPort:           equ $A14000     ; Write "SEGA" to unlock VDP

VdpCtrl:            equ $C00004     ; VDP control port
VdpData:            equ $C00000     ; VDP data port

IoCtrl1P:           equ $A10009     ; 1P I/O control port
IoCtrl2P:           equ $A1000B     ; 2P I/O control port
IoData1P:           equ $A10003     ; 1P I/O data port
IoData2P:           equ $A10005     ; 2P I/O data port
0000000000000000                            
00000000                            
00000000                            
00000000                            
00000000                            HwVersion:          equ $A10001     
00000000                            TmssPort:           equ $A14000     
00000000                            
00000000                            VdpCtrl:            equ $C00004     
00000000                            VdpData:            equ $C00000     
00000000                            
00000000                            IoCtrl1P:           equ $A10009     
00000000                            IoCtrl2P:           equ $A1000B     
00000000                            IoData1P:           equ $A10003     
00000000                            IoData2P:           equ $A10005     
                            IoData2P:           equ $A10005     

Example 2

;*******************************************************************************
; EntryPoint
; Where the program boots.
;-------------------------------------------------------------------------------
; note: doesn't return
;*******************************************************************************

EntryPoint:
    move.w  #$2700, sr                  ; Disable interrupts
    
    moveq   #$0F, d0                    ; Disable TMSS if needed
    and.b   (HwVersion), d0
    beq.s   @NoTmss
    move.l  ($100).w, (TmssPort)
@NoTmss:
    
    bra.s   *                           ; Hang up

;*******************************************************************************
; ErrorInt
; Called if the program crashes.
;-------------------------------------------------------------------------------
; note: doesn't return
;*******************************************************************************

ErrorInt:
    move.w  #$2700, sr                  ; Disable interrupts
    bra.s   *                           ; Hang up
0000020000000200                            
00000200                            
00000200                            
00000200                            
00000200                            
00000200                            
00000200                            
00000200                            EntryPoint:
00000200 46FC 2700                      move.w  #$2700, sr                  
00000204                                
00000204 700F                           moveq   #$0F, d0                    
00000206 C039 00A1 0001                 and.b   (HwVersion), d0
0000020C 67FE                           beq.s   @NoTmss
0000020E 23F8 0100 00A1 4000            move.l  ($100).w, (TmssPort)
00000216                            @NoTmss:
00000216                                
00000216 60FE                           bra.s   *                           
00000218                            
00000218                            
00000218                            
00000218                            
00000218                            
00000218                            
00000218                            
00000218                            
00000218                            ErrorInt:
00000218 46FC 2700                      move.w  #$2700, sr                  
0000021C 60FE                           bra.s   *                           
                           bra.s   *                           

Issues

The issues I found so far:

  • The address of the included file is inserted as-is, without a newline (so it gets glued together to the address of the first included line).
  • Comments are removed, leaving those lines "blank" (which is both confusing and can make it harder to read when comparing against the original source code).
  • The last line is repeated, without an address.
  • The include line is removed (unless the included file is blank, for some reason).

EDIT: did I seriously write "linker" instead of "listing"? lol

Work around for Gnu Bison 3.5.1

I'm not a C programmer and know very little about Bison and Flex.

On Ubuntu 20 with Gnu Bison 3.5.1 and flex 2.6.4, make errored with bison: unrecognized option '--header'

I worked around this by changing the Makefile to this

syntactic.c syntactic.h: syntactic.y
	$(YACC) -d syntactic.y
	mv syntactic.tab.h syntactic.h
	mv syntactic.tab.c syntactic.c
	$(YACC) --output=syntactic.c $(YFLAGS) $<

and added these to syntactic.y

#define YYNOMEM

#define M68KASM_error 1

Then it all compiles (despite many warnings about YYNOMEM), and the assembler does seem to work based on some simple tests.

Just adding this here in case anyone else hits this (or knows a better fix...)

RS labels can't be used before they're defined

Trying to use a label defined with rs does not work if the code referencing comes before it. Expected behavior is that labels declared with rs have the same behavior as labels declared with equ (i.e. can be used from anywhere in the code but can be defined only once).

Segfault when trying to write a token starting with .

Helping somebody figure out why his code doesn't work and he wrote .include instead of include (oops). The bug report here is that clownassembler crashes with a segfault instead of reporting an error as expected.

Tried further with bogus keywords…

This doesn't segfault (just reports an error as expected):

    word 1

This does segfault:

    .word 1

So the problem seems to be tokens that start with a . (in fact, . on its own also segfaults)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.