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.
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.
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]
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?
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]
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 :)
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]
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.