flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > 16 bit operand in LGDT

Author
Thread Post new topic Reply to topic
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 20 Oct 2023, 04:48
LGDT can load just 24 bits of the base instead of 32 (32 bit mode) or 64 (64 bit mode) if you specify the operand as 16 bit, but I don't know how to do it in fasm.
If I put "word" before the memory operand, I get an error.
Post 20 Oct 2023, 04:48
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20060
Location: In your JS exploiting you and your system
revolution 20 Oct 2023, 04:58
Where are you putting "word"? There are two places it can go. The data size and/or the address size.
Code:
lgdt word[word 0x0000]    
Note that sizes dword, fword and pword also exist.
Post 20 Oct 2023, 04:58
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 20 Oct 2023, 05:21
I put it as "data" ("operand", to use the intel nomenclature) size, before the square bracket:
lgdt word [addr]
It works fine without "word"; with it, I cannot make it work neither in 32 bit mode nor 64 bit mode
Post 20 Oct 2023, 05:21
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20060
Location: In your JS exploiting you and your system
revolution 20 Oct 2023, 05:46
There is no word length gdt entry. IIRC it has to be at least 48-bits 16:32 (pword).
Post 20 Oct 2023, 05:46
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8340
Location: Kraków, Poland
Tomasz Grysztar 20 Oct 2023, 05:52
You can force the 32-bit version by specifying 6-byte operand with PWORD operator, but fasm 1 has no similar keyword for 5-byte operand to enforce 16-bit version. It is easier with fasmg/fasm2 where sizes can be defined more freely:
Code:
lgdt [data5] ; 16-bit version
lgdt [data6] ; 32-bit version

label data5: 5 ; assembles with fasmg / fasm 2 only
data6 dp ?    
PS. Digging deeper, you could even define an additional operator:
Code:
define x86.wpword? :5 ; affects x86-2.inc module of fasm 2

lgdt wpword [0]
lgdt pword [0]    
Post 20 Oct 2023, 05:52
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20060
Location: In your JS exploiting you and your system
revolution 20 Oct 2023, 06:40
I think the operand is never 5 bytes. It always reads 6 bytes and ignores the top 8 bits and internally replaces them with zeros.

That could be tested by placing the address at (top_of_segment - 5) and see if it tries to read the wraparound byte at address 0.
Post 20 Oct 2023, 06:40
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8340
Location: Kraków, Poland
Tomasz Grysztar 20 Oct 2023, 07:42
Yes, the definition of what constitutes the "operand" here is disputable, I made a compromise, but the size is the only way to attempt distinguishing these forms in fasm's syntax.

With x86-2 we could alternatively invent some new instruction decorators, but this is not just a choice of a different encoding, it is a change in what the instruction does, and for that I preferred to have a distinguished base syntax.
Post 20 Oct 2023, 07:42
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 20 Oct 2023, 13:03
Yes revolution, with 16 bit operand size I meant "read 6 bytes and use only 5".
I tried the "pword" operand size in 64bit and I get "illegal instruction" in fasm 1.

So there is no way to change the operand size? It only depends on the current processor mode?
Post 20 Oct 2023, 13:03
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8340
Location: Kraków, Poland
Tomasz Grysztar 20 Oct 2023, 13:12
pfranz wrote:
So there is no way to change the operand size? It only depends on the current processor mode?
Yes, see the reference:
Intel® 64 and IA-32 Architectures Software Developer’s Manual wrote:
In 64-bit mode, the instruction’s operand size is fixed at 8+2 bytes (an 8-byte base and a 2-byte limit).
Post 20 Oct 2023, 13:12
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20060
Location: In your JS exploiting you and your system
revolution 20 Oct 2023, 16:17
So to summarise:
Code:
use16
lgdt [si]               ; 0F0114        16 + 24
lgdt pword[si]          ; 660F0114      16 + 32

use32
db 0x66
lgdt [esi]              ; 660F0116      16 + 24
lgdt pword[esi]         ; 0F0116        16 + 32

use64
lgdt tword[rsi]         ; 0F0116        16 + 64    
The only unreachable encoding is for 32 bit mode to create 16+24. There needs to be a manual prefix.

Using a macro:
Code:
macro lgdt24 address {
        local mode
        virtual at 0
                inc ax
                mode = 8 shl $
        end virtual
        if mode = 16
                lgdt address
        else if mode = 32
                db 0x66
                lgdt address
        else if mode = 64
                err "16+24 lgdt not available in 64 bit mode"
        end if
}

use16
lgdt24 [si]
lgdt24 [esi]
use32
lgdt24 [si]
lgdt24 [esi]
use64
lgdt24 [rsi]    ; err    
Post 20 Oct 2023, 16:17
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20060
Location: In your JS exploiting you and your system
revolution 21 Oct 2023, 05:11
The original 80286 manual says that the CPU loads 6 bytes. And further that the last byte must be zero. So it appears that with the 16-bit encoding only the later CPUs have dropped the requirement for the zero and instead ignore the final byte.


Description:
Filesize: 65.61 KB
Viewed: 1467 Time(s)

80286-LGDT.png


Post 21 Oct 2023, 05:11
View user's profile Send private message Visit poster's website Reply with quote
pfranz



Joined: 13 Jan 2007
Posts: 116
Location: Italy
pfranz 22 Oct 2023, 02:31
Thanks for the research. Probably 80286 wanted to be upward compatible with possible future use of 32bit base (which actually happened), and then 80386+ wanted to be backward compatible with misbehaved software that wouldn't bother to clear reserved bits.
By the way, I tried 66 prefix in 64bit mode: it works but does nothing. lgdt still reads and uses 10 bytes.
Post 22 Oct 2023, 02:31
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.