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


zak100

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.

FORTRANS

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

MichaelW

The segment would be pushed first, placing it at the higher address and the offset at the lower address.
eschew obfuscation

zak100

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.

zak100

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.

FORTRANS

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.

MichaelW

Japheth's DOS Debug clone can handle instruction sets through the Pentium Pro.

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

eschew obfuscation

zak100

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.

dedndave

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

zak100

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.

dedndave

i bet Steve or Michael can tell you how to set up a floppy for debugging (hint hint)

FORTRANS

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

dedndave

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

FORTRANS

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.