flat assembler
Message board for the users of flat assembler.

Index > DOS > Accessing memory at 0xF000FFFE (computer type) in fasm DOS

Author
Thread Post new topic Reply to topic
deathmood



Joined: 17 Feb 2013
Posts: 16
deathmood 17 Feb 2013, 19:35
The problem is: I need to get 'computer' type from BIOS memory. I know, that I can do it that way in fasm (my program and all segments are 16 bits):

Code:
mov al, [0xF000FFFE]     


but that returns zero and it is not right, because equivalent code in turbo c++ 3.1

Code:
UCHAR pcType = *((UCHAR*)0xF000FFFE);    


returns right 'type' of my computer, when using LARGE model (in code generation settings). So how to fix it in fasm ? (for example I know, that masm has .model directive, but there is no such thing in fasm). Please, help...
Post 17 Feb 2013, 19:35
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20430
Location: In your JS exploiting you and your system
revolution 17 Feb 2013, 19:57
You probably need to consider your segment register value. Does DS=0x0000 ?

And also for 32-bit addresses in DOS you need to be running in FRM or Unreal mode else you will get an exception generated.
Post 17 Feb 2013, 19:57
View user's profile Send private message Visit poster's website Reply with quote
deathmood



Joined: 17 Feb 2013
Posts: 16
deathmood 17 Feb 2013, 20:06
No Ds is not zero (I looked in turbo debugger). How can run unreal mode?
Post 17 Feb 2013, 20:06
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20430
Location: In your JS exploiting you and your system
revolution 17 Feb 2013, 20:09
You could also try:
Code:
mov ax,0xf000
mov ds,ax
mov al,[0xfffe]    
Post 17 Feb 2013, 20:09
View user's profile Send private message Visit poster's website Reply with quote
deathmood



Joined: 17 Feb 2013
Posts: 16
deathmood 17 Feb 2013, 20:15
Wow! That really worked for me!!! Can you post explanation? Please...
Post 17 Feb 2013, 20:15
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 17 Feb 2013, 20:53
deathmood,

Consult Intel SDM or AMD APM about real-address mode and its translation of logical addresses. Those segment*16+offset thingies.
Post 17 Feb 2013, 20:53
View user's profile Send private message Reply with quote
shutdownall



Joined: 02 Apr 2010
Posts: 517
Location: Munich
shutdownall 17 Feb 2013, 22:58
deathmood wrote:
Wow! That really worked for me!!! Can you post explanation? Please...


Under DOS you can address only 1 MByte.
It is used in 16 bit mode (use16) with segment register.

The register and corresponding segment register are simply added.

What are you looking for is address F:FFFE and not F000:FFFE.

Segment register is moved 4 bit to left and added with register.
So DS=F000 and AX=FFFE is same as
DS=FF00 and AX=FFE or
DS=FFF0 and AX=FE or
DS=FFFF and AX=E

The default segment register is DS for normal registers, SS for SP and CS for IP.

You can use other segment registers explicitly:

Code:
mov ax,0xf000
mov es,ax
mov al,es:[0xfffe]
    
Post 17 Feb 2013, 22:58
View user's profile Send private message Send e-mail Reply with quote
freecrac



Joined: 19 Oct 2011
Posts: 117
Location: Germany Hamburg
freecrac 18 Feb 2013, 08:34
shutdownall wrote:
deathmood wrote:
Wow! That really worked for me!!! Can you post explanation? Please...


Under DOS you can address only 1 MByte.
It is used in 16 bit mode (use16) with segment register.

But under a real DOS we can switch to the 16 bit PM, or to the 16 bit Unrealmode/16 bit FRM for to address up to 4GB(80386+) also using the 16 bit mode (use16).
Because the number(32 or 16 of the assembler directive of the addressmode (example "[use16]" and "[use32]") does not refers to the maximum amount of memory that the application can address!
(The maximum amount of memory that our application can be address is refering to the segment entries of the segmentsize inside of a GDT/LDT selector, or by the default size for a segment of 64 kb.)

Starting with the 80386 we can use operandsize- and addresssize- override prefixes. Those prefixes can be used in combination with the 16 bit address mode and with the 32 bit address mode.
Additional it can be used with the real addressmode and with the protected mode and the virtual 86 mode. Those prefixes reverse the default operandsize and/or the addresssize for one instruction in the codesegment.
The default operandsize and the addresssize is specified by the D flag in the code-segment descriptor(or if there is no GDT/LDT, then we become the 16 bit addressmode after the POST-process of the bios is done.)

The only one differnce between the 32 bit - and the 16 bit addressmode is the meaning and the usage of those operandsize- and addresssize prefixes.

[use16]
So if we want to use in the 16 bit addressmode 32 bit operands/addresses, then we have to add those prefixes to our opcode. Without those prefixes we can only use 16 bit.

[use32]
In the 32 bit addressmode we found a diametrical opposite situation, so if we want to use 32 bit operands/addresses, then we have to leave out those prefixes from our opcode and only if we want to use 16 operand/addresses, then we have to add those prefixes to our opcode.

Quote:
The default segment register is DS for normal registers, SS for SP and CS for IP.

The default segment register is DS for normal registers, SS for SP and for BP and CS for IP.

...

@deathmood:
For using the 16 bit Unrealmode/16 bit FRM we have to switch from the realmode to the protected mode with a GDT with an increased segmentsize of a datasegment deskriptor and with loading a data-segmentregister with the selector of this deskriptor and then switching back to the realmode. While we are in the PM without to have an interrupt vector table(IVT), we have to stop interrupts before we are switching to the PM. After we are back in the RM we can enable the interrupts again. At last we have to open the 20. addressline.
Code:
       NMI_Port = 70h

START:    ; mainroutine

          cli
          in       al, NMI_Port  ; stop NMIs
          or       al, 80h
          out      NMI_Port, al
          in       al, 71h 

          call ESEG                     ; switch to the 16 bit Unrealmode/16 bit FRM

          in       al, NMI_Port         ; enable NMIs
          and      al, 7Fh
          out      NMI_Port, al
          in       al, 71h 
          sti

; --------------- GDT and sub-routines----------------

;----------------------------------------------------------------------------
;                     GDT for the Protected Mode
;----------------------------------------------------------------------------
 org START + ((($-START)/64)*64)+64     ; Code-alignment
;----------------------------------------------------------------------------
GDTZEIGER DW ?      ; Length of the GDT
          DW ?      ; Address low -Word:SEGMENTE
          DW ?      ; Address high-Word:SEGMENTE
          DW 0      ; reserved

SEGMENTE  DW 0      ; Bits: 0-15 Seg.length(Bit0-15)
          DW 0      ; Bits: 0-15 Basis-Address Deskriptor-Table
          DB 0      ; Bits:16-23 Basis-Address Deskriptor-Table
          DB 0      ; Bits: 0- 7 Access Rigths
          DB 0      ; Bits: 0- 3 Seg.length(Bit16-19)/Bit7:1=4KByte/0=1Byte
          DB 0      ; Bits:24-31 Basis-Address Deskriptor-Table

;-------------------------------------------- Selektor    Segmente
       DW 0FFFFh ; Segment length  Bits: 0-15         
       DW 0      ; Address low    Bits: 0-15   08h  Code (CS)
       DB 0      ; Address high   Bits:16-23
       DB 9Ah    ; Access Rights
       DB 0      ; Seg.length Bits:16-19 im Bit0-3 /Bit7:1=4KByte/0=1Byte
       DB 0      ; Seg.Address    Bits:24-31
;--------------------------------------------------- Selektor    Segmente
       DW 0FFFFh ; Segment length  Bits: 0-15         
       DW 0      ; Address low    Bits: 0-15  10h  Stack (SS)
       DB 0      ; Address high   Bits:16-23  
       DB 92h    ; Access Rights
       DB 0      ; Seg. length Bits:16-19 im Bit0-3 /Bit7:1=4KByte/0=1Byte
       DB 0      ; Seg.Address    Bits:24-31
;--------------------------------------------------- Selektor    Segmente
       DW 0FFFFh ; Segment length   Bits: 0-15
       DW 0      ; Seg.Address    Bits: 0-15  18h (DS,ES,FS,GS)
       DB 0      ; Seg.Address    Bits:16-23  
       DB 92h    ; Access Rights
       DB 0FFh   ; Seg. length Bits:16-19 im Bit0-3//Bit7:1=4KByte/0=1Byte
       DB 0FFh   ; Seg.Address    Bits:24-31
;---------------------------------------------------
        SEGMENTE_END label WORD
        Gdt_Groesse equ (OFFSET SEGMENTE_END - SEGMENTE -1)
;---------------------------------------------------
 org START + ((($-START)/32)*32)+32              ; Code-Alignment
;----------------------------------------------------------------------------
ESEG:     xor      eax, eax
          mov      ax, cs
          mov      ds, ax
          shl      eax, 4                        ; EAX = physical-
          mov      ebx, eax                      ; Segmentstartaddress
          mov     WORD PTR[SEGMENTE+0Ah], ax     ; in the deskriptor
          mov     WORD PTR[SEGMENTE+12h], ax     ; for CS
          ror      eax, 10h                      ; and SS saved into the
          mov     BYTE PTR[SEGMENTE+0Ch], al     ; GDT
          mov     BYTE PTR[SEGMENTE+14h], al
          xor      eax, eax                      ; EAX = null
          mov      ax, OFFSET SEGMENTE           ; 16-Bit-Offset
          add      ebx, eax                      ; GDT-Address in the
          mov     WORD PTR[GDTZEIGER], Gdt_Groesse ; GDT-Deskriptor
          mov     DWORD PTR[GDTZEIGER+2], ebx

          pushf                                  ; save Flags
          lgdt    FWORD PTR[GDTZEIGER]           ; load GDT
          mov      dx, ss                        ; save SS
          mov      eax, cr0                      ;
          or       al, 1                         ; switch to the Protected Mode
          mov      cr0, eax                      ;
                                                 ; clear Prefetch-Buffer
          DB  0EAh
          DW  (OFFSET PMODE)
          DW  8                                  ; JMP FAR CS:PMODE
;------------------------------------------------
 org START + ((($-START)/32)*32)+32              ; Code-Alignment
;------------------------------------------------
PMODE:    mov      ax, 10h                       ; SS-Selektor
          mov      ss, ax                        ; 64 KByte
          mov      ax, 18h
          mov      ds, ax                        ; DS,ES,FS,GS-Selektor
;          mov      es, ax
;          mov      fs, ax
;          mov      gs, ax

          mov      eax, cr0                ; switch back to the realmode
          and      eax, not 1
          mov      cr0, eax
                                                 ; clear Prefetch-Buffer
          DB  0EAh
          DW  (OFFSET RMODE)
AKTSEG    DW  (SEG RMODE)                        ; JMP FAR CS:RMODE
;------------------------------------------------
 org START + ((($-START)/32)*32)+32
;------------------------------------------------
RMODE:    mov      ss, dx                        ; load SS
          popf                                   ; load Flags
;----------------------------------------------------------------------------
;           switch the 20. adressline on
;----------------------------------------------------------------------------
BIT_FREI: call W_8042        ;  Wait for the 8042
          jnz BACK
          mov      al, 0D1h  ; write command
          out      64h, al
          call W_8042        ;  ready to recieve data
          jnz BACK
          mov      al, 0DFh  ; yes, enable the 20 addressline
          out      60h, al
;------------------------------------------------------------
;           Wait for the 8042
;------------------------------------------------------------
W_8042:   xor      cx, cx    ; CX=0
STATUS:   in       al, 64h   ; read Status
          and      al, 2     ; Buffer full?
          loopnz STATUS      ;  loop til no or Timeout
BACK:     ret
    

Dirk
Post 18 Feb 2013, 08:34
View user's profile Send private message Send e-mail Reply with quote
shutdownall



Joined: 02 Apr 2010
Posts: 517
Location: Munich
shutdownall 18 Feb 2013, 18:33
I think then in 32 bit (unreal mode) you have to read with

Code:
mov al, [0x000FFFFE] 
- instead of -
mov al, [0xF000FFFE] 
    
Post 18 Feb 2013, 18:33
View user's profile Send private message Send e-mail Reply with quote
deathmood



Joined: 17 Feb 2013
Posts: 16
deathmood 19 Feb 2013, 18:12
I have one more question: can I use unreal mode with .com files?
Post 19 Feb 2013, 18:12
View user's profile Send private message Reply with quote
ACP



Joined: 23 Sep 2006
Posts: 204
ACP 19 Feb 2013, 22:28
deathmood wrote:
I have one more question: can I use unreal mode with .com files?


Yes you can. Unreal mode is a "state of segment registers" and limits so basically any DOS structure including PSP and MZ exe header have no direct impact on it whatsoever. The only drawback in case of COM files is that internally DOS loader can not handle files larger than 64kb all together and EXE files can have separate multiple segments for code and data.
Post 19 Feb 2013, 22:28
View user's profile Send private message Reply with quote
deathmood



Joined: 17 Feb 2013
Posts: 16
deathmood 20 Feb 2013, 06:57
Ok! Thanks all)))
Post 20 Feb 2013, 06:57
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.