News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Operand must be relocatable

Started by 16bitPM, November 27, 2024, 01:49:19 AM

Previous topic - Next topic

16bitPM

Hi all,

I'm trying to convert the famous 256b demo "LATTICE" (Full source code here) from FASM to MASM syntax.
I'm stuck at the following:



PALETTE: mov dx,3c8h
ZMOVE    EQU $-2

...
...

DRAWX:   mov si,EYE
EYE      EQU $-2

...
...

ROTATE: fild word ptr [si-EYE+ZMOVE]   <<----


Lines like the one marked with <<---- fail with error A2094: operand must be relocatable.
I can see why it doesn't work, but somehow it works in FASM and I don't know how to do it properly in MASM.

Thx :-)


_japheth

Quote from: 16bitPM on November 27, 2024, 01:49:19 AM
PALETTE: mov dx,3c8h
ZMOVE    EQU $-2
...
...
DRAWX:   mov si,EYE
EYE      EQU $-2
...
...
ROTATE: fild word ptr [si-EYE+ZMOVE]   <<----

I can see why it doesn't work, but somehow it works in FASM and I don't know how to do it properly in MASM.

Both EYE and ZMOVE contain the $ symbol, making them "relocatable labels". You cannot add relocatable labels. but you can subtract them - if they are in the very same segment. So perhaps change the line to:

ROTATE: fild word ptr [si+(ZMOVE-EYE)]

Btw., Fasm doesn't know "offset" - I guess that line
DRAWX:   mov si,EYE

must be
DRAWX:   mov si,offset EYE

in Masm syntax.
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

16bitPM

Thanks!! I'll try that out.

Quote from: _japheth on November 27, 2024, 02:36:42 AMBtw., Fasm doesn't know "offset" - I guess that line
DRAWX:   mov si,EYE

must be
DRAWX:   mov si,offset EYE

in Masm syntax.

Well, EYE is an EQU,so I expect that OFFSET won't work.

Diederik.
PS: I still use your JWASM for retro fun. I find UASM too overbloated and your assembler is a gem and works great!



_japheth

Quote from: 16bitPM on November 27, 2024, 01:54:56 PMWell, EYE is an EQU,so I expect that OFFSET won't work.

Masm's EQU is a very strange beast. It can be used to define constants, text equates or (relocatable) labels; for labels, OFFSET should ( and will ) work.

QuotePS: I still use your JWASM for retro fun. I find UASM too overbloated and your assembler is a gem and works great!

Thanks, good to know! It's still updated on occation, but I'm no big fan of that SIMD stuff, hence a bit too lazy to add the newest 512-/1024-/2048-/...bit instructions.
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

16bitPM

Thank you, kind Sir! Your first suggestion worked!

The EQU wasn't needed, but the application crashes on exit. Oh well, I'll figure it out.

Quote from: _japheth on November 27, 2024, 05:36:40 PMThanks, good to know! It's still updated on occation, but I'm no big fan of that SIMD stuff, hence a bit too lazy to add the newest 512-/1024-/2048-/...bit instructions.

Not to mention the convoluted HLA stuff. I mean up to a certain point sure, but if it gets too big I'd switch to a higher level language and if needed do inline asm there.

Anyway programming modern processors is not fun anymore. Setting up a system has become very complex and tedious, and it's very hard to outperform a modern compiler. Modern assembly also isn't exactly elegant, if you care about performance. And I use assembly on old computers anyway (286, 386, Pentium, ...).

I've had some secret wishes though, but I don't think anyone else on the planet really cares, so...
(it's about support for true LIDATA structures, some of the not-implemented MASM features for full compatibility, Turbo Debugger compatibility and a way to exploit more of the obscure x86 stuff, such as separately define segment granularity, mainly for low-level stuff).

I tried to do the LIDATA-fix myself by looking at the MASM 5 and JWASM source code, but I just don't know enough about assemblers, compilers and linkers, NOR how to do open-source contributions properly... and it seemed much more difficult to do than I anticipated.

Also JWASMR.EXE sometimes crashes the computer with certain errors. If I can reproduce it I'll make a bug fix (I wasn't aware that JWASM was still maintained somehow). JWASMR is relevant for me because it gives me MASM 6 syntax on 16-bit CPU's. But let's be honest: this is a hobby.

Have a nice day :-)

TimoVJL

perhaps a conditionally compiled jwasm for 16-bit only could be useful ?
May the source be with you

16bitPM

I found that both MASM and JWASM produce different opcodes in several places. Mostly it doesn't matter (like 8-bit adc instructions) but there is one place where it may:

dec word ptr [bp-160+ZMOVE]

gets a 16-bit displacement instead of 8-bit with encoding FF 8E 71 00, which makes the code length 1 byte longer. I have no idea how to force this to 8-bit. Switching ZMOVE and 160 doesn't make a difference. Replacing the displacement with LOW(ZMOVE-160) changes the encoding to FF 8E 71 01.
The code generated by FASM is FF 4E 71.

The original code in FASM is

dec word [byte bp-160+ZMOVE]


~D~


16bitPM

Quote from: TimoVJL on November 28, 2024, 12:39:43 AMperhaps a conditionally compiled jwasm for 16-bit only could be useful ?

That's what JWASMR is.

_japheth

Quote from: 16bitPM on November 28, 2024, 01:13:51 AMI found that both MASM and JWASM produce different opcodes in several places. Mostly it doesn't matter (like 8-bit adc instructions) but there is one place where it may:

dec word ptr [bp-160+ZMOVE]

gets a 16-bit displacement instead of 8-bit with encoding FF 8E 71 00, which makes the code length 1 byte longer. I have no idea how to force this to 8-bit.

Are you sure that Masm generates a 1-byte offset? IIRC, if a relocatable label is involved, both Masm and JWasm will always generate a 16-bit displacement ( since the actual value is calculated at link time only ).

However, you can overcome this if there's just 1 source. For this you'll have to change the label to a constant; this can be done by subtracting 2 labels, the second one pointing to the very first byte of the code:

         .code
startlabel:

PALETTE: mov dx,3c8h
ZMOVE    EQU $-2
ZMOVEX   EQU ($-2-startlabel) AND 0ffffffffh ; the "AND xxx" required by JWasm only, probably a bug...
...
         dec word ptr [bp-160+ZMOVEX]
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

daydreamer

Quote from: 16bitPM on November 28, 2024, 12:32:40 AMAnyway programming modern processors is not fun anymore. Setting up a system has become very complex and tedious, and it's very hard to outperform a modern compiler. Modern assembly also isn't exactly elegant, if you care about performance. And I use assembly on old computers anyway (286, 386, Pentium, ...).
I have tried write some tiny Dos16bit demos/games,the challenge of slow few mhz cpu and lack of gigabytes of memory makes it a real challenge compared to 32bit/64bit several ghz cpu and very fast hardware accelerated gpus
unfinished projects,but still fun,ok I run on DOSbox
there are still many algos/code that worked well on 16bit regs or smaller registers


my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

16bitPM

Quote from: _japheth on November 28, 2024, 02:23:37 AMAre you sure that Masm generates a 1-byte offset? IIRC, if a relocatable label is involved, both Masm and JWasm will always generate a 16-bit displacement ( since the actual value is calculated at link time only ).

No I meant, MASM and JWasm produce a different opcode from FASM. Sorry :-)

Quote from: _japheth on November 28, 2024, 02:23:37 AMHowever, you can overcome this if there's just 1 source. For this you'll have to change the label to a constant; this can be done by subtracting 2 labels, the second one pointing to the very first byte of the code:

         .code
startlabel:

PALETTE: mov dx,3c8h
ZMOVE    EQU $-2
ZMOVEX   EQU ($-2-startlabel) AND 0ffffffffh ; the "AND xxx" required by JWasm only, probably a bug...
...
         dec word ptr [bp-160+ZMOVEX]


Naah, that didn't work. I thought you meant AND 0ffh, but that didn't work either (neither JWasm nor MASM 6.11).

_japheth

Quote from: 16bitPM on November 28, 2024, 11:14:53 PMNaah, that didn't work. I thought you meant AND 0ffh, but that didn't work either (neither JWasm nor MASM 6.11).

Ok, I don't know what you tried, but I did some more investigation  - because, as it turned out, there's a (minor) bug in JWasm and a bug in Masm. Here's my (full) test case:
;--- subtraction of 2 labels.
;--- jwasm < v2.19 was confused if an intermediate result was negative
;--- due to - erroneously - using 32-bit arithmethic.
;--- since jwasm v2.19, all calculation is 64-bit.

;--- Masm also has a bug - it does truncate the displacement

.286
.model tiny
.stack

.code
@:
mov si, offset Z2
;Z2  equ ($ - 2 - @) and 0ffffh   ; workaround - works with JWasm < v2.19
Z2  equ ($ - 2 - @)       ; this works since JWasm v2.19

start:
inc word ptr [bp-129+Z2]  ; ok, byte displ with Masm/JWasm
inc word ptr [bp-130+Z2]  ; JWasm ok; Masm truncates to a byte displ - bug!?
inc word ptr [bp-130+1]   ; ok, word displ
mov ah,4ch
int 21h
END start

It's 16-bit code, because your code also was 16-bit, but it's actually also relevant for 32-bit ( most likely also for 64-bit ).
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

16bitPM

Quote from: _japheth on November 29, 2024, 05:28:08 AMIt's 16-bit code, because your code also was 16-bit, but it's actually also relevant for 32-bit ( most likely also for 64-bit ).

Well, well, well!!
Shall I make a bug fix request on Github?