News:

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

Main Menu

jwasm 2.10 vs jwasm 2.11 ~ uasm 2.38 problem

Started by fonolite, September 02, 2017, 06:10:37 PM

Previous topic - Next topic

fonolite

Hello~

I have some problems in between jwasm 2.10 and jwasm 2.11 ~ uasm 2.38.
Here is my code.

mov edi, fs:[var]   ; inside USE64 64bit segment  (long mode) & omf object.
[var] = static varable in data segment
assume DS:FLAT , FS:_DATA , bla bla bla

No.1) jwasm 2.10 : mov edi, fs:[var] => mov edi, fs:[var]

No.2) jwasm 2.11 ~ uasm 2.38 : mov edi, fs:[var] => mov edi, fs:[var+eip]  (showed in runtime debugger like bochs)

You know fs & gs are used for relative offset like 16bit or 32bit segment.

I want to continue to use the No.1 way with uasm 2.38 for new cpu instructions.

Please help me for solving this problems.

habran

There is no difference between ml.exe and uasm.exe, they produce the same code but they break because system uses GS and FS for its purpose, here are code:
ml.exe:

009A1067 64 8B 3D 00 50 9A 00 mov         edi,dword ptr fs:[9A5000h] 
    57:     mov eax, [edi]
009A106E 8B 07                mov         eax,dword ptr [edi] 

UASM:

    56:     mov edi, [fs:var]
01331057 64 8B 3D 00 50 33 01 mov         edi,dword ptr fs:[1335000h] 
    57:     mov eax, [edi]

in 32 bit you can still access data with LEA EDI and then use MOV EAX[EDI]
however, in 64 bit FS contents is garbage and brakes the code

this is from intel Introduction to x64 Assembly.pdf
Quote Indirect: this allows using an 8, 16, or 32 bit displacement, any general purpose registers for base and index, and a scale of 1, 2, 4, or 8 to multiply the index. Technically, these can also be prefixed with segment FS: or GS: but this is rarely required.
MOV R8W, 1234[8*RAX+RCX] ; move word at address 8*RAX+RCX+1234 into R8W There are many legal ways to write this. The following are equivalent
MOV ECX, dword ptr table[RBX][RDI]
MOV ECX, dword ptr table[RDI][RBX]
MOV ECX, dword ptr table[RBX+RDI]
MOV ECX, dword ptr [table+RBX+RDI]
The dword ptr tells the assembler how to encode the MOV instruction.
 RIP-relative addressing: this is new for x64 and allows accessing data tables and such in the code
relative to the current instruction pointer, making position independent code easier to implement.
MOV AL, [RIP] ; RIP points to the next instruction aka NOP NOP
Unfortunately, MASM does not allow this form of opcode, but other assemblers like
UASM supports RIP relative encoding

Cod-Father

fonolite

First of all, thanks for your kind answer.

I googled rip-relative addressing these days.

1) I found yasm (maybe nasm has the same grammers.) has rel & abs specifiers for symbols.
https://www.tortall.net/projects/yasm/manual/html/nasm-effaddr.html
http://www.nasm.us/doc/nasmdoc6.html#section-6.2.1
3.3.2. RIP Relative Addressing
mov [rel sym], rax  ; RIP-relative
mov [abs sym], rax  ; not RIP-relative
mov [fs:sym], rbx   ; not RIP-relative (fs or gs use)
I think the 3rd ([fs:sym]) means exactly what I want for the special purpose of FS & GS 's segment relative offset in 64bit segments.

2) Intel ASM386 has the similar directives.
https://archive.org/stream/bitsavers_inteliRMXi9165003ASM386AssemblyLanguageReference19_1663542/469165-003_ASM386_Assembly_Language_Reference_1995_djvu.txt
Relative Displacement Directives
Syntax
RELB fparam
RELW fparam
or
RELD fparam
Where:
fparam is the name of a formal parameter with a C (code) specifier letter.
Discussion
The relative displacement directives instruct the assembler to generate the
displacement between the end of an instruction and a label expression operand as
follows:



Does uasm/jwasm/wasm have the similar expression for the specific absolute addressing only for FS & GS segments?

johnsa

#3
We don't have any rel/abs type addressing modifiers at present, something I've been thinking about.
Immediately however as a fix for 2.42 I would suggest that NO fs/gs reference should ever be rip relative.
If everyone is ok with that that should be easy to do.

Edit: Possibly ANY segment override should force this behaviour?

so
mov eax,[rdi]   ; this would allow RIP relative and be rip relative where possible
mov eax,seg:[rdi]   ; non-RIP


fonolite

#4
Thanks, johnsa

I analyzed the full sources of uasm and debugged them with visual studio.
And I found the changing point of parser.c about fs segment between jwasm v2.10 and v2.11.

I built the v2.40 newest uasm's modified sources with visual studio and it makes fs:[var] have no rip-relative offset.
So I'll use this program temporarily.

If uasm v2.42+ will have no rip-relative offset with segment override only for FS & GS segments, I'll appreciate that.


4) parser.c
v2.11+
#if AMD64_SUPPORT
            /* v2.03: the non-RIP encoding for 64bit uses a redundant SIB mode (base=none, index=none) */
            /* v2.11: always use 64-bit non-RIP addressing if no fixup has been created. */
            //if ( CodeInfo->Ofssize == USE64 && CodeInfo->prefix.RegOverride != EMPTY && SegOverride != &ModuleInfo.flat_grp->sym ) {
            if ( CodeInfo->Ofssize == USE64 && CodeInfo->opnd[CurrOpnd].InsFixup == NULL ) {
                DebugMsg1(( "set_rm_sib: 64-bit, no fixup, data64=%" I64_SPEC "X\n", CodeInfo->opnd[CurrOpnd].data64 ));
                rm_field = RM_SIB;
                CodeInfo->sib = 0x25; /* IIIBBB, base=101b, index=100b */
            }
#endif

=> from v2.10
#if AMD64_SUPPORT
            /* v2.03: the non-RIP encoding for 64bit uses a redundant SIB
             * mode (base=none, index=none) */
            if ( CodeInfo->Ofssize == USE64 &&
                CodeInfo->prefix.RegOverride != EMPTY &&
                SegOverride != &ModuleInfo.flat_grp->sym ) {
                DebugMsg1(( "set_rm_sib: 64-bit non-RIP direct addressing: SegOverride=%X, flat=%X\n", SegOverride, ModuleInfo.flat_grp ));
                rm_field = RM_SIB;
                CodeInfo->sib = 0x25; /* IIIBBB, base=101b, index=100b */
            }
#endif

johnsa

It will be so in 2.42 coming soon to a store near you :)

fonolite

My sources including fs:[var] work fine with uasm 2.42 now.

Thank you so much johnsa.

nidud

#7
deleted

habran

Hi nidud, that is nice solution :t
Now this is what we get with UASM:

   219: assume cs:flat,ds:flat,ss:flat,es:flat,fs:_DATA,gs:nothing
   220: lea rcx,gs:[1234h]
00007ff7353910e5 48 8D 0C 25 34 12 00 00          lea rcx, ptr [0x1234] 
   221: lea rax,var
00007ff7353910ed 48 8D 05 40 3F 00 00             lea rax, ptr [rip+0x3f40] 
   222: lea rdx,fs:[var]
00007ff7353910f4 48 8D 15 39 3F 00 00             lea rdx, ptr [rip+0x3f39] 
   223: lea eax,var
00007ff7353910fb 8D 05 33 3F 00 00                lea eax, ptr [rip+0x3f33] 
   224: lea edx,fs:[var]
00007ff735391101 8D 15 2D 3F 00 00                lea edx, ptr [rip+0x3f2d] 
   225: mov edi,fs:[var]
00007ff735391107 64 8B 3D 26 3F 00 00             mov edi, dword ptr fs:[rip+0x3f26] 

Cod-Father


johnsa

In addition to the changes that have been made, this is pulled from the original jwasm manual FYI:

In 64-bit a RIP-relative addressing mode was introduced. This mode is used as default for direct addressing, because it allows to access all code or data labels with a 32-bit displacement. However, for constant address locations this mode is not appropriate and won't be used:


     mov al, gs:[1000h]
     mov al, gs:[100000000h]

If a constant address is to be accessed without segment prefixes - note that in 64-bit, only segment registers FS and GS can be used as segment prefixes - one has to use the FLAT keyword in JWasm:



     mov al, FLAT:[1000h]           ;invalid for Masm
     mov al, FLAT:[100000000h]      ;invalid for Masm