The MASM Forum Archive 2004 to 2012

Miscellaneous Forums => 16 bit DOS Programming => Topic started by: zak100 on February 19, 2010, 06:21:07 PM

Title: Memory Map
Post by: zak100 on February 19, 2010, 06:21:07 PM
Hi,
I have got a code related to memory map. I have not understood everything of this code. But thing which hindering me is that its using 32 bit registers. Should I have to switch to protected mode?


; use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
; inputs: es:di -> destination buffer for 24 byte entries
; outputs: bp = entry count, trashes all registers except esi
do_e820:
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx, 0x0534D4150 ; Place "SMAP" into edx
mov eax, 0xe820
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes
int 0x15
jc short .failed ; carry set on first call means "unsupported function"
mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short .failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short .failed
jmp short .jmpin
.e820lp:
mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes again
int 0x15
jc short .e820f ; carry set means "end of list already reached"
mov edx, 0x0534D4150 ; repair potentially trashed register
.jmpin:
jcxz .skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short .notext
test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
je short .skipent
.notext:
mov ecx, [es:di + 8] ; get lower dword of memory region length
test ecx, ecx ; is the qword == 0?
jne short .goodent
mov ecx, [es:di + 12] ; get upper dword of memory region length
jecxz .skipent ; if length qword is 0, skip entry
.goodent:
inc bp ; got a good entry: ++count, move to next storage spot
add di, 24
.skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
jne short .e820lp
.e820f:
mov [mmap_ent], bp ; store the entry count
ret ; test opcode cleared carry flag
.failed:
stc ; "function unsupported" error exit
ret






Zulfi.
Title: Re: Memory Map
Post by: dedndave on February 19, 2010, 08:33:46 PM
no - in fact, i don't think it will work in protected mode
from what i understand, to use 32-bit registers in real mode, all you should need is....

        .386

(or higher) after the model directive
Title: Re: Memory Map
Post by: redskull on February 19, 2010, 09:45:00 PM
Remember that when running anything this low-level within a DOS Box under Windows NT, always take the output with a grain of salt.  I'm fairly certain NTVDM doesn't support this particular INT 15 call, so ensure you run this in 'real' real mode

-r
Title: Re: Memory Map
Post by: FORTRANS on February 19, 2010, 09:53:36 PM
Hi,

   As Dave says you can use 32 bit instructions in real mode.
You have to make sure that the assembler knows to be in 16-bit
mode or the default instruction mode will be incorrect.  I Think
Dave and MichaelW have posted posted code that shows how
to do this.

   When you are in protected mode interrupts work differently
than when in real mode.  If that has not been set up correctly,
it will not work.  Also BIOS code is 16-bit and a lot of examples
of setting up protected mode also set up the 32-bit execution
mode.

Regards,

Steve N.
Title: Re: Memory Map
Post by: dedndave on February 19, 2010, 10:17:09 PM
i think he is reading Ralf
if i recall, it was E820h where Ralf said some BIOS's expect the high word of eax to be 0
Title: Re: Memory Map
Post by: zak100 on February 20, 2010, 06:32:32 PM
Hi,
I got it from OSDev Wiki & topic is "Detecting Memory (x86)". There is no author name.

mov [mmap_ent], bp   ; store the entry count


Should I declare the mmap_ent as:

mmap_ent db  0

How can I use it for indirect addressing ?

Zulfi.


Title: Re: Memory Map
Post by: dedndave on February 20, 2010, 06:53:44 PM
those guys over there use NASM, mostly
for MASM, you can use

        mov     mmap_ent,bp   ; store the entry count

but, BP is a word register, so mmap_ent should be a word

mmap_ent dw ?
Title: Re: Memory Map
Post by: zak100 on February 21, 2010, 03:38:46 PM
Thanks for removing this confusion. I really appreciate your replies. Its very good forum. Replies come immediately.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on February 21, 2010, 06:14:53 PM
Hi,
Can somebody plz guide me with this statement:

mov [es:di + 20], dword 1


I am getting following error:
sect8_2.asm(277) : error A2032: invalid use of register

Zulfi.
Title: Re: Memory Map
Post by: dedndave on February 21, 2010, 07:54:38 PM
try this

        mov dword ptr es:[di+20],1

not sure if that will work in 16-bit mode - if not, you'll have to split it up

        mov word ptr es:[di+20],1
        mov word ptr es:[di+22],0
Title: Re: Memory Map
Post by: zak100 on February 24, 2010, 06:28:48 PM
Hi,

Thanks. In this code they have not specified the declaration for the buffer of the list pointed by ES:DI. Should I declare it as:

buffer db ?

and then point ES:DI towards it using following code:

       
push es
        push cs
        pop es
        mov di, offset buffer+LoadOfs

     



What is the function of bp?



xor bp, bp ; keep an entry count in bp




I cant understand this entry count?

I want to first print this qword Base address. The loop counter should be set to 64??

Kindly somebody guide me with this.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on February 24, 2010, 08:46:43 PM
Hi,

Quote
What is the function of bp?

Code:

xor bp, bp ; keep an entry count in bp

I cant understand this entry count?

   A call to Int 15H Fn E820 returns information about a memory
block.  You supply a buffer for the BIOS to fill with this information.
This code snippet calls this an "entry".  BP is a count of the memory
blocks in that computer.  You call the BIOS Int 15H more than once
to get a map of the memory.

Regards,

Steve
Title: Re: Memory Map
Post by: dedndave on February 24, 2010, 10:52:38 PM
the buffer needs to be large enough to hold all the entries
the problem is, you do not know how many entries there will be on any given computer - lol
but, you are in luck   :bg
you are only interested in the last entry
if i remember, it is 20 bytes per entry
just use the same 20 bytes over and over
when the function tells you there are no more entries, you will have the one you want in the buffer
Title: Re: Memory Map
Post by: zak100 on February 25, 2010, 06:05:07 AM
Hi,

Thanks for the reply.

Quote

BP is a count of the memory
blocks in that computer.

But these blocks can be of different sizes (qword or dword) and some of them can be filled and some are unused???

Should I declare the buffer as 'qword'? I want to do it in steps. First I want to print the Base address which is of 'qword' size.

Zulfi.
Title: Re: Memory Map
Post by: dedndave on February 25, 2010, 11:10:26 AM
you could define a structure
have a look at Steve's memory map code to see how it is done (i think he did it that way   :P )

something like this...

MMap_Descriptor STRUCT
  BaseAddress_Lo dd ?
  BaseAddress_Hi dd ?
  ByteLength_Lo  dd ?
  ByteLength_Hi  dd ?
  RangeType      dd ?
MMap_Descriptor ENDS

now, MMap_Descriptor is a new data type

MMap_Table MMAP_Descriptor <>

now, you have a structure named MMap_Table of the type MMap_Descriptor
you can access one of the elements like this

        mov     eax,MMap_Table.ByteLength_Lo
Title: Re: Memory Map
Post by: zak100 on February 26, 2010, 06:05:11 PM
Thanks. I never worked on structures in Assembly language but your example shows that its not difficult.
I cant understand following fields:

ByteLength_Lo  dd ?
  ByteLength_Hi  dd ?
  RangeType      dd ?


BaseAddress is clear to me.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on February 26, 2010, 06:23:57 PM
Hi,

According to that Article :
Quoteincrement DI by your list entry size:
       
The structure which you told me is of 80 bytes. Should I increase DI by 80 bytes for next call?

Should I have one more dd field in the structure for ACPI 3.0 Extended Attributes bitfield??


From this structure it seems that each time I invoke int 15h I would get a base address of a region.

Kindly somebody guide me with this.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on February 26, 2010, 08:34:34 PM
Hi,

QuoteI cant understand following fields:

ByteLength_Lo  dd ?


MMap_Descriptor STRUCT
  BaseAddress_Lo dd ?
  BaseAddress_Hi dd ?
  ByteLength_Lo  dd ?
  ByteLength_Hi  dd ?
  RangeType      dd ?
MMap_Descriptor ENDS


   This corresponds to the description in the article.

Quote
   * First qword = Base address
   * Second qword = Length of "region" (if this value is 0, ignore the entry)
   * Next dword = Region "type"
         o Type 1: Usable (normal) RAM
         o Type 2: Reserved - unusable
         o Type 3: ACPI reclaimable memory
         o Type 4: ACPI NVS memory
         o Type 5: Area containing bad memory
   * Next dword = ACPI 3.0 Extended Attributes bitfield (if 24 bytes are
           returned, instead of 20)

   So if I rearrange things a bit, it becomes:


MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DD      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DD      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS


   (I added a record for the attributes like you mentioned.)
So Dave showed you the structure using DWORD sized fields,
which is a bit easier when programming 32-bit code.

Quote
The structure which you told me is of 80 bytes. Should I increase DI by 80 bytes for next call?

   Actually what Dave showed you was 20 bytes, five
DWORDS.  The one I just showed was 24 bytes.  So
you would declare multiple structures and increment for
each new call, or reuse the first one each time.


Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


HTH,

Steve N.
Title: Re: Memory Map
Post by: zak100 on February 27, 2010, 07:35:35 AM
Thanks. Very good explanations by you people. Will these five variables be enough to check the entire memory or I may need more?

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on February 27, 2010, 02:17:33 PM
Hi,

   Different computers will have different numbers of blocks.
In the other thread with MichaelW's software, the examples
posted showed two with six blocks and one with four.  And
there should be another to show the end block.   Five was
just an example showing the allocation of structures.  They
are not all that big, so starting with ten or sixteen won't hurt
much.  MichaelW seems to reuse just one in a loop.  (If I
read his program correctly.)

Regards,

Steve
Title: Re: Memory Map
Post by: zak100 on March 02, 2010, 05:04:48 AM
Very Good. I must do some programming now. And inform you people about the results.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on March 03, 2010, 02:45:30 PM
Hi,
I want to print this base address once its stored in the structure i.e I want to print the following field:

BaseAddress   DQ      ?


Can somebody guide me in this regard?

Zulfi.
Title: Re: Memory Map
Post by: zak100 on March 04, 2010, 06:37:00 PM
Hi,
I am putting my code for memory map but still I dont have any clue to display the base address:


do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes
int 15h
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
jmp short jmpin
jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
je short skipent

skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
jne short e820f
        mov ah,0
        mov end_of_list, ah
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
ret
failed:
stc ; "function unsupported" error exit
ret





displayBaseAddress:
                   
                    ret

Can somebody help me with displaying the base address??

Zulfi.


Title: Re: Memory Map
Post by: dedndave on March 04, 2010, 08:59:54 PM
Zulfi
this routine will convert it to a zero-terminated ASCII string
use the display routine we have used before to display it

;-----------------------------------------------------------------------

Qw2Hex  PROC    NEAR

;convert a QWORD from a memory location to ASCIIZ hexidecimal string

;Call With: DS:SI = address of binary QWORD input value
;           DS:DI = address of 17-byte ASCII buffer

        push    ax
        push    cx
        push    si
        push    di
        mov     cx,8
        add     si,7

Qw2Hx0: mov     al,[si]
        dec     si
        mov     ah,al
        shr     al,1
        shr     al,1
        shr     al,1
        shr     al,1
        cmp     al,0Ah
        sbb     al,69h
        das
        mov     [di],al
        inc     di
        mov     al,ah
        and     al,0Fh
        cmp     al,0Ah
        sbb     al,69h
        das
        mov     [di],al
        inc     di
        dec     cx
        jnz     Qw2Hx0

        mov     [di],cl
        pop     di
        pop     si
        pop     cx
        pop     ax
        ret

Qw2Hex  ENDP

;-----------------------------------------------------------------------

EDIT - fixed a typo

        jnz     Qw2Hx0
Title: Re: Memory Map
Post by: zak100 on March 05, 2010, 02:39:06 PM
Thanks . I would try this.

Zulfi.
Title: Re: Memory Map
Post by: dedndave on March 05, 2010, 02:59:35 PM
this version is probably better, Zulfi
it can be used for smaller integers, as well
you have to tell it how many binary bytes to convert in CX

        mov     si,offset BinaryValue
        mov     di,offset AsciiBuffer
        mov     cx,sizeof BinaryValue
        call    MB2Hex


;-------------------------------------------------------------------------------

MB2Hex  PROC    NEAR

;convert a multi-byte binary from a memory location to ASCIIZ hexidecimal string

;Call With: DS:SI = address of binary input value
;           DS:DI = address of ASCII buffer (minimum length = 2 x CX + 1)
;              CX = number of binary input bytes to convert

        push    ax
        push    cx
        push    di
        add     si,cx

MB2Hx0: dec     si
        mov     al,[si]
        mov     ah,al
        shr     al,1
        shr     al,1
        shr     al,1
        shr     al,1
        cmp     al,0Ah
        sbb     al,69h
        das
        mov     [di],al
        inc     di
        mov     al,ah
        and     al,0Fh
        cmp     al,0Ah
        sbb     al,69h
        das
        mov     [di],al
        inc     di
        dec     cx
        jnz     MB2Hx0

        mov     [di],cl
        pop     di
        pop     cx
        pop     ax
        ret

MB2Hex  ENDP

;-------------------------------------------------------------------------------
Title: Re: Memory Map
Post by: FORTRANS on March 05, 2010, 04:59:21 PM
Hi,

   Cough.  Dave beat me to it.  Twice.  Oh well, here is my
version anyway.  Why waste typing effort?

Regards,

Steve


; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    Call with DS:SI pointing to a QWORD (eight bytes) to be
; displayed as hexadecimal.
QW2Hex$:
        PUSH    SI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX

        STD             ; String instructions decrement.

        ADD     SI,7    ; Point to last byte, (Intel big end).
        MOV     CX,8    ; Number of bytes to print.
QW_1:
        LODSB           ; Get a byte.
        CALL TOASCII    ; Display as hex.
        LOOP    QW_1

        CLD             ; Restore default.

        POP     CX
        POP     AX
        POP     SI

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Title: Re: Memory Map
Post by: zak100 on March 06, 2010, 04:33:53 AM
Hi,

Fine. I actually tried Dave's work last night but it didnt work. I would try your's now.Its very good to get these 2 different versions. I would try to understand them as its difficult to understand Assembly programs without the help of an alg.


Zulfi.
Title: Re: Memory Map
Post by: dedndave on March 06, 2010, 05:51:12 AM
the first one had a typo in it, Zulfi - i fixed it
here is a little demo program using the multi-byte version...
Title: Re: Memory Map
Post by: zak100 on March 08, 2010, 06:49:30 PM
Hi Steve,

Quote

Call with DS:SI pointing to a QWORD (eight bytes) to be
; displayed as hexadecimal.



Thanks for your code. I have one prob. which is stated in the comment. In my code, ES:DI points to the QWORD which is natural after executing 15h. This comment means I cant use your code.

Hi Dave,
Thanks for your help. I was able to compile your program. I would check your updated version some time maybe tomorrow.

I appreciate your consistent help in solving my problems.

Zulfi.
Title: Re: Memory Map
Post by: dedndave on March 08, 2010, 07:42:37 PM
it's kind of fun Zulfi
i get to keep my hand in 16-bit code so i don't forget it all - lol
but, you should try to understand the code we provide - learn from it
it would be great to see you post good code you have written yourself  :bg
Title: Re: Memory Map
Post by: FORTRANS on March 08, 2010, 10:21:14 PM
Quote from: zak100 on March 08, 2010, 06:49:30 PM

quote

Call with DS:SI pointing to a QWORD (eight bytes) to be
; displayed as hexadecimal.
/quote

Thanks for your code. I have one prob. which is stated in the comment. In my code, ES:DI points to the QWORD which is natural after executing 15h. This comment means I cant use your code.

Hi Zulfi,

   Try changing:


        LODSB           ; Get a byte.


   To something like:


        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI


   And PUSH/POP DI instead of SI.  That _should_ work.
It is handy to use LODSB, which defaults to DS:SI.


Regards,

Steve
Title: Re: Memory Map
Post by: dedndave on March 09, 2010, 12:28:49 AM
you could also fix it by moving segment values around in the segment registers by using push and pop
Title: Re: Memory Map
Post by: zak100 on March 09, 2010, 06:16:37 PM
Hi,
I would try. Thanks for guidance and encouragement.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on March 09, 2010, 06:32:15 PM
Hi,
What is the purpose of this DB?



DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.





Zulfi.
Title: Re: Memory Map
Post by: dedndave on March 09, 2010, 07:34:02 PM
0D4h,0Ah is the opcode for the AAM instruction (ASCII adjust multiply)
it essentially divides the value in AL by 10 and places the quotient in AH and the remainder in AL

by modifying the opcode to 0D4h,10h, we can alter the AAM instruction to divide by 16 instead of 10
so, it splits the lower 4 bits from the upper 4 bits
it is an "undocumented" opcode that has worked since the 8088 - intel and amd have always supported it in new CPUs

it saves some code because it is small
AAM is not a particularly fast instruction, though
on pentiums it is about 18 clock cycles - a mov/shift/and combination is probably slightly faster
on the 8088, it was 84 clock cycles if i remember correctly

if you want speed, code it the other way
if you want small size, use AAM   :bg
Title: Re: Memory Map
Post by: MichaelW on March 09, 2010, 08:05:34 PM
Zulfi,

DB is a data definition directive that allocates one or more unsigned bytes. It's the same directive that you would use in the data segment, but here it is used in the code segment to "synthesize" a form of the AAM instruction that behaves differently than the normal form. You can walk through it in DEBUG to see how it behaves:

-a

0B10:0100 mov al, 63      ; load 99d into AL

0B10:0102 aam             ; convert to unpacked BCD in AX

0B10:0104 mov al, 63      ; load 99d into AL

0B10:0106 db  d4 10       ; convert to unpacked BCH in AX

0B10:0108 nop             ; this is just a filler

0B10:0109

-r

AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000 
DS=0B10  ES=0B10  SS=0B10  CS=0B10  IP=0100   NV UP EI PL NZ NA PO NC
0B10:0100 B063          MOV AL,63                             
-t 4


AX=0063  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000 
DS=0B10  ES=0B10  SS=0B10  CS=0B10  IP=0102   NV UP EI PL NZ NA PO NC
0B10:0102 D40A          AAM                                   

AX=0909  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000 
DS=0B10  ES=0B10  SS=0B10  CS=0B10  IP=0104   NV UP EI PL NZ NA PE NC
0B10:0104 B063          MOV AL,63                             

AX=0963  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000 
DS=0B10  ES=0B10  SS=0B10  CS=0B10  IP=0106   NV UP EI PL NZ NA PE NC
0B10:0106 D410          AAM 10                                 

AX=0603  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000 
DS=0B10  ES=0B10  SS=0B10  CS=0B10  IP=0108   NV UP EI PL NZ NA PE NC
0B10:0108 90            NOP                                   
-q


Note that I added the comments after I captured the output. Also note that I labeled the output for the second form as BCH (Binary-Coded Hex) for want of a better term.

Title: Re: Memory Map
Post by: FORTRANS on March 09, 2010, 10:58:09 PM
Quote from: dedndave on March 09, 2010, 07:34:02 PM
...
it saves some code because it is small
AAM is not a particularly fast instruction, though
...
if you want speed, code it the other way
if you want small size, use AAM   :bg

Hi,

   I mostly wanted to show another way to do the job.  And
if you are going to call DOS or BIOS to emit a character, the
speed is moot.  I probably underdocumented it though.

Regards,

Steve N.
Title: Re: Memory Map
Post by: dedndave on March 09, 2010, 11:59:34 PM
i was just trying to give Zulfi a heads up on using an undocumented opcode - lol
every now and then, he is likely to see some hard-coded instruction - good to know what it is
Title: Re: Memory Map
Post by: zak100 on March 17, 2010, 06:21:44 PM
Hi,
I cant understand following set of instruction:

CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

I have found that DAS subtract 6 or 60 h depending on the value of lower and upper nibble in AL.
What is the significance of 69H.
I need an example in this regard.

Thanks for helping me.

Zulfi.
Title: Re: Memory Map
Post by: dedndave on March 18, 2010, 02:33:57 AM
the CMP AL,10h sets or clears the carry flag for the SBB instruction
the DAS instruction acts like this (copied from Randy Hyde's AoA)

if ( (al and 0Fh) > 9 or (AuxC = 1)) then
        al := al -6
        AuxC = 1
endif
if (al > 9Fh or Carry = 1) then
        al := al - 60h
        Carry := 1              ;Set the Carry flag
endif


so, there is no "magic", Zulfi - lol
in computers, there rarely is
microwave circuits - now, that's another subject   :P
Title: Re: Memory Map
Post by: zak100 on March 18, 2010, 05:55:27 AM
Thanks. Kindly say something about 69h also.

Zulfi.
Title: Re: Memory Map
Post by: dedndave on March 18, 2010, 11:42:00 AM

; AL = 0 to 0Fh

        cmp     al,0Ah
        sbb     al,69h
        das

; AL = ASCII hexidecimal

; initial AL   CF after CMP   AL after SBB   AC after SBB   AL after DAS
;
;     0             CY             96h            AC             30h
;     1             CY             97h            AC             31h
;     2             CY             98h            AC             32h
;     3             CY             99h            AC             33h
;     4             CY             9Ah            AC             34h
;     5             CY             9Bh            AC             35h
;     6             CY             9Ch            AC             36h
;     7             CY             9Dh            AC             37h
;     8             CY             9Eh            AC             38h
;     9             CY             9Fh            AC             39h
;    0Ah            NC            0A1h            NA             41h
;    0Bh            NC            0A2h            NA             42h
;    0Ch            NC            0A3h            NA             43h
;    0Dh            NC            0A4h            NA             44h
;    0Eh            NC            0A5h            NA             45h
;    0Fh            NC            0A6h            NA             46h
;
; in this code, the carry flag is always set after the SBB instruction
; the auxilliary carry flag is similar to carry, but applies to the lower nybble of the result
;
; DAS pseudo-code:
;
; if ( (al and 0Fh) > 9 or (AuxC = 1)) then
;         al := al -6
;         AuxC = 1
; endif
; if (al > 9Fh or Carry = 1) then
;         al := al - 60h
;         Carry := 1
; endif
Title: Re: Memory Map
Post by: FORTRANS on March 18, 2010, 12:51:36 PM
Hi,

   Sorry Zulfi, I probably should not have said "magic".  But as
shown in my other posts, I have a defective sense of humor.
It probably should have said "This converts binary to ASCII,
but how this is done is too complex to fit in the margin".  The
69H just happens to work with the CMP, SBB, and DAS sequence.
(And that appears to be magic until you work out how it really works.)
dedndave shows exactly how that works out in his last post.  You
can walk through the code in DEBUG (or another debugger/emulator)
to see how it works for yourself.

Regards,

Steve


A:\>debug
-a
1673:0100 nop
1673:0102 cmp al,a
1673:0104 sbb al,69
1673:0106 das
1673:0107 jmp 100
1673:0109
-t4

AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1673  ES=1673  SS=1673  CS=1673  IP=0102   NV UP EI PL ZR NA PE NC
1673:0102 3C0A          CMP     AL,0A

AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1673  ES=1673  SS=1673  CS=1673  IP=0104   NV UP EI NG NZ AC PE CY
1673:0104 1C69          SBB     AL,69

AX=0096  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1673  ES=1673  SS=1673  CS=1673  IP=0106   NV UP EI NG NZ AC PE CY
1673:0106 2F            DAS

AX=0030  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=1673  ES=1673  SS=1673  CS=1673  IP=0107   OV UP EI PL NZ AC PE CY
1673:0107 EBF7          JMP     0100
-rax
AX 0030
:9
-t5


   Repeat as necessary!
Title: Re: Memory Map
Post by: zak100 on March 18, 2010, 02:59:32 PM
Hi,
I think it should help me. Thanks for giving me so much time.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on March 19, 2010, 03:01:13 PM
Hi,
I am facing prob with DAS:


AL=AL-CF-69
AL=0-1-69
AL=0-6A
AL=96H using 2's complement

DAS:
if ((96H and 0FH) > 9 or (AUXC=1)) ----TRUE because AUXC =1

al=al-6
al= 96 -6
al=90h

At this point AL should be 30H instead of 90H.


Can somebody help me with this prob.
Zulfi.
Title: Re: Memory Map
Post by: dedndave on March 19, 2010, 03:43:41 PM

; if ( (al and 0Fh) > 9 or (AuxC = 1)) then
;         al := al -6
;         AuxC = 1
; endif
; if (al > 9Fh or Carry = 1) then
;         al := al - 60h
;         Carry := 1
; endif

the last section subtracts another 60h
for this code, the carry flag is always set just prior to the DAS instruction
Title: Re: Memory Map
Post by: zak100 on March 19, 2010, 05:51:14 PM
Ok. Thanks for your reply.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on April 03, 2010, 05:36:43 PM
Hi,
I have written the code and I now understand most of it but its not printing any new stuff i.e base address and length of region.
Following is the code:


;Declarations

arr  db 10 dup(0)
VAL1 db 0
VAL2 db 0
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>

;Calling procedure

call do_e820_Step1

;procedure
;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
;jmp short jmpin
;jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];
        jecxz skipent
goodent:
        inc bp
       
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
je short e820f
next_call2:                     
        call QW2Hex$            ;Displaying the base address
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di
        call QW2Hex$            ;Displaying the length of region
        add di, 24
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

;----other procdures
;--------------------------------- By Steve
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    Call with DS:SI pointing to a QWORD (eight bytes) to be
; displayed as hexadecimal. Not now. SI removed

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;
                     ;Displaying the array contents

        mov ax,0B800h
        mov es,ax
        xor di,di
        mov di,50h
        mov cx,8       
        mov si,offset arr+LoadOfs
        mov ah,1Fh
nextval: mov al, [si]
        inc si
        stosw     ; <= You are automatically incrementing DI
        loop nextval

        CLD             ; Restore default.

        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET





Kindly some body  help me with this.

Zulf.
Title: Re: Memory Map
Post by: FORTRANS on April 03, 2010, 09:44:53 PM
Hi,

   What environment are you using to test your program?
I see one piece where you have a typo from where I posted
some code and edited it later to fix it.


  RangeType     DD      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DD      ?       ; * Next dword = ACPI 3.0 Extended Attri


   Anyway I am using similar code to yours, and finally got it
working.  I don't see much difference in the individual routines
between your code and mine, except for printing characters.
And formatting output.

   Your posted code does not assemble for me.  So the lack of
exit code and defining an entry point are problems to check on.
And I would use more than five of those descriptor structures
as my test machine is using seven of them.


Regards,

Steve N.
Title: Re: Memory Map
Post by: zak100 on April 04, 2010, 02:03:52 PM
Hi,
Sorry for not posting a compilable version. I have shortened my code and its able to print:
70027002.

I am printing both the base address and region length. I dont know if its the correct value.

I am using a lable 'next_call2' at which point I am displaying the values by calling your routines.

Kindly check if its correct or not. Let me know where to add your two variables.




;//portion of memMap code from original file sect8_2.asm
;//for masm forum
;ml /c memMp2.asm
;link16 /tiny memMp2.obj,memMp2.bin;
;DEBUG Btl3p_3.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp2.BIN
;-w 100 0 1 1
;-q
;DISPLAYING real Time using int 1AH
.MODEL  TINY
.386
.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h

   
;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
       
;---------------------- done - halt
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgAloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        ;jz RTime
        jz mem
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop
        mov cx, 1000
;DISPLAY_TIMER:
;-------------Find Total Memory
mem:        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
msgA db 'Total minutes elapsed since Kernel start is',0
clkcounter db 0
secs db 0
mins db 0
hrs  db 0
cnt  db 0; Its value represents the digits of Timer
s    db 0; selector for secs minutes and hrs used in displayCnt
arr  db 10 dup(0)
VAL1 db 0
VAL2 db 0
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
;jmp short jmpin
;jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];
        jecxz skipent
goodent:
        inc bp
       
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
je short e820f
next_call2:                     
        call QW2Hex$            ;Displaying the base address   <---------------
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di <-----------
        call QW2Hex$            ;Displaying the length of region
        add di, 24
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;
                     ;Displaying the array contents

        mov ax,0B800h
        mov es,ax
        xor di,di
        mov di,50h
        mov cx,8       
        mov si,offset arr+LoadOfs
        mov ah,1Fh
nextval: mov al, [si]
        inc si
        stosw     ; <= You are automatically incrementing DI
        loop nextval

        CLD             ; Restore default.

        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



;----------------------------------------------------------------------------------

        END     Start






Zulfi.

Title: Re: Memory Map
Post by: FORTRANS on April 05, 2010, 02:09:36 PM
Hi Zulfi,

   Okay, I got it to work.  I sure hope your machine boots
faster than mine if you need to reboot each time.  I used
DEBUG to walk through the program.  Anyway, some minimal
changes to your code.


       PAGE ,132    ;## Added for better listing.
...
MMap_Descriptor STRUC    ;## changed for older MASM, you can ignore.
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DD      ?       ; * Next dword = Region "type"  ## change typo.
  ACPI_Attrib   DD      ?       ; * Next dword = ACPI 3.0 Extended Attri  ## change typo.
MMap_Descriptor ENDS
...
        call QW2Hex$            ;Displaying the base address   <---------------
        add di, 8               ;Length of region starts 15 bytes from current val
;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H
                                ;In the procedure we adding 7 to di <-----------
        call QW2Hex$            ;Displaying the length of region
...
QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES      ;## You are using ES then changing it to display the characters.
...
        mov di,50h
        mov cx,16      ;## 8 bytes will be 16 characters.  And it comes out backwards...
        mov si,offset arr+LoadOfs
...
        POP     ES      ;##
        POP     CX
        POP     AX
        POP     DI


   This got me the same values as MichaelW's and my code gave
on my computer.  I may have missed something, but that was
most of what I did.

HTH,

Steve N.
Title: Re: Memory Map
Post by: zak100 on April 05, 2010, 06:16:24 PM
Thanks Steve. I am little bit slow. I am interested in this. I am impressed by quick response from you people. I would try to get back on this as early as possible.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on April 08, 2010, 06:36:27 PM
Hi,
I am getting 16 0s as base address and following value as length of region:
7002700270027002

What does it mean??

Thanks for your help. I am still trying to print it using base:length of Region format (style).

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on April 08, 2010, 09:49:14 PM
Hi,

   When I got that value it meant that the ES register was
pointing to the wrong segment.  It was pointing to the video
segment and not your data area.  20 hex is a space and
07H is the default background attribute.

Regards,

Steve
Title: Re: Memory Map
Post by: zak100 on April 09, 2010, 08:00:58 AM
Hi,
Thanks for your attention. By wrong you mean that there is a technical error in my code ??

Quote
<<20 hex is a space and
07H is the default background attribute.>>


This means that the value printed is not the length of region.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on April 09, 2010, 10:55:05 AM
Hi,

QuoteBy wrong you mean that there is a technical error in my code ??

   My post in reply 51 has eight pieces of code marked with ##.
Did you make all of those changes to your code?  More changes
are _still_ needed, but that was the minimum to show the region
length data in some form.  Actually two of the ## marked pieces
are sort of extra, but the rest are needed.

QuoteThis means that the value printed is not the length of region.

   Exactly.  The length of the region is stored in your program's data
by the BIOS.  The 20072007H is in the video display memory.  On my
computer the length printed out as 000000000009FC00, after reformatting
it.  You should see something similar for the length on your computer.

Steve
Title: Re: Memory Map
Post by: zak100 on April 09, 2010, 02:47:15 PM
Thanks for your reply. I am checking what I missed.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on April 09, 2010, 06:37:41 PM
Hi,
I checked and I found that I forgot PUSH and POP ES.

But I am getting 0's for base but for length of region I am getting:
004f000000000000

I am also showing you my code:


;//portion of memMap code from original file sect8_2.asm
;//Updated by Steve :masm forum
;ml /c memMp3.asm
;link16 /tiny memMp3.obj,memMp3.bin;
;DEBUG Btl3p_3.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp3.BIN
;-w 100 0 1 1
;-q
;DISPLAYING real Time using int 1AH
.MODEL  TINY
.386
.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h

   
;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
       
;---------------------- done - halt
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgAloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        ;jz RTime
        jz mem
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop
        mov cx, 1000
;DISPLAY_TIMER:
;-------------Find Total Memory
mem:        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
msgA db 'Total minutes elapsed since Kernel start is',0
clkcounter db 0
secs db 0
mins db 0
hrs  db 0
cnt  db 0; Its value represents the digits of Timer
s    db 0; selector for secs minutes and hrs used in displayCnt
arr  db 10 dup(0)
VAL1 db 0
VAL2 db 0
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
;jmp short jmpin
;jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];
        jecxz skipent
goodent:
        inc bp
       
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
je short e820f
next_call2:                     
        call QW2Hex$            ;Displaying the base address   <---------------
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di <-----------
;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H
        call QW2Hex$            ;Displaying the length of region
        add di, 24
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;
                     ;Displaying the array contents

        mov ax,0B800h
        mov es,ax
        xor di,di
        mov di,50h
        mov cx,16        ;## 8 bytes will be 16 characters.  And it comes out backwards...
        mov si,offset arr+LoadOfs
        mov ah,1Fh
nextval: mov al, [si]
        inc si
        stosw     ; <= You are automatically incrementing DI
        loop nextval

        CLD             ; Restore default.

        POP     ES
        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



;----------------------------------------------------------------------------------

        END     Start




Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on April 10, 2010, 02:05:03 PM
Hi Zulfi,

Quote
I checked and I found that I forgot PUSH and POP ES.

   Right.  Fits the symptoms.

QuoteBut I am getting 0's for base but for length of region I am getting:
004f000000000000

   Except for being backwards that looks okay.  To "unbackwards"
the number change the code something like.

   Either pull this out and make it a separate routine.  That
would be a start to change where the number prints out later on.


                     ;Displaying the array contents

        mov ax,0B800h
        mov es,ax
        xor di,di
        mov di,50h          ; <= You will want to make this changable to print in different places.
        mov cx,16        ;## 8 bytes will be 16 characters.  And it comes out backwards...
        mov si,offset arr+LoadOfs
        mov ah,1Fh
nextval: mov al, [si]
        inc si
        stosw     ; <= You are automatically incrementing DI
        loop nextval


   Or move it to be after this line for a quick fix.


        CLD             ; Restore string instruction direction default.


   Tricky.

Regards,

Steve N.
Title: Re: Memory Map
Post by: zak100 on April 10, 2010, 05:59:31 PM
Hi,
Thanks. I would try what you have said. If you have some more time, kindly tell me what you mean by:

Quote

That
would be a start to change where the number prints out later on.



Sorry for taking so much of your time.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on April 10, 2010, 09:29:46 PM
Hi,

   Right now it prints the number in one place only.  You will
probably want to be able to print it anywhere on the screen
some time.  That allows formatting the program output.  Having
a smaller routine can make it easier to see how and where to
change the code.

Steve
Title: Re: Memory Map
Post by: zak100 on April 11, 2010, 04:46:16 AM
Hi,

Thanks for your reply. Its clear to me now.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on April 14, 2010, 06:40:36 PM
Hi,
I am trying to do it with a macro which was developed on this forum. It was working previously but now I am getting syntax error.
I dont have any clue for it.


;//portion of memMap code from original file sect8_2.asm
;//Updated by Steve :masm forum
;ml /c memMp3.asm
;link16 /tiny memMp3.obj,memMp3.bin;
;DEBUG Btl3p_3.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp3.BIN
;-w 100 0 1 1
;-q
;DISPLAYING real Time using int 1AH
.MODEL  TINY
.386

print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
       push    ax
       mov     ax,xlat0
       push    ax
       retf


;display the message at B800:50h

xlat0: mov     ax,0B800h     
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm



.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h

   
;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
       
;---------------------- done - halt
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgAloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        ;jz RTime
        jz mem
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop
        mov cx, 1000
;DISPLAY_TIMER:
;-------------Find Total Memory
mem:        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
msgA db 'Total minutes elapsed since Kernel start is',0
clkcounter db 0
secs db 0
mins db 0
hrs  db 0
cnt  db 0; Its value represents the digits of Timer
s    db 0; selector for secs minutes and hrs used in displayCnt
arr  db 10 dup(0)
VAL1 db 0
VAL2 db 0
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
;jmp short jmpin
;jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];
        jecxz skipent
goodent:
        inc bp
       
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
je short e820f
next_call2:                     
        call QW2Hex$            ;Displaying the base address   <---------------
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di <-----------
;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H
        call QW2Hex$            ;Displaying the length of region
        add di, 24
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;
                     ;Displaying the array contents<------------------

        ;mov ax,0B800h
        ;mov es,ax
        ;xor di,di
        ;mov di,50h
        ;mov cx,16        ;## 8 bytes will be 16 characters.  And it comes out backwards...
        ;mov si,offset arr+LoadOfs
        ;mov ah,1Fh
;nextval: mov al, [si]
        ;inc si
        ;stosw     ; <= You are automatically incrementing DI
        ;loop nextval

        ;CLD             ; Restore default.

        print_mesg macro offset arr+LoadOfs, 50h, 16;<----------SYNTAX ERROR
        nextval: lodsb
                 stosw
        loop nextval
       
        POP     ES
        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



;----------------------------------------------------------------------------------

        END     Start










I am getting arror at the following spot in the code:

<----------SYNTAX ERROR

The error is:


D:\masm prog\OS10_MemMap_totMem>ml /c memMp3.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: memMp3.asm
memMp3.asm(238) : error A2008: syntax error : arr

D:\masm prog\OS10_MemMap_totMem>




Can somebody guide me with this?

Zulfi.
Title: Re: Memory Map
Post by: dedndave on April 14, 2010, 07:29:58 PM
when you define a macro, you use the word "macro" - not when you invoke it
also, the offset arr+LoadOfs may be a bit much to pass as a single argument
you might try this, Zulfi

MyArg   EQU     <offset arr+LoadOfs>
        print_mesg MyArg, 50h, 16
Title: Re: Memory Map
Post by: zak100 on April 15, 2010, 05:16:43 AM
Thanks.

Its my fault but I have learned something new.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on April 15, 2010, 06:26:38 PM
Hi,
This time its printing 16 0s as Base address and then:
0000 0000 0000 F400

as the length of region. Macro has solved the backward problem though I am not much clear about it.


Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on April 16, 2010, 01:18:40 PM
Hi,

   Those numbers look okay for the base and size.  You can
compare using the MEM /C command and look for conventional
memory.

   The following lines are intended to be "paired".  Comment
both or uncomment both.  Since they are not now being
used, you should delete or comment them.


        STD             ; String instructions decrement.
        ;CLD             ; Restore default.


Regards,

Steve N.
Title: Re: Memory Map
Post by: zak100 on June 02, 2010, 06:31:42 PM
Hi,
I would comment the 'std' in my next run. However now I want to print the Base and length side by side. For this I have parameterized the macro call.


print_mesg MyArg, ScrCoord, 16;<------------------


I have declared ScrCoord as:
   

ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region length
                ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Macro argument



The whole code is given below:



;//portion of memMap code from original file sect8_2.asm
;//Updated by Steve :masm forum

;"Solved the prob of backward printing of the length of region"
;Beyond memMp3: printing the base address & pause & then the offset at different locations
;               both visible
;-------------------------------------------------------------
;ml /c memMp4.asm
;link16 /tiny memMp4.obj,memMp4.bin;
;DEBUG Btl3p_3.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp4.BIN
;-w 100 0 1 1
;-q
.MODEL  TINY
.386

print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
       push    ax
       mov     ax,xlat0
       push    ax
       retf


;display the message at B800:50h

xlat0: mov     ax,0B800h     
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm



.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h

   
;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
       
;---------------------- done - halt; NOT A CLK PROG
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgAloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        ;jz RTime
        jz mem
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop
        mov cx, 1000
;DISPLAY_TIMER:
;-------------Find Total Memory
mem:        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
msgA db 'Total minutes elapsed since Kernel start is',0
clkcounter db 0
secs db 0
mins db 0
hrs  db 0
cnt  db 0; Its value represents the digits of Timer
s    db 0; selector for secs minutes and hrs used in displayCnt
arr  db 10 dup(0)
VAL1 db 0
VAL2 db 0
ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region length
                ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Macro argument
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MyArg   EQU     <offset arr+LoadOfs>

       
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
;jmp short jmpin
;jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length; i.e from 8 to 11
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];i.e from 12 to 15
        jecxz skipent
goodent:
        inc bp
       
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
je short e820f
next_call2:     
;---------------------------    ;NOTE QW2HEX$ converts to Hex & prints using Macro
                 
        call QW2Hex$            ;Displaying the base address   
;--------------------------     Incrementing the screen coordinates
        ;push dx
        ;mov dx,ScrCoord
        ;add dx, 20h
        ;mov ScrCoord, dx
        ;pop dx
;------------------------------
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di
;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H
        call QW2Hex$            ;Displaying the length of region
;--------------------------     Incrementing the screen coordinates
        ;push dx
        ;mov dx,ScrCoord
        ;add dx, 30h
        ;mov ScrCoord, dx
        ;pop dx
;-------------------------
        add di, 24
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
                        ; When called 1st DI=0. Now DI =7. So print from 7 to 0. So it pints the Base address
                        ; When called 2nd time DI=8. After adding DI=15. So it prints the length of region

        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;---------------------------Calling Macro with the screen coordinates
       
        ;print_mesg MyArg, 50h, 16;
        print_mesg MyArg, ScrCoord, 16;<------------------
        nextval: lodsb
                 stosw
        loop nextval
       
        POP     ES
        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



;----------------------------------------------------------------------------------

        END     Start





I am seeing the two messages but its not printing any values. Can somebody help me with this?

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 03, 2010, 02:00:46 PM
Hi Zulfi,

   I took a look at your code, but on a computer that
is not too conveniently set up, so I may have not gotten
things quite right.

   You have:


print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
       push    ax
       mov     ax,xlat0
       push    ax
       retf


;display the message at B800:50h

xlat0: mov     ax,0B800h     
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm


   I think it should be something more like:


print_mesg macro offsetStr, offsetScr, msgSize
        LOCAL xlat0

        mov     ax,cs
        mov     ds,ax
;       push    ax      ; I do not see why you are doing this?
;       mov     ax,xlat0
;       push    ax
;       retf

;display the message at B800:50h

xlat0:  mov     ax,0B800h
        mov     es,ax
        mov     di,OFFSET offsetScr  ; This is where the error in printing occurs, fix?
        mov     si, offsetStr
        cld
        mov     ah,1Fh
        mov     cx,msgSize
endm


   Actually, I don't know if the OFFSET should be in the
macro or in the line where you invoke the macro.  I
just found the wrong value in DI when it was being used.
So maybe:


        print_mesg OFFSET MyArg, ScrCoord, 16;<------------------


   And you still need to fix this.


  RangeType     DD      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DD      ?       ; * Next dword = ACPI 3.0 Extended Attri


HTH,

Steve N.
Title: Re: Memory Map
Post by: zak100 on June 03, 2010, 06:50:34 PM
Thanks for your reply.

For the offset Dave told me to use a macro:


MyArg   EQU     <offset arr+LoadOfs>



Thus when I use:

print_mesg MyArg, 50h, 16;



It works fine. But when i use a variable for 50h i.e :


print_mesg MyArg, ScrCoord, 16;



Its not working.

This is the problem.
If somebody has any solution for this, kindly help me.

I would check about the second part of your statement later.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 03, 2010, 07:37:53 PM
Hi,

   My mistake.  What I posted was wrong.  Adding an
OFFSET is not the answer.  And I managed to put the
OFFSET on the wrong argument on the macro call anyway.
But the DI register had a bad value in it in DEBUG.  I will
try to find out where it came from.  It ended up writing
to a different page of video memory, so I saw nothing
on screen.

Regards,

Steve N.
Title: Re: Memory Map
Post by: FORTRANS on June 03, 2010, 08:21:49 PM
Hi,

   Okay, here is the problem:


arr  db 10 dup(0)
VAL1 db 0
VAL2 db 0
ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region length
                ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Macro argument
AscBuf  db      8 dup (0),' Kb Total Memory',0


    ScrCoord is being overwritten by the binary to ASCII routine.
So instead of it being 50H it is 3030H when it is first used.  Not
actually tracked down, so this is a guess, arr is 10 and it should
be at least 16 (10H).  See if that helps.

Steve N.
Title: Re: Memory Map
Post by: zak100 on June 04, 2010, 10:08:39 AM
Yes, it helped. I would also try Debug.

Thanks.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 04, 2010, 11:53:48 AM
Quote from: zak100 on June 04, 2010, 10:08:39 AM
Yes, it helped. I would also try Debug.

Thanks.

Zulfi.

Hi,

   Most of the work to get it running in DEBUG is to change
ORG 0 to ORG 100H and create a *.COM executable.  I
also got rid of the code that used the RETF as it crashed
the program in a VDM.

Regards,

Steve
Title: Re: Memory Map
Post by: zak100 on June 04, 2010, 05:32:34 PM
Thanks.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on June 05, 2010, 06:30:47 PM
Hi,
I am trying to update the code by printing the base address, pause and then the length of region. Currently I am printing the base address then pause and length of the region at the same place where base is located. I am using the following code:


push dx                   ;<---------------------
        mov dx,ScrCoord
        add dx, 20h
        mov ScrCoord, dx
        pop dx


This code is giving me prob because I cant see any test messages and computer hangs up.
I have tried Debug also but after int 15h it fails and goes to stc instruction.

The whole code is :





;//portion of memMap code from original file sect8_2.asm
;//Updated by Steve :masm forum

;"Solved the prob of backward printing of the length of region"
;Beyond memMp3: printing the base address & pause & then the offset at different locations
;               both visible
;               using arguments for print_mesg macro e.g:
; print_mesg MyArg, ScrCoord, 16;
;-------------------------------------------------------------
;ml /c memMp4.asm
;link16 /tiny memMp4.obj,memMp4.bin;
;DEBUG Btl3p_3.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp4.BIN
;-w 100 0 1 1
;-q
.MODEL  TINY
.386

print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
       push    ax
       mov     ax,xlat0
       push    ax
       retf


;display the message at B800:50h

xlat0: mov     ax,0B800h     
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm



.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h

   
;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
       
;---------------------- done - halt; NOT A CLK PROG
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgAloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        ;jz RTime
        jz mem
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop
        mov cx, 1000
;DISPLAY_TIMER:
;-------------Find Total Memory
mem:        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
msgA db 'Total minutes elapsed since Kernel start is',0
clkcounter db 0
secs db 0
mins db 0
hrs  db 0
cnt  db 0; Its value represents the digits of Timer
s    db 0; selector for secs minutes and hrs used in displayCnt
arr  db 16 dup(0)
VAL1 db 0
VAL2 db 0
ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region length
                ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Macro argument
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MyArg   EQU     <offset arr+LoadOfs>

       
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
;jmp short jmpin
;jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length; i.e from 8 to 11
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];i.e from 12 to 15
        jecxz skipent
goodent:
        inc bp
       
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
je short e820f
next_call2:     
;---------------------------    ;NOTE QW2HEX$ converts to Hex & prints using Macro
                 
        call QW2Hex$            ;Displaying the base address   
;--------------------------     Incrementing the screen coordinates
        push dx                   ;<---------------------NEW
        mov dx,ScrCoord
        add dx, 20h
        mov ScrCoord, dx
        pop dx
;------------------------------
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di
;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H
        call QW2Hex$            ;Displaying the length of region
;--------------------------     Incrementing the screen coordinates
        push dx<------NEW
        mov dx,ScrCoord
        add dx, 30h
        mov ScrCoord, dx
        pop dx
;-------------------------
        add di, 24
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
                        ; When called 1st DI=0. Now DI =7. So print from 7 to 0. So it pints the Base address
                        ; When called 2nd time DI=8. After adding DI=15. So it prints the length of region

        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;---------------------------Calling Macro with the screen coordinates
       
        ;print_mesg MyArg, 50h, 16;
        print_mesg MyArg, ScrCoord, 16;<------------------
        nextval: lodsb
                 stosw
        loop nextval
       
        POP     ES
        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



;----------------------------------------------------------------------------------

        END     Start





Can somebody help me with this?

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 06, 2010, 04:40:58 PM
Hi,

   Actually, with the changes I suggested, it is working for me.
If you are using Windows 2000, XP, or such, the INT 15H
is going to fail.  In reply #69 the stuff about OFFSET was
bad.  But I commented out the RETF code in your macro
because it crashed the program on my computer.  Maybe
it is doing the same to yours?  And your STRUCT still needs
fixing, though that is not the problem now.

   Dave, or anyone, is the order he is pushing the segment
and address backwards?  And what does that code accomplish?

Regards,

Steve
Title: Re: Memory Map
Post by: MichaelW on June 06, 2010, 05:34:28 PM
The segment would be pushed first, placing it at the higher address and the offset at the lower address.
Title: Re: Memory Map
Post by: zak100 on June 06, 2010, 05:38:22 PM
My program is crashing with int 15h. For 32 bit registers, Debug is showing DB 66 as the instruction instead of the original instruction in the program. i got the Debug tutorial also  by MichealW  which I would also check later on.

In order to avoid int 15h, I am writing a simple program to see if my code works and if it doesnt I can troubleshoot using debug.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on June 06, 2010, 06:17:09 PM
Hi,
I have tried printing two strings in another program using the macro which I am using in my program, reply#76. It works fine. It prints the first string then pause and then the 2nd string.

The code for that program is :


.MODEL  TINY
.386
print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
       push    ax
       mov     ax,xlat0
       push    ax
       retf


;display the message at B800:50h

xlat0: mov     ax,0B800h     
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm

;------------------
.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h
;----------------------msg0
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
        ;--------------
TimerMesg: print_mesg MyArg1, ScrCoord, 16;
disp0:  lodsb
        stosw
loop disp0
        ;--------------changing screen Coordinates
       
push dx                   ;<---------------------
        mov dx,ScrCoord
        add dx, 20h
        mov ScrCoord, dx
        pop dx
        ;--------------
        MOV     AX,0    ;## Pause?
        INT     16H
        ;---------------
        print_mesg MyArg2, ScrCoord, 16;
disp1:  lodsb
        stosw
loop disp1

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
arr1  db '1234567890abcdef',0
arr2  db '!!!!!!!!!!!!!!!!',0
ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region length
                ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Macro argument
MyArg1   EQU     <offset arr1+LoadOfs>
MyArg2   EQU     <offset arr2+LoadOfs>


END     Start



But when I am trying the same thing with my code in reply# 76, its not working.

Sorry to say, I cant relate the following quote with my program:
Quote
The segment would be pushed first, placing it at the higher address and the offset at the lower address.

Can somebody help me with my prob.?

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 06, 2010, 06:58:06 PM
Hi,

   Thanks MichaelW, I can never remember those kinds
of things.

Quote
Sorry to say, I cant relate the following quote with my program:

   It means that the code section I was talking about is
not coded incorrectly.

QuoteDebug is showing DB 66 as the instruction instead of the original
instruction in the program.

   That would be a 32-bit instruction (80386 or newer) and
DEBUG can only work with 16-bit (8086) instructions.

Steve N.
Title: Re: Memory Map
Post by: MichaelW on June 06, 2010, 07:47:14 PM
Japheth's DOS Debug clone can handle instruction sets through the Pentium Pro.

http://www.japheth.de/debxxf.html

Title: Re: Memory Map
Post by: zak100 on June 07, 2010, 05:48:00 PM
Thanks for providing me this link. I would try to download it. If anybody having any clue to my printing prob (printing base address and region length side by side using Macro), kindly let me know.

Zulfi.
Title: Re: Memory Map
Post by: dedndave on June 07, 2010, 06:31:15 PM
Zulfi
long ago, i used to make a special floppy that replaced COMMAND.COM with the old DEBUG.COM program
DEBUG.COM came with older versions of DOS - newer versions were EXE's
also, DOS versions older than 3.0 (i think) did not have the EXEC loader installed during CONFIG.SYS
DOS 3 and above had the EXEC loader, so you could install an EXE as a SYS file (tricky - lol)
even so, you can load COMMAND.COM, then use the COMSPEC and SHELL commands in AUTOEXEC.BAT to load an EXE
that way, you can debug through your program without a windows OS loaded
i don't have a floppy drive to play with it at the moment, so you may have to fart around with it a bit   :bg
Title: Re: Memory Map
Post by: zak100 on June 07, 2010, 06:46:39 PM
Hi,
I think you are right. I must  run my program through Debug utility. I would try MichealW's link to find out the bug with my code.
If it works with int 15h its fine, otherwise I have try to resort to your tricks.

Zulfi.
Title: Re: Memory Map
Post by: dedndave on June 07, 2010, 06:51:09 PM
i bet Steve or Michael can tell you how to set up a floppy for debugging (hint hint)
Title: Re: Memory Map
Post by: FORTRANS on June 07, 2010, 08:30:23 PM
Hi,

   I just have a bootable floppy set up with with a large RAM
disk.  You can copy COMMAND.COM to the RAM disk, set
COMSPEC to point to it so you don't have to swap diskettes
after running a program.  And copy what ever you need to a
sub-directory on the RAM drive.  Do your work, copy the results
back to a floppy, and off you go.

   If I follow what Dave was saying, in CONFIG.SYS point
COMSPEC to DEBUG.EXE.

   I use the RAM disk and leave COMMAND.COM on the floppy.
Here is the CONFIG.SYS for a DOS 6.2 diskette.


REM Normal Boot
DEVICE=A:\DOS\HIMEM.SYS
FILES=40
DOS=UMB
LASTDRIVE=J
DEVICEHIGH=A:\DOS\ANSI.SYS
DOS=HIGH
DEVICEHIGH=A:\DOS\RAMDRIVE.SYS 8192 /E
DEVICEHIGH=A:\DOS\SETVER.EXE
SHELL=A:\DOS\COMMAND.COM A:\DOS /P


   And AUTOEXEC.BAT.


echo off
REM Normal Boot

LH /S A:\DOS\SMARTDRV.EXE
PROMPT $p$g
PATH A:\DOS;A:\utility;
rem mkdir G:\temp
rem SET TEMP=G:\TEMP
rem SET TMP=G:\TEMP
sertype

doskey
SET COMSPEC=A:\DOS\COMMAND.COM


Regards,

Steve
Title: Re: Memory Map
Post by: dedndave on June 07, 2010, 10:45:55 PM
thanks Steve
well - what i was refering to was actually either
1) replacing command.com with debug
or
2) setting it up so debug was executed as a command.com shell command

as i said - it has been a long time since i have had to do this
i used to have the requirement to sometimes troubleshoot config.sys type device drivers in this manner
Title: Re: Memory Map
Post by: FORTRANS on June 08, 2010, 12:07:39 PM
Hi Dave,

   For 1) just use COMSPEC in CONFIG.SYS.  (Or REName,
shudder.)  But I need DIR (short memory?) and the like,
so that's not what I try.

   What I posted will get you 2).  If you want, add DEBUG
to AUTOEXEC.BAT.  With a file name argument you don't
even need a good memory.  Here I just end up with the
code off the boot diskette, so I don't [fill in your favorite
stupidity] and junk the boot diskette.

Cheers,

Steve N.
Title: Re: Memory Map
Post by: dedndave on June 08, 2010, 12:10:20 PM
right - he probably doesn't need to go through all the trouble i was going through
i wanted to see the driver in memory before COMMAND.COM was loaded
that is why i went that route
Title: Re: Memory Map
Post by: zak100 on June 09, 2010, 04:32:05 AM
Hi,
Sorry, is this exercise going to help me to get around with int 15h problem
during Debugging?

I am using a floppy disk in which I am storing the bootloader &
the kernel. I have got following Questions:
i) Do I have to use another floppy?
ii) Do I have to change my config.sys and autoexec.bat?
iii)I dont know if I have Dos 6.2. When I type ver, its telling
me the version of OS & not DOS?
iv)If i change my config.sys & Autoexec.bat with the listing provided by
Steve, is it going to do everything, I mean setup the RAM disk & load the
Debug.

Thanks for telling me this new thing.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 09, 2010, 02:24:12 PM
Hi Zulfi,

   Since your code is working for me in DEBUG, I will redo it
as a boot loader to see if anything changes.  But that may
take a while.

Quote from: zak100 on June 09, 2010, 04:32:05 AM
Hi,
Sorry, is this exercise going to help me to get around with int 15h problem
during Debugging?

   Well, that was the idea.  But of course it may not work.  Or
you can procede as you are doing now.

Quote
I am using a floppy disk in which I am storing the bootloader &
the kernel. I have got following Questions:
i) Do I have to use another floppy?

   Probably a very good idea to do so, but not required.

Quote
ii) Do I have to change my config.sys and autoexec.bat?

   If you mean reusing the CONFIG.SYS and AUTOEXEC.BAT
from a Windows system, then yes you cannot use that on a
DOS floppy.

Quote
iii)I dont know if I have Dos 6.2. When I type ver, its telling
me the version of OS & not DOS?

   Right, you probably do not have MS-DOS 6.2.  You can get
"FreeDOS" or another real-mode MS-DOS clone if you don't
have access to a DOS or Windows 9x system.  From what
you have said, you probably have some version of NT style
Windows.

www.freedos.org/ (http://www.freedos.org/)

Quote
iv)If i change my config.sys & Autoexec.bat with the listing provided by
Steve, is it going to do everything, I mean setup the RAM disk & load the
Debug.

   You will have to format a bootable DOS diskette.  Then copy
the RAM Disk driver, DEBUG, DOSKEY, your code, an _old_
version of MASM, and LINK16 to the disk.  Then you can use
the CONFIG.SYS and AUTOEXEC.BAT I posted assuming you
put everything in the same places I did.  You don't need to
worry about the RAM drive, that is just an extra I use. Oh,
EXE2BIN will be needed for making a COM style executable.
And you may want an editor.

   The basic idea was to avoid rebooting after each modification
of the code.  That drove me nuts.  I had/have computers set
up with DOS so things were fairly simple for me to switch over
from a boot loader to DEBUG.  The computer I mostly used
for this is no longer usable, so things are going a bit slower
now.

HTH,

Steve N.
Title: Re: Memory Map
Post by: FORTRANS on June 09, 2010, 08:46:02 PM
Hi,

   Okay, another failure mode found.  My version of this code
assembles to longer than 512 bytes for the boot loader binary.
So I had to modify the boot sector to load two sectors.  Or
it's silently off to la-la land.  And at least it now works as an
independent boot.

Regards,

Steve N.
Title: Re: Memory Map
Post by: zak100 on June 14, 2010, 06:05:43 PM
Hi Steve and Dave (and everybody else who has helped me with this problem),
I have decided to continue my work on memory map. I am working on Debug related stuff in another thread. I have completed the code (using the downloaded stuff), but its not giving me any results. It hangs up after printing character 'A'.



;               Entire code of MemMap: Printing the base address and length in a loop
;-------------------------------------------------------------
;ml /c memMp4.asm
;link16 /tiny memMp4.obj,memMp4.bin;
;DEBUG Btl3p_3.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp4.BIN
;-w 100 0 1 1
;-q

.MODEL  TINY
.386

print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
       push    ax
       mov     ax,xlat0
       push    ax
       retf


;display the message at B800:50h

xlat0: mov     ax,0B800h     
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm



.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h

   
;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
       
;---------------------- done - halt; NOT A CLK PROG
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgAloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        ;jz RTime
        jz mem
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop
        mov cx, 1000
;DISPLAY_TIMER:
;-------------Find Total Memory
mem:        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
msgA db 'Total minutes elapsed since Kernel start is',0
clkcounter db 0
secs db 0
mins db 0
hrs  db 0
cnt  db 0; Its value represents the digits of Timer
s    db 0; selector for secs minutes and hrs used in displayCnt
arr  db 16 dup(0)
VAL1 db 0
VAL2 db 0
ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region length
                ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Macro argument
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MyArg   EQU     <offset arr+LoadOfs>

       
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
jmp short jmpin
e8201p:
        mov eax, 0e820h
        mov dword ptr es:[di + 20], 1
        mov ecx, 24
        int 24h
        jc short e820f
        mov edx, 0534D4150h
jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length; i.e from 8 to 11
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];i.e from 12 to 15
        jecxz skipent
goodent:
        inc bp
        ;---------------------------    ;NOTE QW2HEX$ converts to Hex & prints using Macro
                 
        call QW2Hex$            ;Displaying the base address
       
;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H
       
        push di
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di
        call QW2Hex$            ;Displaying the length of region 
        pop di
        add di, 24
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
jne short e8201p
     
;-------------------------
       
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
                        ; When called 1st DI=0. Now DI =7. So print from 7 to 0. So it pints the Base address
                        ; When called 2nd time DI=8. After adding DI=15. So it prints the length of region

        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;---------------------------Calling Macro with the screen coordinates
       
        ;print_mesg MyArg, 50h, 16;
        print_mesg MyArg, ScrCoord, 16;<------------------
        nextval: lodsb
                 stosw
        loop nextval
       
        POP     ES
        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



;----------------------------------------------------------------------------------

        END     Start







Can anybody check the problem?

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 14, 2010, 07:23:38 PM
Hi,

   Did you make the changes suggested in Reply #93?  I made
only minor changes to your code and it is working for me.  Alter
the boot sector to load two sectors instead of one.  And of course
write out two sectors from DEBUG.

   If you did make those changes, I would add a failure message
for the test for a "good interrupt".


failed:
     : Write a message to the screen. "INT E820 not supported".
stc ; "function unsupported" error exit
        pop es
ret
Title: Re: Memory Map
Post by: zak100 on June 15, 2010, 07:12:53 AM
Thanks. I read your reply again and now its clear to me. I would try to do the required changes. I have not checked the size of my binary yet.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on June 18, 2010, 05:49:57 PM
Hi Steve, Dave ( and every person who is helping me with this code),
I have modified the boot sector program. I dont know whether its correct or not so I want to get some comment  from you people.
The code is given below:
 
;*
;ml /c btl3p_4.asm
;link16 /tiny btl3P_4.obj,btl3P_4.bin;
;
;DEBUG btlder3P_4.BIN
;-w 100 0 0 1
;-q

;DEBUG sect4_2.BIN
;-w 100 0 1 1
;-q
;*

.MODEL  TINY
        .CODE
;----------------------------------------------------------------------------------

LoadOfs EQU     0
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- branch to executable code

        ORG     0

Boot0:  jmp short Boot1
nop
;---------------------- OEM identifier

        ORG     3

        DB      "Zulfi OS"

;---------------------- BIOS parameter block for 1.44 Mb floppy disk

        ORG     0Bh

bpbBytesPerSector    DW 512
bpbSectorsPerCluster DB 2; 1
bpbReservedSectors   DW 1
bpbNumberOfFATs      DB 2
bpbRootEntries       DW 112; 224
bpbTotalSectors      DW 1440; 2880
bpbMedia             DB 0F9H; 0F0h
bpbSectorsPerFAT     DW 3; 9
bpbSectorsPerTrack   DW 9; 18; different (18)
bpbHeadsPerCylinder  DW 2
bpbHiddenSectors     DD 0
bpbTotalSectorsBig   DD 0
bsDriveNumber        DB 0
bsUnused             DB 0
bsExtBootSignature   DB 29h
bsSerialNumber       DD 0a0a1a2a3h
bsVolumeLabel        DB "MOS FLOPPY "
bsFileSystem         DB "FAT12   "
SectorNum            DB  1
LoadOfsvar      DW  LoadOfs

;---------------------- initialize SS:SP
Boot1:  cli                     ;disable maskable interrupts
        xor     di,di
        mov     ss,di
        mov     sp,7C00h        ;SS:SP = 0000:7C00
        sti                     ;enable maskable interrupts
;---------------------- display 'A' character
        cld
        mov     ax,0B800h
        mov     es,ax
        mov     ax,1F41h
        stosw
;---------------------- wait for a keypress
        mov     ah,0
        int     16h
;--------------------- read bootloader
ReadSectorLoop:
        mov     cx,5            ;retry count
Reset0: push    cx
        mov     ah,0            ;reset floppy disk function
        mov     dl,0            ;drive A:
        int     13h

        mov     ax,LoadSeg      ;read sector into address LoadSeg:LoadOfs
        mov     es,ax
        mov     bx,LoadOfsVar

        call    ReadSectors
        pop     cx
        jnc     PreReadNextSector
        loop    Reset0
        jc      ReadError   ;After 5th try display error message
        jmp     Exec0
PreReadNextSector:
        inc     SectorNum
        cmp     SectorNum, 3; ---------------reading first 2 sectors
        jz      Exec0
        add     LoadOfsVar, 512
        jmp     ReadSectorLoop

;---------------------- failed 5 times - halt
;---display 'F' character  to show the failure occured
ReadError:
mov ax, 0B800h
mov es, ax
mov Di,4
mov ax, 9c46h
stosw


Halt0:  hlt
      jmp     Halt0
;----------------------
ReadSectors:
      mov ax, 201h ;ah=2 function, al=1 (read 1 sector only)
      mov ch,0; Track
      mov cl, sectorNum ;Sector start with 1 not 0
      xor dx, dx; Head 0, drive 0
      int 13h
      ret

;---------------------- execute the bootloader code


Exec0:
        db      0EAh            ;JMP FAR instruction
        dw      LoadOfs         ;offset
        dw      LoadSeg         ;segment

;---------------------- boot sector signature


     
        ORG     1FEh

        dw      0AA55h

;----------------------------------------------------------------------------------

        END     Boot0



About the Kernel, do I have to break it into two separate executable programs? Kindly advise me how to break the Kernel?

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 18, 2010, 10:06:34 PM
Hi,

QuoteAbout the Kernel, do I have to break it into two separate executable programs?

   I didn't.  I did a little less work with my version.  Here is
what I did.


COMMENT * Original code by dedndave on MASM32 Forum.  Modifications,
additions, tpyos, and corrections FORTRANS (Steve) on MASM32 Forum.
27 November 2009
10 June 2010 load two sectors.

REM Create BooSect.BIN, NOT sure about ML switches.
\MASM32\BIN\ML /AT /c /Fl /Fm BootSect.ASM
\MASM32\BIN\LINK16 BootSect.OBJ;
EXE2BIN BootSect.EXE

11/27/2009  04:02p                  40 BOOTLOAD.BIN
11/27/2009  04:02p                 512 BOOTSECT.BIN
06/09/2010  03:24p                 548 TEST22.BIN

DEBUG BootSect.BIN
-w 100 0 0 1
-q

DEBUG BootLoad.BIN
-w 100 0 1 2
-q

TODO:  Use a different sector to write/read BootLoad.BIN to.
       Convert to hexadecimal and display contents of CS and IP.
       Fix up messages...
*

        .MODEL  TINY
        .CODE

;----------------------------------------------------------------------

LoadOfs EQU     0
LoadSeg EQU     1000h

;----------------------------------------------------------------------

;---------------------- branch to executable code

        ORG     0

Boot0:  jmp short Boot1
        NOP     ; - - - Mods to deadndave's code: Win2K error fix,
                ; - - - original was a zero.

;---------------------- OEM identifier

        ORG     3

        DB      "Steve OS"

;---------------------- BIOS parameter block for 1.44 Mb floppy disk
; - - - Mod to 720K - - -

        ORG     0Bh

bpbBytesPerSector    DW 512
bpbSectorsPerCluster DB 1 ; 2 ; 1   Mods to deadndave's code: Cluster size,
                             ; may/may not have caused a problem?  He was okay?
bpbReservedSectors   DW 1
bpbNumberOfFATs      DB 2
bpbRootEntries       DW 112  ; 224    Mods to deadndave's code: 720 K
bpbTotalSectors      DW 1440 ; 2880   diskette instead of 1.44 M
bpbMedia             DB 0F9H ; 0F0h
bpbSectorsPerFAT     DW 3    ; 9
bpbSectorsPerTrack   DW 9    ; 18
bpbHeadsPerCylinder  DW 2
bpbHiddenSectors     DD 0
bpbTotalSectorsBig   DD 0
bsDriveNumber        DB 0
bsUnused             DB 0
bsExtBootSignature   DB 29h
bsSerialNumber       DD 0DeadBeefH
bsVolumeLabel        DB "MOS FLOPPY "
bsFileSystem         DB "FAT12   "

;---------------------- initialize SS:SP

Boot1:  cli                     ;disable maskable interrupts
        xor     di,di
        mov     ss,di
        mov     sp,7C00h        ;SS:SP = 0000:7C00
        sti                     ;enable maskable interrupts

;---------------------- display 'A' character

        cld
        mov     ax,0B800h       ; CGA text memory segment
        mov     es,ax
        mov     ax,1F41h
        stosw                   ; Store character and attribute.

;---------------------- wait for a keypress

        mov     ah,0            ; Keboard BIOS wait for character.
        int     16h

;---------------------- read the bootloader code

        mov     cx,5            ;retry count

Reset0: push    cx
        mov     ah,0            ;reset floppy disk function
        mov     dl,0            ;drive A:
        int     13h

        mov     ax,LoadSeg      ;read sector into address LoadSeg:LoadOfs
        mov     es,ax
        mov     bx,LoadOfs

        mov     cx,2            ;cylinder 0, sector 2 (1 based)
        xor     dx,dx           ;head 0, drive 0
        mov     ax,202h         ;read 2 sectors
        int     13h
        pop     cx
        jnc     Exec0

        loop    Reset0

;---------------------- failed 5 times - halt
; - - - Display 'F' character - - -
; - - - to show the failure occured.

        mov     ax,0B800h
        mov     es,ax
        mov     DI,4    ; Move a bit to avoid the 'A',
        mov     ax,9C46h; 9C attribute should be ugly.
        stosw

Halt0:  HLT
        jmp     Halt0

;---------------------- execute the bootloader code

Exec0:
        db      0EAh            ;JMP FAR instruction
        dw      LoadOfs         ;offset
        dw      LoadSeg         ;segment


;---------------------- boot sector signature

        ORG     1FEh

        dw      0AA55h

;----------------------------------------------------------------------------------

        END     Boot0
Title: Re: Memory Map
Post by: zak100 on June 19, 2010, 06:14:41 PM
Hi,
Thanks for your help. The boot sector code is working. But my kernel is still showing only the base address & region length of only the first region. I posted its (kernel) code on June 14, 2010. Can somebody please guide me with this?

Zulfi.
Title: Re: Memory Map
Post by: sinsi on June 19, 2010, 11:02:21 PM

e8201p:
        mov eax, 0e820h
        mov dword ptr es:[di + 20], 1
        mov ecx, 24
        int 24h

int 24h? Maybe try int 15h.
Title: Re: Memory Map
Post by: zak100 on June 20, 2010, 06:03:41 PM
Hi,
Thanks for your help sinsi. In my opinion it should work but now I am not even getting the base address and length of 1st region. However I am getting 'A' and all the string messages. Kindly provide me more guidance on this.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 20, 2010, 06:42:33 PM
Hi,

Quote from: zak100 on June 19, 2010, 06:14:41 PM
Thanks for your help. The boot sector code is working. But my kernel is still showing only the base address & region length of only the first region. I posted its (kernel) code on June 14, 2010. Can somebody please guide me with this?

   Well, one of the things you should do is preserve the contents of
EBX to do another Int 15H.  The 0E820H function wants the value
it returned from the last call to allow it to get the next region.  The
OSDev Wiki code does this, but your printing the values changes
it.  That code was intended to store all the regions and let the user
process them afterwards.  And in debugging the code I found that
you can get very strange errors sometimes if you have an invalid
value in EBX.

   MichaelW's MemMap code process each region after the interrupt,
like you are doing.  So you may want to look at his code to see how
and where he uses EBX.  I am using the Wiki code as you started
with, but process all the regions afterward.  This lets me sort the
entries as suggested in the Wiki article.  A bit of warning, if you store
the values in an array, you should count the regions returned so you
don't overflow your array.  That was messy on one of my machines.

   Just to show the effect of the sort, I'll post the output of my program
and MichaelW's.

Regards,

Steve N.


SRN's MemTest

   Memory Map returned by system interrupt 15H Function E820H:

      Base       Length   Usable Size    Type
    00000000    0009FC00      654336    Usable (normal) RAM.
    0009FC00    00000400           0    Reserved, not available.
    000F0000    00010000           0    Reserved, not available.
    00100000    0FEF0000   267321344    Usable (normal) RAM.
    0FFF0000    00003000           0    ACPI NVS memory.
    0FFF3000    0000D000           0    ACPI reclaimable memory.
    FFFF0000    00010000           0    Reserved, not available.
    --------    --------  -----------
    Total Usable Memory:   267975680

MichaelW's MemMap.exe

Memory Map returned by Interrupt 15h Function E820h:

BASE=00000000h LENGTH=0009FC00h (654336)TYPE=AVAILABLE
BASE=0009FC00h LENGTH=00000400h (1024)TYPE=RESERVED
BASE=000F0000h LENGTH=00010000h (65536)TYPE=RESERVED
BASE=FFFF0000h LENGTH=00010000h (65536)TYPE=RESERVED
BASE=00100000h LENGTH=0FEF0000h (267321344)TYPE=AVAILABLE
BASE=0FFF3000h LENGTH=0000D000h (53248)TYPE=ACPI_RECLAIM
------------------------------------------------------------
TOTAL LENGTH          0FFBD000h (268161024)

Extended Memory size returned by Interrupt 15h Function 88h = 0 bytes

Extended Memory size from CMOS RAM = 67043328 bytes

Press any normal key to exit...
Title: Re: Memory Map
Post by: zak100 on June 21, 2010, 06:05:00 PM
Hi,
I tried to search MichealW's code on this forum but I am not lucky in this regard. Can you people provide me a link for his code?

Zulfi.
Title: Re: Memory Map
Post by: MichaelW on June 21, 2010, 06:58:27 PM
Do you mean this?:

http://www.masm32.com/board/index.php?topic=7679.msg56497#msg56497

Title: Re: Memory Map
Post by: zak100 on June 25, 2010, 03:03:46 AM
Hi,
Thanks MichealW.
Quote
Well, one of the things you should do is preserve the contents of
EBX to do another Int 15H.
I have checked this code but I didnt see any explicit instruction for preserving ebx.

xor   ebx, ebx
  callLoop:
    mov   eax, 0e820h
    mov   edx, 'SMAP'
    mov   ecx, SIZEOF smmard
    ; Set DI to the offset address of smmard.
    mov   di, OFFSET smmard
    int   15h
    ; Preserve CF for later test.
    pushf
    .IF eax != 'SMAP'
      popf
      print NL,"Interrupt 15h Function E820h not supported or not available.",NL,NL
      jmp   callFunction88h
    .ENDIF
    ; The function may indicate that the last range
    ; has been returned by setting the carry flag
    ; or by returning zero in EBX.
    popf
    jc    finish
    test  ebx, ebx
    jz    finish

    print NL,"BASE=",hexdword$(smmard.baseLo),"h "
    print "LENGTH=",hexdword$(smmard.lengthLo),"h "
    print chr$(40),dword$(smmard.lengthLo),chr$(41)
    loc ,44
    print "TYPE="
    .IF smmard.rangeType == RT_AVAILABLE
      print "AVAILABLE"
    .ELSEIF smmard.rangeType == RT_RESERVED
      print "RESERVED"
    .ELSEIF smmard.rangeType == RT_ACPI_RECLAIM
      print "ACPI_RECLAIM"
    .ELSEIF smmard.rangeType == RT_ACPI_NVS
      print "ACPI_NVS"
    .ENDIF

    ; Update the total length.
    mov   eax,smmard.lengthLo
    add   memTotal,eax

    jmp   callLoop



In my code I have tried to preserve ebx by saving it in a variable
storeEBX and later on I am retrieving its value but its not
working. Since I have put my memory map code in a loop, its not
displaying any base address. Earlier it was printing one base address
and its length.


;//portion of memMap code from original file sect8_2.asm
;//Updated by Steve :masm forum

;"Solved the prob of backward printing of the length of region"
;Beyond memMp3: printing the base address & pause & then the offset at different locations
;               both visible
;               using arguments for print_mesg macro e.g:
; print_mesg MyArg, ScrCoord, 16;
;               Entire code of MemMap: Printing the base address and length in a loop
;-------------------------------------------------------------
;ml /c memMp4.asm
;link16 /tiny memMp4.obj,memMp4.bin;
;DEBUG btl5.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp4.BIN
;-w 100 0 1 2
;-q

.MODEL  TINY
.386

print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
       push    ax
       mov     ax,xlat0
       push    ax
       retf


;display the message at B800:50h

xlat0: mov     ax,0B800h     
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm



.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h

   
;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
       
;---------------------- done - halt; NOT A CLK PROG
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgAloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        ;jz RTime
        jz mem
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop
        mov cx, 1000
;DISPLAY_TIMER:
;-------------Find Total Memory
mem:        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
msgA db 'Total minutes elapsed since Kernel start is',0
clkcounter db 0
secs db 0
mins db 0
hrs  db 0
cnt  db 0; Its value represents the digits of Timer
s    db 0; selector for secs minutes and hrs used in displayCnt
arr  db 16 dup(0)
VAL1 db 0
VAL2 db 0
ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region length
                ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Macro argument
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MyArg   EQU     <offset arr+LoadOfs>
storeEBX  dq 0 ;<<<<<<<<<<<<<<<<<<<<------------------------------------

       
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
        mov storeEBX, ebx;<<<<<<<<<<<<<<<<<<<<<-----------------------------
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
jmp short jmpin
e8201p:
        mov ebx, storeEBX;<<<<<<<<<<<<<<<<---------------------------
        mov eax, 0e820h
        mov dword ptr es:[di + 20], 1
        mov ecx, 24
        int 15h
        jc short e820f
        mov edx, 0534D4150h
jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length; i.e from 8 to 11
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];i.e from 12 to 15
        jecxz skipent
goodent:
        inc bp
        ;---------------------------    ;NOTE QW2HEX$ converts to Hex & prints using Macro
                 
        call QW2Hex$            ;Displaying the base address
       
;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H
       
        push di
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di
        call QW2Hex$            ;Displaying the length of region 
        pop di
        add di, 24
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
jne short e8201p
     
;-------------------------
       
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
                        ; When called 1st DI=0. Now DI =7. So print from 7 to 0. So it pints the Base address
                        ; When called 2nd time DI=8. After adding DI=15. So it prints the length of region

        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;---------------------------Calling Macro with the screen coordinates
       
        ;print_mesg MyArg, 50h, 16;
        print_mesg MyArg, ScrCoord, 16;<------------------
        nextval: lodsb
                 stosw
        loop nextval
       
        POP     ES
        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



;----------------------------------------------------------------------------------

        END     Start





Kindly help me in this regard.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 25, 2010, 04:00:16 PM
Hi,

   The code of yours that I got working (for one entry) was from
Reply #76.  You have moved some code around since then.  The
the code that prints the results in particular.  The code in the first
posting has the "cure" for the current problem.  (I think.)  The
problem (on my machine) is currently with this code.


cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short skipent


   On my machine it now takes the jump (not 24 bytes).  So you
need something like this logic from the first posting.

cmp cl, 20  ; got a 24 byte ACPI 3.X response?
jbe short .notext


   That way you can process ACPI that predates the 3.x speci-
fication.

Regards,

Steve
Title: Re: Memory Map
Post by: zak100 on June 26, 2010, 06:17:51 PM
Hi Steve,
Thanks for your help. I have added the notext code which you told me. Its now showing the 1st region and its length. But its not showing beyond that. Kindly guide me with this problem,



;ml /c memMp5.asm
;link16 /tiny memMp5.obj,memMp5.bin;
;DEBUG btl5.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp5.BIN
;-w 100 0 1 2
;-q

.MODEL  TINY
.386

print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
       push    ax
       mov     ax,xlat0
       push    ax
       retf


;display the message at B800:50h

xlat0: mov     ax,0B800h     
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm



.CODE

;----------------------------------------------------------------------------------

LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

;---------------------- initialize ES segment register

        ORG     0

Start:  push    cs
        pop     ds
       
;-----------clear screen
mov ax, 3
int 10h

   
;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
       
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz TimerMesg
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgloop
       
;---------------------- done - halt; NOT A CLK PROG
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
       mov ah, 41h; attribute byte
       cld;
msgAloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        ;jz RTime
        jz mem
        stosw; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop
        mov cx, 1000
;DISPLAY_TIMER:
;-------------Find Total Memory
mem:        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0: hlt
jmp     Halt0


Msg0    db      "We be bootin234!",0
msgA db 'Total minutes elapsed since Kernel start is',0
clkcounter db 0
secs db 0
mins db 0
hrs  db 0
cnt  db 0; Its value represents the digits of Timer
s    db 0; selector for secs minutes and hrs used in displayCnt
arr  db 16 dup(0)
VAL1 db 0
VAL2 db 0
ScrCoord dw 50h ;dx stores the screen location for displaying Base address & region length
                ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Macro argument
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw ?
end_of_list db 1
MyArg   EQU     <offset arr+LoadOfs>
storeEBX  dd 0   ; 32 bits

       
MMap_Descriptor STRUCT
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DW      ?       ; * Next dword = Region "type"
  ACPI_Attrib   DW      ?       ; * Next dword = ACPI 3.0 Extended Attri
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>


;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx,0534D4150h ; Place "SMAP" into edx
mov eax, 0e820h
mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                ;dword to 1 before each call
mov ecx, 24 ; ask for 24 bytes
int 15h
        mov storeEBX, ebx
jc short failed         ; carry set on first call means "unsupported function"
mov edx, 0534D4150h ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short failed
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short failed
jmp short jmpin
e8201p:
        mov ebx, storeEBX
        mov eax, 0e820h
        mov dword ptr es:[di + 20], 1
        mov ecx, 24
        int 15h
        jc short e820f
        mov edx, 0534D4150h
jmpin:
jcxz skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short notext
test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if the entire
                                ; entry should be ignored
je short skipent
notext:
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length; i.e from 8 to 11
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12];i.e from 12 to 15
        jecxz skipent
goodent:
        inc bp
        ;---------------------------    ;NOTE QW2HEX$ converts to Hex & prints using Macro
                 
        call QW2Hex$            ;Displaying the base address
       
;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H
       
        push di
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di
        call QW2Hex$            ;Displaying the length of region 
        pop di
        add di, 24
         
skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
jne short e8201p
     
;-------------------------
       
e820f:
mov mmap_ent, bp ; store the entry count
        pop es
        ret

failed:
stc ; "function unsupported" error exit
        pop es
ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
                        ; When called 1st DI=0. Now DI =7. So print from 7 to 0. So it pints the Base address
                        ; When called 2nd time DI=8. After adding DI=15. So it prints the length of region

        mov si ,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI
       
        CALL TOASCII    ; Display as hex.
        mov  dl, VAL1
        mov  [si], dl   ; store the values in array and display array later
        inc si
        mov  dl, VAL2
        mov  [si], dl
        inc si
        LOOP    QW_1
;---------------------------Calling Macro with the screen coordinates
       
        ;print_mesg MyArg, 50h, 16;
        print_mesg MyArg, ScrCoord, 16;<------------------
        nextval: lodsb
                 stosw
        loop nextval
       
        POP     ES
        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



;----------------------------------------------------------------------------------

        END     Start





Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 27, 2010, 04:56:13 PM
Hi Zulfi,

   Okay.  I went and tried to follow what you were trying to do
and minimally fix it up.  It is (more or less) working now (for me).
I can see if you need to reboot for each change, it would take
a while to progress.  You should be able to clean things up from
here I think.  A bunch of changes were only reformatting, as I
looked at the code.  That was only to help me debug things
quicker.  Look for ## marking most of the real changes.  And
if something does not make sense to you, ask, I may have
torpedoed it.

   Tested as both a separate boot and as a DOS COM program.
If in doubt, hit a key...  Enjoy!

HTH,

Steve N.


        PAGE ,132
; DeadNDave/Zulfi/zak100 code from 26 June 2010, MASM32 forum.
; 27 June 2010, Mods by FORTRANS/Steve N. {Idiosyncratic formatting & fixes.}
; Look for ##.

;ml /c memMp5.asm
;link16 /tiny memMp5.obj,memMp5.bin;
;DEBUG btl5.BIN
;-w 100 0 0 1
;-q

;DEBUG memMp5.BIN
;-w 100 0 1 2
;-q

.MODEL  TINY
.386

print_mesg macro offsetStr, offsetScr, msgSize
       LOCAL xlat0

       mov     ax,cs
       mov     ds,ax
;       push    ax       ; ## ??
;       mov     ax,xlat0
;       push    ax
;       retf

;display the message at B800:50h

xlat0: mov     ax,0B800h
       mov     es,ax
       mov     di, offsetScr
       mov     si, offsetStr
       cld
       mov     ah,1Fh
       mov     cx,msgSize
endm

DOSish  EQU     0       ; ## EQUate = 1 to use DEBUG in a VDM, 0 = BootLoader...

.CODE

;----------------------------------------------------------------------------------
;IF DOSish?  Okay, what was Dave doing? ##?
LoadOfs EQU     0               ;must match the value in the bootloader source file
LoadSeg EQU     1000h

;----------------------------------------------------------------------------------

IF DOSish               ; ## DEBUGing?
        ORG     100H    ; DOS COM file load point.
ELSE
        ORG     0       ; deadndave load point.
ENDIF

;---------------------- initialize DS segment register
Start:  push    cs
        pop     ds

;-----------clear screen
        mov ax, 3
        int 10h

;---------------------- writing a message on screen at startup, character by character- we can't use int 21h
overdata:
        xor di, di
        mov ax, 0B800h
        mov es, ax
        mov si, offset msg0+LoadOfs
        mov ah, 41h ; attribute byte
        cld
msgloop:
        lodsb; loads al with a byte of data pted by ds:si
        or al, al
        jz SHORT TimerMesg
        stosw ; transfers the contents of al to mem location ptd by ES:DI
        jmp msgloop

;---------------------- done - halt; NOT A CLK PROG
TimerMesg:

        xor di, di
        mov ax, 0B820h
        mov es, ax
        mov si, offset msgA+LoadOfs
        mov ah, 41h ; attribute byte
        cld
msgAloop:
        lodsb ; loads al with a byte of data pted by DS:SI
        or al, al
        ;jz RTime
        jz SHORT mem
        stosw ; transfers the contents of al to mem location ptd by es:di
        jmp msgAloop

;DISPLAY_TIMER:
;-------------Find Total Memory
mem:
        cld
        ;call    FindTotalMem    ;calculate total memory (sets the SI register)
        mov     ah,7            ;display attribute
        mov     di,0            ;display position
        ;call    Dsply           ;display total memory
        call do_e820_Step1
        ;call Qw2Hex by Dave (instead using code provided by Fortran or Steve)

Halt0:
IF DOSish
        MOV     AH,04CH ; DOS 2+ Exit.
        INT     21H
ELSE
        HLT
        JMP     Halt0
ENDIF


Msg0    db      "We be bootin234!",0
msgA    db      'Total minutes elapsed since Kernel start is',0
clkcounter db   0
secs    db      0
mins    db      0
hrs     db      0
cnt     db      0 ; Its value represents the digits of Timer
s       db      0 ; selector for secs minutes and hrs used in displayCnt
arr     db      16 dup(0)
VAL1    db      0
VAL2    db      0
ScrCoord dw     50h ; dx stores the screen location for displaying Base address & region length
                ; Macro argument
AscBuf  db      8 dup (0),' Kb Total Memory',0
mmap_ent dw     ?
end_of_list db  1
MyArg   EQU     <offset arr+LoadOfs>
storeEBX dd     0   ; 32 bits

MMap_Descriptor STRUC           ; Old MASM
  BaseAddress   DQ      ?       ; * First qword = Base address
  ByteLength    DQ      ?       ; * Second qword = Length of "region"
  RangeType     DD      ?       ; * Next dword = Region "type" ##
  ACPI_Attrib   DD      ?       ; * Next dword = ACPI 3.0 Extended Attri ##
MMap_Descriptor ENDS

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>

;---------------do_e820_Step1
do_e820_Step1:
        push es
        push cs
        pop es
        mov di, offset call15_1+LoadOfs
        xor ebx, ebx ; ebx must be 0 to start
        xor bp, bp ; keep an entry count in bp
        mov edx,0534D4150h ; Place "SMAP" into edx
        mov eax, 0e820h
        mov dword ptr es:[di + 20],  1 ; force a valid ACPI 3.X entry. This reqd to set last
                                       ;dword to 1 before each call
        mov ecx, 24 ; ask for 24 bytes
        int 15h
        mov storeEBX, ebx
        jc failed               ;## carry set on first call means "unsupported function"
        mov edx, 0534D4150h     ; Some BIOSes apparently trash this register?
        cmp eax, edx            ; on success, eax must have been reset to "SMAP"
        jne failed              ; ## as above, now is out of range...
        test ebx, ebx           ; ebx = 0 implies list is only 1 entry long (worthless)
        je failed               ; ## as above, now is out of range...
        jmp short jmpin
e8201p:
        CMP     BP,5            ;## Oh yeah.  Prevent buffer overflow.
        JAE     E820F

        mov ebx, storeEBX
        MOV     EDX,0534D4150H  ; ## Place "SMAP" into EDX
        mov eax, 0e820h
        mov dword ptr es:[di + 20], 1
        mov ecx, 24
        int 15h
        jc short e820f
        MOV     [storeEBX],EBX  ; ##
        mov edx, 0534D4150h
jmpin:
        jcxz skipent    ; skip any 0 length entries
        cmp cl, 20      ; got a 24 byte ACPI 3.X response?
        jbe short notext
        test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if
                                ; the entire entry should be ignored
        je short skipent
notext:
        mov ecx, dword ptr es:[di+8]; get lower dword of memory region length; i.e from 8 to 11
        test ecx, ecx;          ; is the qword=0????
        jne short goodent
        mov ecx, dword ptr es:[di+12] ; i.e from 12 to 15
        jecxz skipent
goodent:
        inc     bp
;---    ;NOTE QW2HEX$ converts to Hex & prints using Macro

        call QW2Hex$            ;Displaying the base address
        ADD     [ScrCoord],40   ; ## Move print region.

;## You are not pausing after showing the first value before showing the second.
;## And they both print at the same location on screen.
        MOV     AX,0    ;## Pause?
        INT     16H

        push di
        add di, 8               ;Length of region starts 15 bytes from current val
                                ;In the procedure we adding 7 to di
        call QW2Hex$            ;Displaying the length of region
        pop di
        add di, 24
        ADD     [ScrCoord],120  ; ## Move print region.
skipent:
        test ebx, ebx ; if ebx resets to 0, list is complete
        jne short e8201p

;-------------------------

e820f:
        mov mmap_ent, bp ; store the entry count
        pop es
        CLC
        ret

failed:
        stc ; "function unsupported" error exit
        pop es
        ret

QW2Hex$:
        PUSH    DI      ; Save registers used by routine.
        PUSH    AX
        PUSH    CX
        PUSH    ES

        STD             ; String instructions decrement.

        ADD     DI,7    ; Point to last byte, (Intel big end).
                        ; When called 1st DI=0.  Now DI=7.  So print from 7 to 0. So it prints the Base address
                        ; When called 2nd time DI=8.  After adding DI=15.  So it prints the length of region

        mov     si,offset arr+LoadOfs
        MOV     CX,8    ; Number of bytes to print. QWORD = 8 bytes
                        ;
QW_1:
        MOV     AL,ES:[DI]      ; Get a byte
        DEC     DI

        CALL TOASCII    ; Display as hex.
        mov     dl, VAL1
        mov     [si], dl        ; store the values in array and display array later
        inc     si
        mov     dl, VAL2
        mov     [si], dl
        inc     si
        LOOP    QW_1
;--- Calling Macro with the screen coordinates

        ;print_mesg MyArg, 50h, 16;
        print_mesg MyArg, ScrCoord, 16;<------------------
nextval: lodsb
        stosw
        loop nextval

        POP     ES
        POP     CX
        POP     AX
        POP     DI

        RET
;---------------------------------------------------
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;    This routine converts the one byte binary number in the
; AL register into its hexadecimal ASCII representation and
; prints these two bytes to the standard output or console.
; 4 March 2010,
;   Changed TOASCII routine to use AAM varient instead of MOV,
; AND, and SHR codes on nybbles.

TOASCII:
        PUSH    AX      ; Make safer for debugging.
        PUSH    DX

        XOR     AH,AH   ; Clear AH for AAM using base 16.
DB      0D4H, 10H       ; Isolates high nybble in AH and low
                        ; nybble in AL.
        PUSH    AX      ; Save low nybble.
        MOV     AL,AH   ; And process high digit first.

        CMP     AL,10   ; Convert to ASCII hex using "magic".
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL1, al
        ;CALL ConOutByte ; DOS Fn 2 or BIOS 10H Fn 0EH (or whatever).

        POP     AX      ; Retrieve low digit in AL.

        CMP     AL,10   ; Convert to ASCII hex.
        SBB     AL,69H
        DAS

        MOV     DL,AL
        mov     VAL2,al
;        CALL ConOutByte

        POP     DX
        POP     AX

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

;----------------------------------------------------------------------------------

        END     Start
Title: Re: Memory Map
Post by: zak100 on June 27, 2010, 05:48:33 PM
Hi,
Thanks for your reply. I have not yet tested it but just to inform you that I am about to start working on it, I am writing this. I have made a quick look at it and I am not to able to digest the indirect addressing with storeEBX.
There maybe other Qs which I would ask you once I have gone through the code thoroughly.

Thanks for making it workable and signifying the changes.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 27, 2010, 06:08:16 PM
Hi,

   It is not indirect addressing.  It is part of my idiosyncratic
formatting that I warned about.


        MOV     [storeEBX],EBX
        mov storeEBX, ebx


   These produce the exact same code.  I like using the brackets
to indicate storage to a variable.  Some assemblers do produce
different code for the above (i.e. NASM).  But not MASM.  Just
my habit.

Regards,

Steve N.
Title: Re: Memory Map
Post by: zak100 on June 28, 2010, 02:36:27 AM
Hi Steve,
Thanks for this explanation.

Zulfi.
Title: Re: Memory Map
Post by: zak100 on June 29, 2010, 05:50:07 PM
Hi,
Thanks Steve. Its working now. I got following 5 regions with base addresses and lengths:
0000 0000 0000 0000         0000 0000 0009 F400
0000 0000 0009 F400         0000 0000 0000 0C00   
0000 0000 000F 0000         0000 0000 0001 0000   
0000 0000 0010 0000         0000 0000 1F5E 0000   
0000 0000 1F6E 0000         0000 0000 0000 3000   


Thanks for formatting.
Let me know about the correctness of this result.
Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 29, 2010, 08:21:12 PM
Hi,

   Glad it works for you.  Your results look good as well.  But
when I compare that to some of my computers, it looks as
if you should alter the program to print out more memory
blocks.  If you look at the six or seven regions in Reply #102,
you will see a region starting at FFFF 0000 and the same
length as the block at 000F 0000.  Those should be the
computer's BIOS regions.  You are not showing both of
those regions yet.  You could look at the results there
to see what else you mayl want your program to print out

Cheers,

Steve N.
Title: Re: Memory Map
Post by: zak100 on June 30, 2010, 05:41:17 PM
Hi,
Thanks Steve for guiding me upto this point and for pointing out the regions not being printed. I would try to look at this problem first before going into the details of other stuff shown in those sample printouts (reply#102). Right now I have no clue why those regions were left out.

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on June 30, 2010, 10:03:58 PM
Hi,

   They were left out as you only defined five buffers for
the data returned by the interrupt.  If you call that
interrupt more than that, you crash the program as you
overwrite the executing progam.  (Quick guess how I
found that out.)  I then put in a test to prevent that
from happening.


        CMP     BP,5            ;## Oh yeah.  Prevent buffer overflow.
        JAE     E820F


Regards,

Steve N.
Title: Re: Memory Map
Post by: zak100 on July 06, 2010, 06:35:34 PM
Hi Steve,
I am now getting following 9 regions:
0000 0000 0000 0000         0000 0000 0009 F400
0000 0000 0009 F400         0000 0000 0000 0C00   
0000 0000 000F 0000         0000 0000 0001 0000   
0000 0000 0010 0000         0000 0000 1F5E 0000   
0000 0000 1F6E 0000         0000 0000 0000 3000   
0000 0000 1F6E 3000         0000 0000 0000 D000
0000 0000 1F6F 0000         0000 0000 0001 0000
0000 0000 E000 0000         0000 0000 0800 0000
0000 0000 FEC0 0000                      0000 0000 0140 0000


I cant see the BIOS region.
I tried with 12 buffers:

Call15_1        MMap_Descriptor <>      ; Set DI to point to the first one, and
Call15_2        MMap_Descriptor <>      ; increment by 24  to point to second.
Call15_3        MMap_Descriptor <>
Call15_4        MMap_Descriptor <>
Call15_5        MMap_Descriptor <>
call15_6        MMap_Descriptor <>
call15_7        MMap_Descriptor <>
call15_8        MMap_Descriptor <>
call15_9        MMap_Descriptor <>
call15_0        MMap_Descriptor <>
call15_A        MMap_Descriptor <>
call15_B        MMap_Descriptor <>


and the comparison code is given below:



CMP     BP,12           ;## Oh yeah.  Prevent buffer overflow.
                               ;Total buffers=8, last one is:   
                               ;call15_8        MMap_Descriptor <>
        JAE     E820F


But its not going beyond 9. Is it the maximum number of regions??
My other prob. is non-printing of BIOS regions.
Kindly guide me in this regard. I appreciate your help and guidance.

Zulfi.
Title: Re: Memory Map
Post by: MichaelW on July 06, 2010, 07:25:49 PM
I have not been keeping up with this thread, but on some (probably older) systems the BIOS is duplicated in E block and F block, for example:

BASE=00000000H LENGTH=0009F800 (653312)    TYPE=AVAILABLE
BASE=0009F800H LENGTH=00000800 (2048)      TYPE=RESERVED
BASE=000E0000H LENGTH=00020000 (131072)    TYPE=RESERVED
BASE=00100000H LENGTH=0FF00000 (267386880) TYPE=AVAILABLE


Also, if the goal is to assemble the entire map in memory, it should be possible to count the number of blocks in the first pass, allocate the required memory, then make another pass to read the information into the allocated memory.


Title: Re: Memory Map
Post by: FORTRANS on July 06, 2010, 08:19:03 PM
Hi,

QuoteI cant see the BIOS region.

   Well, you got the one at 000F 000.  All the machines I have
tested have had one at FFFF 0000.  Most of those were older
machines though.  You could put in some checks to see if it
was skipped by the code as it does make some checks.


        test byte ptr es:[di + 20], 1 ; if so: is the "ignore this data" bit clear?
                                ;Bit 0 of the extended Attributes indicates if
                                ; the entire entry should be ignored
        je short skipent


   That seems unlikely, but you could comment out the JE line
and see what happens.

   I have heard of some BIOS'es hiding parts of the BIOS after
it boots up, but have no further information about that.  So if
that is all that are reported, that is probably all there is.

Cheers

Steve
Title: Re: Memory Map
Post by: FORTRANS on July 06, 2010, 09:51:52 PM
Hi,

   Modifying the code to increase the number of records, I got
same seven regions on my machine.  So I think things are
working okay on my machine.

Steve N.
Title: Re: Memory Map
Post by: zak100 on July 07, 2010, 04:50:15 AM
Hi Steve,
Thanks for your reply.
If I am getting 9 regions, is it wrong?

Zulfi.
Title: Re: Memory Map
Post by: FORTRANS on July 07, 2010, 01:26:35 PM
Hi,

   Your results look reasonable.  The program works on my
machine.  So, probably not wrong.

Steve
Title: Re: Memory Map
Post by: zak100 on July 07, 2010, 05:37:51 PM
Hi,
Thanks for your reply. I feel that the number of regions depend upon the amount of memory (RAM). If I have more memory, I can even get more than nine regions???

Zulfi.