64 bit assembler > UASM Assembler Development

jwasm 2.10 vs jwasm 2.11 ~ uasm 2.38 problem

(1/2) > >>


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.

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:

--- Code: ---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] 

--- End code ---

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

--- End code ---
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

--- End quote ---
UASM supports RIP relative encoding

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.
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.
Relative Displacement Directives
RELB fparam
RELW fparam
RELD fparam
fparam is the name of a formal parameter with a C (code) specifier letter.
The relative displacement directives instruct the assembler to generate the
displacement between the end of an instruction and a label expression operand as

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

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?

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

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.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 */

=> from v2.10
            /* 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 */


[0] Message Index

[#] Next page

Go to full version