News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

operands must be in same segment??

Started by asmftw, August 02, 2008, 03:54:48 AM

Previous topic - Next topic

asmftw

Hey, why can't I use operands in different segments?

CODE_START is a label definsed at the beginning of .code.
dwImageSize is defined in uninitialized data.

mov edi,[esi + offset dwImageSize - offset CODE_START]

And I can't compile because of:
RelocatePointers.asm(10) : error A2025: operands must be in same segment

I don't see why masm32 can't calculate the difference between these two offsets.
Is there any way around this?

I also wonder if there is a constant that points to the base of the image, and a constant that tells the size of the image.
I could just use GetModuleHandle or read from the PEB, but I want to have the values hardcoded instead of making the app look them up.

hutch--

It helps if you tell MASM what is in what module. Use the PUBLIC directive for information you want available to make other modules and the EXTERNDEF directive IN the module that uses the external data so it can find it.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

japheth

Quote from: asmftw on August 02, 2008, 03:54:48 AM
Hey, why can't I use operands in different segments?

CODE_START is a label definsed at the beginning of .code.
dwImageSize is defined in uninitialized data.

mov edi,[esi + offset dwImageSize - offset CODE_START]

And I can't compile because of:
RelocatePointers.asm(10) : error A2025: operands must be in same segment

I don't see why masm32 can't calculate the difference between these two offsets.
Because the size of the segments is determined at link time only.
Quote
Is there any way around this?
If you're using Masm v8+, you can possibly use the IMAGEREL operator:

mov edi,[esi + IMAGEREL dwImageSize]


asmftw

Thanks for the replies guys, but I'm not sure if we are talking about the same thing.

This is basically how the code looks with all irrelevant parts removed:

.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib

.DATA?
dwOldImageBase  dd             ?
dwNewBase       dd             ?
dwImageSize     dd             ?

.code
START:
CODE_START:

  mov edi,[esi + offset dwImageSize - offset CODE_START]

CODE_END:
END START


If you try to compile that it wont work because CODE_START is in the .code segment, while dwImageSize is in the the .data section.
Nevermind the invalid pointer I'm loading. I want to load it anyways, it's not worth explaining because it's not the problem.

I don't know how to fix it with EXTERNDEF or PUBLIC, I never used those directives, could you give some advice?

japheth

Quote from: asmftw on August 02, 2008, 05:19:53 AM
I don't know how to fix it with EXTERNDEF or PUBLIC, I never used those directives, could you give some advice?
Hutch-- probably was in a hurry and just made a wild guess. Those directives cannot solve this problem.

The problem is in the way you've coded:

mov edi,[esi + offset dwImageSize - offset CODE_START]

A detailed description why this fails:

Both <offset dwImageSize> and <offset CODE_START> are relocatable labels, for which fixups (or relocations) are needed. However, due to restrictions of the object file format, it's not possible to have 2 relocations for 1 location. In the case the labels are in the very same segment, Masm can calculate the difference on its own and remove the fixups alltogether. If they are in different segments, Masm won't be able to do that.

Workarounds:
1. the IMAGEREL operator already mentioned
2. split the code:
  lea edi, [esi+offset dwImageSize]
  sub edi, offset CODE_START
  mov edi,[edi]



asmftw

Damn I was thinking it would come to this :(

I'll just stick to masm32 v9 and stick to this:
  lea edi, [esi+offset dwImageSize]
  mov edi, [edi - offset CODE_START]
Edit: ooh that didn't even work o.O I guess I have to do 3 instructions like you did lol.

Thanks for the help.

Also, if anyone knows a magical way to make it all in one instruction please post :)

hutch--

With MASM there is a right way to do things, PUBLIC and EXTERNDEF. Here is how its done.


@echo off

    if exist "start.obj" del "start.obj"
    if exist "start.exe" del "start.exe"

    \masm32\bin\ml /c /coff "start.asm"
    \masm32\bin\ml /c /coff "module.asm"
    if errorlevel 1 goto errasm

    \masm32\bin\Link /SUBSYSTEM:CONSOLE start.obj module.obj
    if errorlevel 1 goto errlink
    dir "start.*"
    goto TheEnd

  :errlink
    echo _
    echo Link error
    goto TheEnd

  :errasm
    echo _
    echo Assembly Error
    goto TheEnd

  :TheEnd

pause


The starting EXE.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    PUBLIC start            ; <<< make the label PUBLIC

    public_test PROTO

    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    print str$(OFFSET start),13,10

    call public_test

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start


The seperate module.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    EXTERNDEF start:DWORD

    .code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

public_test proc

    print str$(OFFSET start),13,10

    ret

public_test endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end


I have attached the zip of the three files.

[attachment deleted by admin]
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

tenkey

Quote from: asmftw on August 02, 2008, 05:53:46 AM
Damn I was thinking it would come to this :(

I'll just stick to masm32 v9 and stick to this:
  lea edi, [esi+offset dwImageSize]
  mov edi, [edi - offset CODE_START]
Edit: ooh that didn't even work o.O I guess I have to do 3 instructions like you did lol.

Thanks for the help.

Also, if anyone knows a magical way to make it all in one instruction please post :)
I don't recall if the OMF format allows subtraction of relocatable offsets.
If it does, you'll need an OMF linker because the MS linker will attempt to convert the OMF to COFF before linking.
Unfortunately, the COFF format does not allow any way to immediately negate or subtract relocatable offsets.
( [edi - value] is actually implemented as [edi + (- value)]. )

Otherwise, you'll need a different assembler-linker combination.
A programming language is low level when its programs require attention to the irrelevant.
Alan Perlis, Epigram #8