New productivity upload: X16 Edit - a text editor

Chat about anything CX16 related that doesn't fit elsewhere
Ed Minchau
Posts: 508
Joined: Sat Jul 11, 2020 3:30 pm

New productivity upload: X16 Edit - a text editor

Post by Ed Minchau »



On 9/30/2021 at 11:26 PM, Stefan said:




I've done some code cleaning the last couple of days. Very rewarding when the code becomes more compact, more readable, and more stringent. So far I've reduced the binary by almost 200 bytes.



Some time ago, I watched a few lectures on Clean Code by "Uncle Bob". Very inspiring, even though not all paradigms may be used in assembly, if you want things to fly fast.



Guys like Uncle Bob and Kevlin Henney are good to watch if you want your code to be clear and maintainable.

One thing that Bob Martin said in another video which stuck with me is (paraphrasing) "paradigms are just a set of arbitrary restrictions we put on programmers".

Stefan
Posts: 465
Joined: Thu Aug 20, 2020 8:59 am

New productivity upload: X16 Edit - a text editor

Post by Stefan »


Continuing on the topic of clean code, even though its not X16 Edit specific, I have some thoughts on how to apply to assembly programming.

In the lesson linked above, Uncle Bob is talking a lot about the design of functions:


  • Names of functions (and variables) should be carefully chosen, so that reading code is like reading (good?) prose


  • Function names should contain verbs, as they are doing something


  • A function should do only one thing; the process of cleaning code entails breaking a function into the smaller and smaller parts, and you know you're done when no more functions can reasonably be extracted


  • A function should be short (most often 5 lines)


In a modern cross assembler, such as ca65, there's nothing stopping you from naming things properly.

But what about functions doing only one thing, and functions being short like 5 lines?

Any high level language examines functions at compile time, and decides wether the resulting machine code is inlined or made into an actual machine language subroutine. Even if you are writing a lot of really small functions in a high level language, the binary code will probably be efficient.

In 6502 assembly, if you do a lot of subroutine calls with JSR+RTS, they will all stay in the final binary code making it inefficient.

I have never seen 6502 assembly code trying to be clean code in the way Uncle Bob describes. Would it even be possible without loosing performance?

I think it might be, if you use extensive use of macros for code that you want to break out into a separate "function" where the resulting machine code is inlined.

A simple example. Is this a good idea?


.macro goto_topleft



   stz VERA_L



   stz VERA_M



   lda #(2<<4)



   sta VERA_H



.endmacro

 


.macro clear_line



   ldx #80



   lda #32



:  sta VERA_D0



   dex



   bne :-



.endmacro

 


.macro goto_nextline



   stz VERA_L



   inc VERA_M



.endmacro

 


.macro is_finished



   lda VERA_M



   cmp #60



.endmacro

 


.proc clear_screen



   goto_topleft



loop:



   clear_line



   goto_nextline



   is_finished



   bne loop



   rts



.endproc

 


VERA_L = $9f20



VERA_M = $9f21



VERA_H = $9f22



VERA_D0 = $9f23


 

User avatar
kliepatsch
Posts: 247
Joined: Thu Oct 08, 2020 9:54 pm

New productivity upload: X16 Edit - a text editor

Post by kliepatsch »


Well, I personally don't like (yet) to extract things that are used only once. It feels messy to me. But the example above makes the code very easy to understand. It took me only a few seconds to understand what you are doing.

 

I wonder what's better: commenting code (e.g. giving headlines to sections of code) or writing macros with explanatory names

Edit: or even use descriptive names for labels

Scott Robison
Posts: 952
Joined: Fri Mar 19, 2021 9:06 pm

New productivity upload: X16 Edit - a text editor

Post by Scott Robison »


I do like using asm macros to abstract away clutter. Something simple like:



LDA #whatever

STA wherever

I think looks much more readable personally behind a STI macro, which I've used recently with Acme on some code that already existed for that assembler:

!macro STI .addr, .value {

        LDA #.value

        STA .addr

}

It's such a simple thing, but even as tiny as it is, it so much better represents the intent. Now, the name in this case isn't necessarily ideal unless you're trying to keep your asm continuing to look like asm. And for me, if I can take a bunch of these sorts of 2 or 3 or more line "routines", I'm able to have twice as much code on screen in context, which makes comprehension easier (for me).

!macro ADD .dst, .src {

        CLC

        LDA .dst

        ADC .src

        STA .dst

}

I like that when it fits the pattern much more than the equivalent four lines. And I can have ADDI, or ADDW, or ADDWI. I think those are good naming conventions for commonly used snippets that can themselves be used to create larger even better named routines.

I like some things about acme. In some ways it is a lot simpler. It's macro facilities aren't as good IMO as ca65, for example, but they are much better than nothing.

 

Scott Robison
Posts: 952
Joined: Fri Mar 19, 2021 9:06 pm

New productivity upload: X16 Edit - a text editor

Post by Scott Robison »



On 10/3/2021 at 12:38 AM, kliepatsch said:




Well, I personally don't like (yet) to extract things that are used only once. It feels messy to me. But the example above makes the code very easy to understand. It took me only a few seconds to understand what you are doing.



 



I wonder what's better: commenting code (e.g. giving headlines to sections of code) or writing macros with explanatory names



I think the key to programming / software engineering is making that judgement call on a case by case basis. Sometimes one will be preferable to the other.

One thing I haven't done yet, but really need to do, is create alternative mnemonics macros for the various branch instructions.

CMP #value

BEQ label

Is pretty clear. I think it becomes far less clear when it is something like:

AND #mask

BEQ label

To me, reading that, my brain wants to go to the place where "if the relevant bits in A are equal to the mask then branch". But it really is saying the opposite. In a case like this a simple alternative like BZ/BNZ as alternatives to BEQ/BNE makes a world of difference to the way I read the code.

Also, my OCD flares up whenever I see BPL. BMI isn't bad, I can read that as "branch negative". BPL though intuitively (even though I know better) means "branch positive" and zero isn't positive in my mind. I mean, I know how to use it, but the official mnemonics selected for 6502 leave me wanting at times.

Stefan
Posts: 465
Joined: Thu Aug 20, 2020 8:59 am

New productivity upload: X16 Edit - a text editor

Post by Stefan »


Bringing clarity to code by lots of comments is not the Clean Code way of doing things, apparently. Comments have the disadvantage of being ignored by the assembler or compiler. Keeping them up to date is a manual process. And all manual processes will fail ?

Good labels are a better option.

The advantage of extracting small functions into macros is that you get better abstraction in higher level functions. In my example above, the function "clear_screen" contains mostly macro calls. It's possible to understand what they will do without looking at the macro. You get the big picture very quickly. And if you are interested in the details, you may look at the macro definition.

That said, I've never tried to program anything in this fashion. It would be interesting to do that.

Scott Robison
Posts: 952
Joined: Fri Mar 19, 2021 9:06 pm

New productivity upload: X16 Edit - a text editor

Post by Scott Robison »


Another huge (IMO) benefit if macro based assembly is to avoid copy and paste programming. Say you have a number of functions to load different files. So you have JSR LOAD_FILE_X and JSR LOAD_FILE_Y and each of these are called only once. The code is practically identical in each. Why not wrap it in a macro?

!macro LDVFILE .file, .len, .addr {

            LDX #0 ; ram block for file name

            LDA #^.addr    ; ram block for load address

            JSR JSETBNK    ; load to bank ^.addr from file named in current bank

            LDA #.len ;LENGTH OF FILENAME

            LDX #<.file

            LDY #>.file

            JSR SETNAM ;SETNAM A=FILE NAME LENGTH X/Y=POINTER TO FILENAME

            LDA #$02

            LDX #$08

            LDY #$00

            JSR SETLFS ;SETFLS A=LOGICAL NUMBER X=DEVICE NUMBER Y=SECONDARY

            LDX #<.addr  ;LOW BYTE FOR LOAD ADDRESS

            LDY #>.addr  ;HIGH BYTE FOR LOAD ADDRESS

            LDA #$00

            JSR LOAD ;LOAD FILE A=0 FOR LOAD X/Y=LOAD ADDRESS

            JSR CLOSE ;CLOSE FILE

}

This could be copied and pasted into multiple routines, but why? It is part of a loader so expanding the macro multiple times isn't harmful in this case, but the actual code becomes much easier to read.

+LDFILE file_a_addr, file_a_len, file_a_addr

+LDFILE file_b_addr, file_b_len, file_b_addr

+LDFILE file_c_addr, file_c_len, file_c_addr

+LDFILE file_d_addr, file_d_len, file_d_addr

+LDFILE file_e_addr, file_e_len, file_e_addr

+LDFILE file_f_addr, file_f_len, file_f_addr

Now, one must be careful. It is easy to get carried away with these and really bloat your code. Hence why the need for judgement and why there isn't a one size fits all approach. But I like looking at the latter example more that expands the macro six times rather than making six copies of the function and tweaking each to use custom parameters.

That doesn't mean I'm perfect and never copy and paste code. Sometimes you just want or need to get it done. Some will not like my use of macros.

TomXP411
Posts: 1804
Joined: Tue May 19, 2020 8:49 pm

New productivity upload: X16 Edit - a text editor

Post by TomXP411 »


Yeah, I tend to create a load of macros, as well. By the time I’m done, my programs are more macro than assembly. 

Essentially, what this means is I’m making up my own programming language. And I’m fine with that. 

Ed Minchau
Posts: 508
Joined: Sat Jul 11, 2020 3:30 pm

New productivity upload: X16 Edit - a text editor

Post by Ed Minchau »


I don't use macros at all; my editor doesn't have that feature. I can however copy and paste code. 

Scott Robison
Posts: 952
Joined: Fri Mar 19, 2021 9:06 pm

New productivity upload: X16 Edit - a text editor

Post by Scott Robison »



On 10/3/2021 at 9:22 PM, Ed Minchau said:




I don't use macros at all; my editor doesn't have that feature. I can however copy and paste code. 



In this case, the macros are part of the assembler. Even notepad can use assembler macros. If the assembler supports, them, that is.

Post Reply