Jump to content
IGNORED

a couple of 68K ASM questions


Recommended Posts

I wrote this little program to print random Hebrew letters

to the screen:

;RANDOM Hebrew PRINTER
;BY 'ACE'
;April 11 2019


loop:

move.w #17,(sp)    ;get random
trap #14	   ;call GEM

cmp #$c1,d0        ;compare to one before Alef
ble loop           ;less or equal? branch back to loop
cmp #$dd,d0        ;compare to one greater than Tau
bge loop           ;greater or equal? branch back to loop

move d0,-(sp)      ;put random on stack


move.w #2,-(sp)    ;print it
trap #1            ;

jmp loop



bp:
rts
end

Now, it works but very slow.

 

How to optimize for machine language speeds?

 

Another question is that I DID NOT clean up the stack

after its use and it runs fine. I tried this with other little

programs (not ADDQ.L or whatever to the stack)

and they seem to work okay.

 

Is it absolutely necessary to add and clean up the stack

after its every usage?

 

Somebodys gotta know.

 

Todah rabah.

|:)

Edited by Wally1
Link to comment
Share on other sites

yes you need to clean up the stack :D

 

imagine that you stack is a glass, and every time you put something on the stack, was like you put some water to the glass.

and ever time you clean up the stack was if you drain some water from the glass.

 

when you can imagine when would happen if you don't clean up the stack.

it will in the long run crash you program, it could also crash the ST.

Link to comment
Share on other sites

I wrote this little program to print random Hebrew letters

to the screen:

 

Now, it works but very slow.

 

How to optimize for machine language speeds?

There are lots of things you can do (and many different ways to do these things).

 

Reading your code I noticed that you call random and check if the value returned is within range. This is super slow as you're calling an expensive routine over and over and is probably the worst offender for speed in your program. So, how to speed this up?

 

From your code I see that the number has to be between $c1 and $dd inclusive. Unless I'm mistaken that's 29 numbers. So, instead of waiting until the random number generator gives you the right number, why not modulo the result instead? Quick math refresher, the modulo is the result of a division. So if we divide by 29, the modulo is guaranteed to be between 0 and 29. So, something like this will do:

 

loop:

move.w #17,(sp) ;get random
trap #14 ;call GEM

and.l #$ffff,d0 ;clear the upper 16 bits so that division will not overflow
divu #29,d0 ;divide by 29. The low word of d0 now contains the result of the division and the high word contains the modulo
swap d0 ;bring the modulo to d0.w. This will be between 0 and 29
add.b #$c1,d0 ;now our number is between $c1 and $dd

move d0,-(sp) ;put random on stack
move.w #2,-(sp) ;print it
trap #1 ;

jmp loop

That should be fine. Of course that's far from the most optimal code but I'm sure it's much faster than your version :)

 

Another question is that I DID NOT clean up the stack

after its use and it runs fine. I tried this with other little

programs (not ADDQ.L or whatever to the stack)

and they seem to work okay.

 

Is it absolutely necessary to add and clean up the stack

after its every usage?

 

Somebodys gotta know.

 

Todah rabah.

| :)

Regarding the stack: Physically it occupies a part of your RAM, so it's not at some magic place where it doesn't matter. To elaborate this using a cruel graph:

 

ooo..........................................Xxxxxxxx..
^                                                     ^
RAM START                                             RAM END

This is a very rough model of the ST RAM layout. The 'o's at the start is memory reserved for the system. The '.'s is free memory that applications can use. The 'X' is the address of the stack, and finally 'x' is screen RAM.

 

So, computers usually place the stack at the highest allowed address, since they go backwards. I.e. when you push parameters on the stack you use -(sp). This works exactly like an address register (and in fact SP is register A7 in 680x0).

 

So what happens if you don't tidy up the stack? It starts writing RAM backwards. So something like this will happen:

 

ooo................................XXXXXXXXXXXxxxxxxx..
^                                                     ^
RAM START                                             RAM END

The stack will start writing over RAM. Usually your program starts in low RAM, right after the 'o's, so it will be safe for a while. Perhaps even forever if you don't use the stack too often.

 

But if you keep hammering data to the stack it will eventually go and overwrite everything, including your code. This will definitely lead to a crash!

 

Hopefully this explains things.

Edited by ggn
Link to comment
Share on other sites

wow thanks a million

 

 

i gotta study your answer

 

i suspected that to chop half of the random byte was necessary

but didnt know how to do it.

 

and i have to learn what 'modulo' is

 

smart!

 

 

 

you are from Greece. do you like Gyros?

Edited by Wally1
Link to comment
Share on other sites

wow thanks a million

 

 

i gotta study your answer

 

i suspected that to chop half of the random byte was necessary

but didnt know how to do it.

 

and i have to learn what 'modulo' is

 

smart!

Here's a nice resource with hands-on examples: https://www.omnicalculator.com/math/modulo

 

you are from Greece. do you like Gyros?

Sure, it's pretty good!

Link to comment
Share on other sites

There is very fast way to generate pseudo random numbers . Just one of many links dealing with it: http://www.cs.miami.edu/home/burt/learning/Csc609.022/random_numbers.html

I used that way in many cases. For instance so called random dissolve - something like pixelwise fading needs fast pseudo random gen.

 

And if you want extra high speed may use direct draw to screen instead trap calls.

Link to comment
Share on other sites

Can you provide examples Peter?

Here is ASM code for 32 bit pseudo random generator, with shifts:

*random generator

  btst #2,d6
  bne.s y1
  btst #16,d6
  beq.s peven
  bra.s podd
y1 btst #16,d6
  beq.s podd
peven bset #31,d6
  bra.s rotate
podd bclr #31,d6
rotate  rol.l #1,d6 

In case of 32 bit length, feedback are bits 2 and 16, and parity of them is condition for setting or resetting last bit, 31 before shift, better said rotate - it will go in bit 0 .

There are specific feedback bits for every length in bits, sometimes it's more than 2 bits. Of course, here talking about feedback what will generate full range of values. So in case of 32 bit length it is all 2 POW 32 different values.

You may find pages about it, where are concrete feedback bits for different bit lengths. I made in past some proggie which tested are used feedback bits correct for getting 2 POW n different values. Will look to dig it out.

Link to comment
Share on other sites

Here is simple code I used in some cases:

txtpr  

	move.l	$44E.w,a1   * dest - screen start
	lea	4(a1),a1   * move to dark blue color  - low res
	move.l	a1,a4

txtloop	move.b	(a0)+,d5   * char code ASCII 
	beq	txtend
	cmp.b	#13,d5
	bne.s	prich
	addq.b	#1,txty
	clr.b	txtx
	bra.s	txtloop

prich	moveq	#0,d0
	moveq	#0,d1
	move.b	txtx,d0
	move.b	txty,d1	

	mulu	#$500,d1
	add.l	d1,a1

	move.l	d0,d2
	bclr	#0,d2
	lsl.w	#2,d2   * x8 - because it is step 2
	btst	#0,d0
	beq.s	notOd
	addq.w	#1,d2
notOd	add.l	d2,a1   * dest, bitplane n

	lea	font(pc),a2
	adda.w	d5,a2
	moveq	#7,d3

charl	move.b	(a2),(a1)
	lea	$100(a2),a2
	lea	$A0(a1),a1
	dbf	d3,charl

	addq.b	#1,txtx
	move.l	a4,a1

	bra	txtloop

txtend	rts

txtx  dc.b  0
txty  dc.b  0

font   incbin  "FONT"



FONT.ZIP

Link to comment
Share on other sites

  • 2 weeks later...

okay

 

i need to know why when I

MOVE #$21,(SP)

that is, move something to the top of the stack

(on my 1040 ST the stack top is $F8000)

and then examine memory at that very address ($F8000)

NOTHING is ever there!

 

I have some idea but would like to hear an expert opinion.

 

however if I: "MOVE #$21,-(SP)"

then the stack pointer decreases and I examine memory

at $F8FFE, the "$21" will be there!

 

 

also, I wrote the object code for this (improved) Hebrew random print

program. It becomes a .PRG file but when I run it it only prints one line

of Hebrew at the very top of the screen!

 

The original source code when run from my assembler works as it should,

filling the screen with random Hebrew letters.

 

AtariAge for some reason won't allow me to attach my .PRG file so

here is the source code for my little work of art that needs your help:

;RANDOM Hebrew PRINTER
;BY 'ACE' with help from ggn of Greece
;April 14, 2019

loop:

move.w #$11,-(sp)   ;get random
trap #$e	    ;call GEM
addq.l #$2,sp       ;fix stack

and.l #$ffff,d0     ;clear upper 16 bits division not overflow
divu #$1b,d0        ;divide by 27
swap d0             ;modulo to D0
add.b #$c2,d0       ;add 194 to random

move d0,-(sp)       ;random on stack
move.w #2,-(sp)     ;print it
trap #1             ;call GEM
addq.w #$4,sp       ;stack correction


jmp loop



bp:
rts
end

thanks !

:jango:

Link to comment
Share on other sites

okay

 

i need to know why when I

MOVE #$21,(SP)

that is, move something to the top of the stack

(on my 1040 ST the stack top is $F8000)

and then examine memory at that very address ($F8000)

NOTHING is ever there!

 

I have some idea but would like to hear an expert opinion.

 

however if I: "MOVE #$21,-(SP)"

then the stack pointer decreases and I examine memory

at $F8FFE, the "$21" will be there!

 

 

also, I wrote the object code for this (improved) Hebrew random print

program. It becomes a .PRG file but when I run it it only prints one line

of Hebrew at the very top of the screen!

 

The original source code when run from my assembler works as it should,

filling the screen with random Hebrew letters.

 

AtariAge for some reason won't allow me to attach my .PRG file so

here is the source code for my little work of art that needs your help:

;RANDOM Hebrew PRINTER
;BY 'ACE' with help from ggn of Greece
;April 14, 2019

loop:

move.w #$11,-(sp)   ;get random
trap #$e	    ;call GEM
addq.l #$2,sp       ;fix stack

and.l #$ffff,d0     ;clear upper 16 bits division not overflow
divu #$1b,d0        ;divide by 27
swap d0             ;modulo to D0
add.b #$c2,d0       ;add 194 to random

move d0,-(sp)       ;random on stack
move.w #2,-(sp)     ;print it
trap #1             ;call GEM
addq.w #$4,sp       ;stack correction


jmp loop



bp:
rts
end

thanks !

:jango:

Hi Wally

a couple of things, lets start with -(Sp) and (SP)+ or -(Ax) (Ax)+.

ok it actual telling you what its doing.

 

In case of -(SP),-(Ax) what it means is, it first start with subtracting the length of the data to the Ax/SP pointer and after that is finish, its moves the data ,

 

so in case if you use a long word. and let say A0 points Address 1000 and you write Move.l #$12345678,-(A0)

it will start with subtracting 4 from A0 so it now pointing to 996, and if you look in address 996 it would say $12345678

 

same with move.w but its only 2 bytes and of cause move.b its only a byte,

but i am not sure that it work when using a byte on the stack Pointer (SP)

 

same with (SP)+,(Ax)+ it just mean that the SP or AX will be add to instead of being subtracted from, one more thing to beware of here, is that the add fist will be add after the memory operations.

 

same example as before

let say A0 points address 996 and the contains in 996 is #$12345678

and if you write Move.l #$0,(A0)+

it will start by moving #0, to address 996 and after that have been done, it now add 4 to the address register.

 

before the move #0 the address contain the value of #$12345678 after the move.l. A0 now pointing to address 1000 and if you look in memory address 996 it should say zero

 

but you can remember it like this is the mathematical symbols before the Parenthesis

it will do the sub first (and in this case) the move after.

 

and if the mathematical symbols are after Parenthesis.

it will do the (in this case) move first and the add after

 

but the party don't stop here. you can do the same with

clr.b.w.l -(ax/sp)+

tst.b.w.l -(ax/sp)+

cmp.b.w.l -(ax/sp)+

or.b.w.l -(ax/sp)+

and.b.w.l -(ax/sp)+

and more

 

why use the -()/()+, I think you get the add and the sub for free. (but I am not 100% sure maybe an other can tell you).

 

one more thing don't use jmp or jsr there can be cases where you only can use the like jmp (A0)

use bra and brs

 

i hope you get my nonsense, i have been very sick the last week, and still not 100%.

Link to comment
Share on other sites

thank you fedepede

 

I was talking about

when the stack pointer is accessed without, the plus or minus (+ or -)

 

"MOVE #$21, (SP)" [notice NO plus or minus]

 

and say stack pointer says $F8000

 

and i check memory $F8000

 

there is nothing there!

 

when you access the stack without a plus or minus

it means the top of the stack.

 

but I don't know why the memory address holds nothing.

 

I hope you feel better fedepede

Edited by Wally1
Link to comment
Share on other sites

I have 1040 ST.

 

i guess its because $F8000 is the very top of memory or something.

 

not the best explanation or whatever...

 

 

can you help with my program

it only prints the very first line at the top of the screen

and nothing else.

 

when run from assembler it fills the whole screen.

Link to comment
Share on other sites

You still use Seka? I could make a source code that can do what you need and uploaded it... and you can take what you need from it, and if you have any questions to it just ask.

But it have to wait for tomorrow I am going out for the rest of the day ?

Btw how much do you know to the Atari hardware like video chip ect.

Link to comment
Share on other sites

yeah i still use Seka

 

its okay but one thing is it exits to TOS with almost every program break.

 

I dont really know Atari hardware like video chip stuff.

 

I try to learn simple things like hardware independent beginner code, stuff like that

 

i am just a beginner myself.

 

and i just ordered DevPac one on a floppy from ebay.

 

thank you very much fedepede

Edited by Wally1
Link to comment
Share on other sites

in Seka you can't terminate a program like you do with other software.

it how you normal terminate a program

 
                  CLR.W     -(A7)  ;PTERM0
                  TRAP      #1
                  Rts 

But in Seka you have to rem these two lines, and only to let them be compiled them the last time (Or when the program is finish for release),

 

                  
;                  CLR.W     -(A7) ;PTERM0
;                  TRAP      #1
                  Rts

now you should be able to run and exit a program in seka with out it exiting to TOS.

 

but give me an idea what you goal would be with this program, so i know what i should make?

Edited by fedepede04
Link to comment
Share on other sites

well

 

I just trying to print random Hebrew (which is in TOS ROM)

to the screen.

 

you dont have to write it for me

 

cause it works from Seka but not as a .PRG file

 

As a .PRG file, it just prints one line at the top of the screen

 

here it is:

;RANDOM Hebrew PRINTER
;BY 'ACE' with help from ggn of Greece
;April 14, 2019

loop:

move.w #$11,-(sp)   ;get random
trap #$e	    ;call GEM
addq.l #$2,sp       ;fix stack

and.l #$ffff,d0     ;clear upper 16 bits division not overflow
divu #$1b,d0        ;divide by 27
swap d0             ;modulo to D0
add.b #$c2,d0       ;add 194 to random

move d0,-(sp)       ;random on stack
move.w #2,-(sp)     ;print it
trap #1             ;call GEM
addq.w #$4,sp       ;stack correction


jmp loop



bp:
rts
end

i appreciate your help Fedepede

 

and i will try that trick in Seka

 

i guess you could run the program to see what i am talking about

 

thank you

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...