English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 21 March 2024, 13:58   #1
remz
Registered User
 
Join Date: May 2022
Location: Canada
Posts: 139
Double the memory address

Hello ASM coders,

I am trying to optimize this and I am stuck. Suppose you have a buffer in memory. I would like to compute its address times two + 24, like so:
Code:
	move.l 	#buffer+24, a1
	add.l		#buffer, a1
However this is a constant: I would have liked to have been able to do this instead:
Code:
	move.l 	#buffer+buffer+24, a1
But this doesn't assemble on vasm. It says "illegal relocation".
Could you help me find a way or if it is even possible?

Reason: The purpose of this "buffer times two" is to have an efficient buffer swap. Imagine in pseudo code:
Code:
<init>
byte buffer[48]; // enough space for two buffers of 24 bytes
byte* current_buffer = &buffer[0];

<usage>
current_buffer = &buffer[0] + &buffer[24] - current_buffer;
This would swap the buffer between address [0] and [24].
The code with the 'add.l' line works, but it bugs me to have to runtime-add at link-time constant.
remz is offline  
Old 21 March 2024, 14:13   #2
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
I dont use vasm. Maybe try?

lea 2*buffer+24,A1
Don_Adan is offline  
Old 21 March 2024, 14:14   #3
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
lea 24(a1,a1.l),a1
ross is offline  
Old 21 March 2024, 14:25   #4
remz
Registered User
 
Join Date: May 2022
Location: Canada
Posts: 139
Thank you both!

Don: similar to the move buffer+buffer:
illegal relocation
> lea 2*buffer+24,A1

ross: nice and compact, but it is still added at runtime instead of compile time. (however, it is efficient and clever!)
remz is offline  
Old 21 March 2024, 14:29   #5
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,411
Quote:
Originally Posted by remz View Post
Hello ASM coders,

I am trying to optimize this and I am stuck. Suppose you have a buffer in memory. I would like to compute its address times two + 24, like so:
Code:
    move.l     #buffer+24, a1
    add.l        #buffer, a1
However this is a constant: I would have liked to have been able to do this instead:
It should probably be pointed out that the address of buffer is not really a constant. Unless you specifically make it point to a single address under all situations (which is not something I'd recommend), it can effectively end up anywhere in memory.

I'd personally use ross's method. Safe, simple and doesn't care about which address buffer is located at.
roondar is offline  
Old 21 March 2024, 15:01   #6
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
If You want to use similar code, You can try:

Code:
 lea buffer+24/2,A1
 add.l A1,A1
Don_Adan is offline  
Old 21 March 2024, 15:11   #7
hooverphonique
ex. demoscener "Bigmama"
 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,624
Quote:
Originally Posted by ross View Post
lea 24(a1,a1.l),a1
I don't think I've ever seen the displacement being an address register...
hooverphonique is offline  
Old 21 March 2024, 16:55   #8
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,039
You can't multiply, shift, swap or split in some way, divide, and/or/eor/not/neg a relocatable address, you can only add or subtract a constant.
A very simple example... If your code looks like abc+$20, when you hexdump it you will see e.g. $00000320, and then in run-time when your program is loaded at e.g. address $120000, the loader will add that and then address will finally become $120320.
Because $120000 is the unknown at compile time.

So what in c/c++ looks like a simple solution, when you translate it to asm it won't necessarily end up being pretty. I feel little in the dark here, not seeing the whole picture...
If you have to do the swap multiple times, maybe load both pointers to aregs and use exg ax,ay?
Or use eor to swap, something like:
Code:
; a4=&buffer[0], d4=curr_offset
  eor.w #24,d4   ; swap
  lea (a4,d4.w),a0
; proceed to use a0
If it's a once per frame deal, have offset (d4) be in memory:
Code:
; e.g. if a5 is a base register pointing to my_data, otherwise use absolute addressing or pc-relative where possible
  eor.w #24,offset-my_data(a5)   ; swap
...
  lea buffer,a0
  add.w offset-my_data(a5),a0
; proceed to use a0
There are better ways to handle this than 32-bit pointer arithmetics, but it depends on the context.
a/b is offline  
Old 21 March 2024, 17:53   #9
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
Right, anyway Amiga exe file can handle similar code:

Code:
	move.l 	#buffer+buffer+24, a1
This is easy enough, if I remember right, how works dos.library.
2 relocs are necessary. Not only 1.
Then this is only question of assembler, if can create 2 relocs for this code.
For single reloc this is impossible, for two relocs this is possible.
Anyway it looks like code can be optimized for size and speed, if 2 relocs will be used
Then remz idea is not bad, like look after first look. And he can manually add 1 reloc to Amiga exe file relocs table, if no assembler has support for this code.
Don_Adan is offline  
Old 21 March 2024, 17:54   #10
remz
Registered User
 
Join Date: May 2022
Location: Canada
Posts: 139
Thank you for your suggestions and replies. It makes a lot of sense.
My request is slightly silly, it is a bit like if I was asking the loader to "store the address of this symbol but doubled". It would be unlikely this feature would exist.
(But technically, it is the same job as relocating/updating the addresses on loading.)
I incorrectly thought it was the linker's job, but in fact this is done by the loader when placing the executable in memory and "burning-in" all the addresses.
I'll stick with the solution of computing the double-address once at initialization and then using that at runtime.
remz is offline  
Old 21 March 2024, 20:19   #11
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,231
Out of curiousity, why is there a need to double an an address? This is in almost all cases an indication of an improper design. There is BCPL and its BPTRs which require quadrupling pointers (and yes, it is quite a bizarre design), and I have seen something similar in the console device because its "attribute map" is word-sized, unlike the character map, and there it is also an indication of an improper design (the attribute map should not be reachable in such a way, but be really represented by a proper data structure - and no, the array is not the only useful data structure).
Thomas Richter is offline  
Old 21 March 2024, 21:51   #12
AestheticDebris
Registered User
 
Join Date: May 2023
Location: Norwich
Posts: 376
You don't need to double the address anywhere, that's not what your pseudo code is even doing.

The first buffer is &buffer, the second is &buffer+24 (assuming bytes but it's a fixed offset regardless) - all the maths works without ever having to double anything.

I think you've confused yourself by thinking having the two "buffers" combined into one somehow means the second one is at double the address, but that's not what is happening.
AestheticDebris is offline  
Old 22 March 2024, 00:02   #13
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,039
X is either A or B. A+B-X will give you B if X=A, or A if X=B (effectively a swap).
Code is logically OK, it's just not resolvable in compile time due to illegal arithmetics with relocatables, but as I already said there's no need for said arithmetics (with or without creative solutions like the one Don Adan proposed). Shorter and faster code is possible, but more details about usage are needed.
And then there's also this: Amiga is only using a half of the 32-bit address space and "fortunately" it's safe to add arbitrary pointers, otherwise (e.g modern OS's) it could result in overflow and a bad pointer. So I'd simply call it a bad practice (but I'd still do it myself if it would save me a few cycles :P).
a/b is offline  
Old 22 March 2024, 01:36   #14
remz
Registered User
 
Join Date: May 2022
Location: Canada
Posts: 139
a/b: I don't think overflow would be an issue. Dealing with unsigned (modulo) arithmetic, it nevers overflows in fact. And the subtraction works anyway.
x=a
x=a+b - x
Will work even if a+b wraps around the 32-bit long.
remz is offline  
Old 22 March 2024, 03:29   #15
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,039
Uff, you're right. Should've finished the calculation, trapv ftl ><.
a/b is offline  
Old 22 March 2024, 06:37   #16
Karlos
Alien Bleed
 
Karlos's Avatar
 
Join Date: Aug 2022
Location: UK
Posts: 4,165
Why do you need double the address of something? Especially something like a symbol that has a runtime address that could be anywhere, what does double the address point at? It could be pointing at arbitrary memory, hardware or even nothing at all.
Karlos is offline  
Old 22 March 2024, 07:36   #17
Rotareneg
Registered User
 
Rotareneg's Avatar
 
Join Date: Sep 2017
Location: Kansas, USA
Posts: 327
*evil laugh* Sounds like the job for self-modifying code!
Rotareneg is online now  
Old 22 March 2024, 12:12   #18
remz
Registered User
 
Join Date: May 2022
Location: Canada
Posts: 139
1) Rotareneg: I personally hate self-modifying code, except on no-cache system like a Tandy CoCo, where it makes a lot of sense
2) Karlos: I never access the 'double memory address': the value is just used as a fast swap between two addresses. I'll try to explain with numbers to make my intention perhaps clearer. Values are in decimal, consider them absolute addresses:
buffer 1 is at address 20
buffer 2 is at address 36
sum of addresses = 20 + 36 = 56
SUM=56
Say X is your pointer, initially starting on buffer 1.
X=20
Now at every frame, you wish to alternate between the two buffers. The calculation would be:
X=SUM-X
This will make X swap between 20 and 36.

Again just to be clear, this exercise is just for fun and understanding the inner workings. My question was essentially to see if this value (i.e.: adding two addresses together) could have been calculated at load-time by the loader, instead of being done at runtime by my code.
remz is offline  
Old 22 March 2024, 15:11   #19
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,474
I understand that you want the linker to solve the problem for you, but I think that using realtime constants the code is much simpler, more intuitive and faster

I would use something like this:
Code:
		lea	buffer1,a0
		lea	(buffer2-buffer1,a0,a0.l),a1

.loop	        move.l	a0,d0
		move.l	a1,a0
		suba.l	d0,a0
;		bra.b	.loop

buffer1	ds.b	16
buffer2	ds.b	16
a0 is always consistent and contains the address of the buffer in use (which could also be initialized relative to the PC).
a1 is a fast constant (which requires no relocation by LoadSeg and uses fewer cycles than a constant value).

If instead you absolutely want an exe file that relocates a1 with a constant value it is possible, but the linker is not able to generate it for you.
It's not a problem with LoadSeg or the Amiga Hunks, nothing in the relocation table prevents you from 'rearranging' the same longword in memory twice.

So I can also create one for you by 'replacing' the linker job, but I don't think that's the purpose
Furthermore, OS purists would tear me to pieces because it's a dirty trick..
ross is offline  
Old 22 March 2024, 15:47   #20
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
No, this is not dirty trick. This is trick only.
Because most (or maybe all) Amiga assemblers dont has support for double relocation for same longword.
Same code at absolute addresses will be assembled by Amiga assemblers.
Then for me can be created for Amiga exe file too.
Of course I dont see really good usage for this command, because code is too short for me.
But maybe can be useful for something. Its minimum 2 bytes shortest (and 6 cycles fastest for 68000, if I remember timings) , than similar code.
Don_Adan is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Double PAL / Double NTSC, oficially supported by WHDLoad... Shoonay project.WHDLoad 3 15 May 2021 19:42
DOUBLE DRAGON II vs DOUBLE DRAGON 3 AMIGA TITLE MUSIC ZEUSDAZ Retrogaming General Discussion 20 16 January 2021 13:29
Any way to avoid value change in memory address permanently fstarred Coders. General 6 12 August 2020 18:51
List memory address range solarmon Coders. Scripting 2 18 December 2019 15:31
NAT address -Rob- support.Other 7 07 April 2008 00:06

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 21:08.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10808 seconds with 13 queries