News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Memory Map

Started by zak100, February 19, 2010, 06:21:07 PM

Previous topic - Next topic

zak100

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.

FORTRANS

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

zak100

Hi,

Thanks for your reply. Its clear to me now.

Zulfi.

zak100

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.

dedndave

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

zak100

Thanks.

Its my fault but I have learned something new.

Zulfi.

zak100

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.

FORTRANS

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.

zak100

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.

FORTRANS

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.

zak100

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.

FORTRANS

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.

FORTRANS

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.

zak100

Yes, it helped. I would also try Debug.

Thanks.

Zulfi.

FORTRANS

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