News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

A2094: Operand Must be Relocatable?

Started by TheGodOfKratos, April 15, 2017, 01:50:11 PM

Previous topic - Next topic

TheGodOfKratos

I'm getting the error in Visual Studio 2017 listed in my subject. It's A2094:operand must be relocatable. The macro works when I pass constant integers but when I pass variable identifiers I get the assembler error message. It has something to do with passing variables. Can someone see what's wrong with the code?

https://pastebin.com/CPSe1xmq

aw27

Instead of if - endif try .if - .endif  :idea:

TheGodOfKratos

Your suggestion is for run-time if/else checks I believe. The IF ENDIF directives are preprocessor instructions that determine what ends up in the run-time instructions.

aw27

Quote from: TheGodOfKratos on April 15, 2017, 02:49:03 PM
Your suggestion is for run-time if/else checks I believe. The IF ENDIF directives are preprocessor instructions that determine what ends up in the run-time instructions.

They serve different purposes.
At compile time it is not possible to decide a run-time decision.
This is a compile time decision:

WHATTODO EQU -1

mLocate MACRO   xval, yval
    IF WHATTODO LT 0
     mov ax, xval
        EXITM   
    ELSEIF  WHATTODO GT 0 
     mov cx, yval
        EXITM
    ENDIF
ENDM




jj2007

Quote from: TheGodOfKratos on April 15, 2017, 02:49:03 PM
Your suggestion is for run-time if/else checks I believe. The IF ENDIF directives are preprocessor instructions that determine what ends up in the run-time instructions.

Yes indeed. But how can the assembler know what is at runtime in xval? That's possible only if xval is an immediate constant.

mLocate MACRO xval, yval
IF xval LT 0
EXITM ;; xval < 0?
ENDIF
IF yval LT 0 ;; yval < 0?
EXITM ;; if so, exit
ENDIF

mov bx,0 ;; video page 0
mov ah,2 ;; locate cursor
mov dh,yval
mov dl,xval
int 10h ;; call the BIOS
ENDM


Btw it's better if you post your code here, as shown above. Not everybody is willing to open external pages, too much clicking is not good for your health.

hutch--

I wish Kip Irvine would do his own support, its a commercial product sold to university students among others so he should be able to manage it. For our members to answer question on Irvine examples, they must get access to them then go to an external site to see that code example then try and work out how to fix it within the confines of lousy code design.

TheGodOfKratos

Quote from: hutch-- on April 15, 2017, 10:53:26 PM
I wish Kip Irvine would do his own support, its a commercial product sold to university students among others so he should be able to manage it. For our members to answer question on Irvine examples, they must get access to them then go to an external site to see that code example then try and work out how to fix it within the confines of lousy code design.

I can certainly do that if it's the preference. The external websites that are legitimate make code pasting so much easier. It would also save storage space on the servers here if that's any type of issue. Whatever the policy here is, it's fine with me.

Mr. Irvine may have a website that offers some kind of support. But I didn't see any public forums on his main website. Maybe through the book publishers website you can pay extra money to some forum there. I don't know for sure. I'm okay with 99% of his material. I wonder if this is just a screwup on his part that hasn't been updated or detected.

Can someone verify me at this point that I'm nothing more than a n00b Kip Irvine student wanting answers to assembly questions? I have no interest in spamming this website.

TheGodOfKratos

Quote from: jj2007 on April 15, 2017, 07:09:42 PM
Quote from: TheGodOfKratos on April 15, 2017, 02:49:03 PM
Your suggestion is for run-time if/else checks I believe. The IF ENDIF directives are preprocessor instructions that determine what ends up in the run-time instructions.

Yes indeed. But how can the assembler know what is at runtime in xval? That's possible only if xval is an immediate constant.

mLocate MACRO xval, yval
IF xval LT 0
EXITM ;; xval < 0?
ENDIF
IF yval LT 0 ;; yval < 0?
EXITM ;; if so, exit
ENDIF

mov bx,0 ;; video page 0
mov ah,2 ;; locate cursor
mov dh,yval
mov dl,xval
int 10h ;; call the BIOS
ENDM


Btw it's better if you post your code here, as shown above. Not everybody is willing to open external pages, too much clicking is not good for your health.

Well, my assumption was that the xval yval (or in reality, col, and row) would be evaluated as the constants 15, 20 (as defined in the code) during the preprocessing phase. But I guess that isn't happening. I'm coming to the conclusion this is a mistake in the book that the author may or not be aware of at this point.

hutch--

You are not the problem, it was a complaint about Kip Irvine not supporting his customers.

jj2007

Quote from: TheGodOfKratos on April 15, 2017, 11:54:26 PMWell, my assumption was that the xval yval (or in reality, col, and row) would be evaluated as the constants 15, 20 (as defined in the code) during the preprocessing phase.

I see what you mean (and you see how useful it can be to post code directly here ;)):
.data
    row BYTE 15
    col BYTE 20
.code

main    PROC
    mLocate -2,20
    mLocate 10,20
    mLocate col,row


row and col are variables defined as 15 and 20, i.e. using two immediate constants. But how could the assembler know what happened in between?

    mLocate -2,20
    mLocate 10,20
    mov col, 100    ; nobody stops you from reassigning a VARIABLE
    mLocate col,row


TheGodOfKratos

I think I've figured this out a bit more. I think you can pass variable names to macros as arguments. But when it says operand must be relocatable I think it means you have to move your argument inside the macro code to another memory location or register to be able to use it. Then the macro works. Actually, when I take out all the IF ENDIF directives the code works.  If you just pass the name of the variable and never move the value to another place then the actual value is never realized during the preprocessing phase. Ultimately, this is what I consider a bug in Kip Irvines book.

You can pass variable identifiers to a macro, where they "ultimately" would be used in run-time instructions, but since they are not constants they cannot be evaluated by the preprocessor. I don't think the variables even exist during the preprocessing phase, meaning they probably don't have a reserved size and memory location.

jj2007

You should guess less and instead try harder to understand the logic.

IF xval LT 0
  EXITM
ENDIF


This sort of IF generates different code, depending on the constant input, e.g. mLocate 10,20

.if xval<0
  print "xval is below zero"
.else
  print "xval is abov or equal zero"
.endif


The .if generates always the same code, independently of the value passed to the macro as a variable, e.g. mLocate col,row
However, the (run-time) decision which line to print depends on the value of the variable.

TheGodOfKratos

I think I do understand the logic. You didn't agree with or deny my logic. Passing variable identifiers to macro makes it easy enough to substitute those variable names in a macro. All that's being passed in reality is a text string which, later on, will represent a true memory location. But those variables don't exist at the preprocessor stage. They have no real memory address. So using the macro argument, in this case, "col" or "row" produces no constant value so the preprocessor directives have nothing to evaluate.

IF xval < 0 becomes IF col < 0. That's no good because this is a preprocessor directive.

However, once an IF ENDIF preprocessor directive is determined to be "true" then using "col" or "row" in between the preprocessor directives inside the macro definition works. The macro definition spits out run-time code that is perfectly valid.


IF truth
  mov ah, col
mov dl, row
int 21h
ENDIF


is perfectly valid because col and row will be evaluated at run-time. As Bill O'Riley likes to say "Am I wrong?"


Cliften

#13
Quote from: aw2r7 on April 15, 2017, 02:46:03 PM
Your suggestion is for run-time if/else checks I believe. The IF ENDIF directives are preprocessor instructions that determine what ends up in the run-time instructions.

Neither worked for me.  :icon_confused:

jj2007

It works for me all the time, Cliften. But without seeing at least the surrounding code, nobody can tell you why it doesn't work for you. Our crystal balls are not very good 8)