Incorrect RAM count with INT 15h

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Kemp

Incorrect RAM count with INT 15h

Post by Kemp »

I am using int 15h to get a quick count of memory as noted in the osfaq, but it doesn't appear to be giving me correct results. Attached is the current output I obtain, which shows there being 300 (hex) KB of memory available. This is 768KB (plus the 1MB that it ignores), whereas I have Bochs set up to use 32MB. Has anyone else had any problems with this? This function can only return an available amount up to about 64MB but as Bochs is set to 32MB I wouldn't see that being a problem. No doubt there will be something stupid wrong with my code, but there honestly isn't very much to it, appropriate excerpts:

Code: Select all

   ; Attempt to count up system memory
   MOV AH, 88h
   INT 15h
   MOV RAMCount, AX
   MOV SI, OFFSET RAMCount
   MOV DI, OFFSET RAMOut
   CALL bin2hex
   MOV SI, OFFSET msgRAMCount
   CALL ShowMsg
   MOV SI, OFFSET RAMOut
   CALL ShowMsg
and

Code: Select all

bin2hex:
   LODSB
   MOV AH, AL
   AND AX, 0000111111110000b
   SHR AL, 4
   ADD AX, 3030h
   STOSB
   LODSB
   MOV AH, AL
   AND AX, 0000111111110000b
   SHR AL, 4
   ADD AX, 3030h
   STOSB
   RETN
(my usual bin2hex routine, anything over 9 gets symbols rather than letters but that isn't occurring here)

Code: Select all

msgRAMCount   DB   'Current system RAM: ', 00h

RAMCount      DW   0000
RAMOut        DB   '0000h KB after 1Mb', 0Dh, 0Ah, 00h
smiddy

Re:Incorrect RAM count with INT 15h

Post by smiddy »

Hi Kemp,

I have written some routines for determining RAM sizes. As you have experienced, not every way to do it is exact. Meaning some way work and others do not, but not on the same machine, as the one's that didn't work before work on another, but the one's that did don't. If that makes sense. I am off to bed now, so I will have to give you screen shot for now of where I am with the project (memory determination; research for my OS):

Code: Select all

GETMEM - 0.17.021E Attempt to see what memory is installed... -smiddy

BIOS:
   15h:
     E820:   Base Address   -  Memory Length    - Type
         : 0000000000000000 - 000000000009FC00h -  01 <<   Available to OS   >>
         : 000000000009FC00 - 0000000000000400h -  02 <<   Reserved Memory   >>
         : 00000000000F0000 - 0000000000010000h -  02 <<   Reserved Memory   >>
         : 0000000000100000 - 0000000027EF0000h -  01 <<   Available to OS   >>
         : 0000000027FF0000 - 0000000000008000h -  03 << ACPI Reclaim Memory >>
         : 0000000027FF8000 - 0000000000008000h -  04 <<   ACPI NVS Memory   >>
         : 00000000FEC00000 - 0000000000001000h -  02 <<   Reserved Memory   >>
         : 00000000FEE00000 - 0000000000001000h -  02 <<   Reserved Memory   >>
         : 00000000FFF80000 - 0000000000080000h -  02 <<   Reserved Memory   >>
         ----------------------------------------------------------------
         : Total Memory     :         27F8FC00h -    670,628,864 bytes.
         ----------------------------------------------------------------
   12h:
         : Lower Memory     :         0009FC00h -        654,336 bytes.
   15h:
     E801: 
         : Extended Memory  :         27EF0000h -    669,974,528 bytes.
         ----------------------------------------------------------------
         : Total Memory     :         27F8FC00h -    670,628,864 bytes.
         ----------------------------------------------------------------
   12h:
         : Lower Memory     :         0009FC00h -        654,336 bytes.
   15h:
     88  :   
         : Extended Memory  :         03FFFC00h -     67,107,840 bytes.
         ----------------------------------------------------------------
         : Total Memory     :         0409F800h -     67,762,176 bytes.
         ----------------------------------------------------------------
CMOS:
         : Lower Memory     :         000A0000h -        655,360 bytes.
         : Extended Memory  :         03FFFC00h -     67,107,840 bytes.
         ----------------------------------------------------------------
         : Total Memory     :         0409FC00h -     67,763,200 bytes.
         ----------------------------------------------------------------
PROBE:
         : Extended Memory  :         27F00000h -    670,040,064 bytes.
         ----------------------------------------------------------------
         : Total Memory     :         27F9FC00h -    670,694,400 bytes.
         ----------------------------------------------------------------
PnP BIOS :   Base Address   -  Memory Length    - Type
         :         00000000 -         0009FC00h -  13 <<   Available to OS   >>
         :         0009FC00 -         00000400h -  10 <<  Read Only Memory   >>
         :         000F0000 -         00010000h -  10 <<  Read Only Memory   >>
         :         00100000 -         27EF0000h -  13 <<   Available to OS   >>
         :         27FF0000 -         00008000h -  10 <<  Read Only Memory   >>
         :         27FF8000 -         00008000h -  10 <<  Read Only Memory   >>
         :         FEC00000 -         00001000h -  10 <<  Read Only Memory   >>
         :         FEE00000 -         00001000h -  10 <<  Read Only Memory   >>
         :         FFF80000 -         00080000h -  10 <<  Read Only Memory   >>
         ----------------------------------------------------------------
         : Total Memory     :         20h -    670,628,864 bytes.
This should make you salivate a bit. There is a posting on BOS where I uploaded the EXE which you can run in Windows, though it doesn't do all the BIOS stuff. It is best to run it in good old DOS: http://bos.asmhackers.net/forum/viewtopic.php?id=64

Enjoy!
QuiTeVexat

Re:Incorrect RAM count with INT 15h

Post by QuiTeVexat »

I think bin2hex is your problem.

For one, it appears you only stosb twice, meaning only two bytes will ever be outputted by bin2hex. For a 16-bit bin2hex conversion, two bytes need to go in, and four need to come out. If you replace stosb with stosw, you'll find that it outputs the right digits, but in the wrong order.

And as you noted, adding 30h won't give you the correct digit if it is above 9. So when you output, you need to check if the digit is above 9, and, if so, add ('A' - 10). And because of this, you need to do loop thru and do each digit individually. So your MOV-AND-SHR-ADD thing isn't going to work for you.

I would rewrite the routine entirely.

I would also like to mention that whenever I've used ah=88h int=15h for memory sizing, my computer with 512MB of RAM would return only 15MB anyway.
AR

Re:Incorrect RAM count with INT 15h

Post by AR »

88h is an old function, I updated the Wiki with a newer function that provides more information.
Kemp

Re:Incorrect RAM count with INT 15h

Post by Kemp »

@Smiddy:
That's a rather convoluted listing ;) I see that your int 15h function 88h is giving you the right value (well... the maximum value it can do).

@QuiTeVexat:
One STOSB for two bytes... ::) Told you there would be some stupid mistake in there. As for the letters being done wrong, this isn't a production function by any stretch of the imagination, I can cope with symbols for now, and it'll be rewritten once I have a couple more bits sorted out.

Edit:
Tested it properly and it now gives me 15Mb as the result, as with you. Time to use a more comprehensive function I think. It's annoying that I now get the values with the first two digits last and vice veras, I also don't see why it should happen. It reads a byte from Address, writes a word to Address2, reads a byte from Address+1, writes a word to Address2+2, how can that go backwards?

Edit2:
No, I see it *slaps head* fool

@AR:
I check that out
Kemp

Re:Incorrect RAM count with INT 15h

Post by Kemp »

Actually no, the more I think about it the less I get why it flips the first and second pairs. Flipping the digits within a pair I can understand, but not the pairs themselves. Demo run:

1) Load 100 in SI
2) Load 200 in DI
3) Call bin2hex
4) Loads a byte from SI (100) and increments
5) Does its thing
6) Stores a word at DI (200) and increments (by 2)
7) Loads a byte from SI (101) and increments
8 ) Does its thing
9) Stores a word at DI (202) and increments (by 2)
10) Returns

It's just the same code twice, the second run doesn't know there has already been a run through. So how does the second word end up before the first one?

Edit:
Modified the bin2hex so it can do a number of any length and tried it with 01234567h, which ended up as '67452301'. I'm thoroughly confused as to how that can go backwards.

And suddenly it hits me... ::) ::) ;D I was thinking in terms of the number I was typing, whereas in the hex dump it's
6745 2301
The whole byte swapping thing really does my head in when I'm not expecting it >:(
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Incorrect RAM count with INT 15h

Post by Solar »

Have you cleared the direction flag?

Anyway:

Code: Select all

   ADD AX, 3030h
...doesn't work for digits >9, since 'A' is 0x41, not 0x3A...

I used an algorithm that processes individual digits (i.e., 4-bit nibbles), masking them to lowest 4 bit and using that value as offset into a "0123456789ABCDEF" string. I admit that it doesn't do any little-endian turning-around at all and prints stuff in big-endian order, but that's what I prefer anyway. Perhaps it gives you an idea. (And I hope I didn't screw up in translating it from AT&T to Intel and adjusting it to your SI / DI needs. ;) )

Code: Select all

_bin2hex:
    MOV AX, [SI]
    MOV SI, hexdigits
    MOV CX, 0x4
_bin2hex_loop:
    ROL AX, 0x4
    MOV BX, AX
    AND BX, BYTE +0x0f
    MOV BX, [BX+SI]
    MOV [DI], BX
    INC DI
    DEC CX
    JNZ _bin2hex_loop

hexdigits db '0123456789ABCDEF'
I'm not sure what ndisasm means with the '+' in front of "0x0f", but I'm sure you do. ;)
Every good solution is obvious once you've found it.
Kemp

Re:Incorrect RAM count with INT 15h

Post by Kemp »

I think I'll switch to something like your lookup table, that's the only clean way I can see to get the letters. In fact, I did implement a lookup table version in my first-stage, but it ended up taking up a bit too much of my little amount of spare space, so I fell back on the symbols version.

I can never tell when the bytes being backwards and stuff is going to be a problem, I just have to try it and see what happens, it's a bit of a blind-spot for me.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Incorrect RAM count with INT 15h

Post by Solar »

To make the above print values "Intel-correctly" (ugh :D ):

Code: Select all

_bin2hex:
    MOV AX, [SI]
    MOV SI, hexdigits
    MOV CX, 0x4
    MOV DX, 0x1
_bin2hex_loop:
    ROR AX, DX
    MOV BX, AX
    AND BX, BYTE +0x0f
    MOV BX, [BX+SI]
    MOV [DI], BX
    INC DI
    DEC CX
    MOV DX, 0x3
    JNZ _bin2hex_loop

hexdigits db '0123456789ABCDEF'
(1 roll-right for first digit, 3 roll-rights on the others.)
Every good solution is obvious once you've found it.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Incorrect RAM count with INT 15h

Post by Solar »

Kemp wrote: I think I'll switch to something like your lookup table, that's the only clean way I can see to get the letters.
Well, you can do:

Code: Select all

    cmp al, 0x3a
    jl xxx; 
    add al, 0x07
xxx:
    cmp ah, 0x3a
    jl yyy;
    add ah, 0x07
But that still leaves you with the NUXI problem you have, and rapidly eats up the space you saved by not using the lookup. ;)
Every good solution is obvious once you've found it.
Kemp

Re:Incorrect RAM count with INT 15h

Post by Kemp »

Weel, I figure I can modify my current code slightly and get something like:

Code: Select all

bin2hex:
  LODSB
  MOV AH, AL
  AND AX, 0000111111110000b
  SHR AL, 4

  MOV BX, OFFSET hexTable
  MOV AL, [BX + AL]
  MOV AH, [BX + AH]

  STOSW
  LOOP bin2hex
  RETN

hexTable DB '0123456789ABCDEF'
(written on-the-fly, so it might be a bit broken)

All I need to do now is fix the whole backwards thing, which I have a plan for.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Incorrect RAM count with INT 15h

Post by Solar »

Kemp wrote: All I need to do now is fix the whole backwards thing, which I have a plan for.
You are aware that your binary constant is of word length, and thus most likely interpreted as low-byte, high-byte as well?
Every good solution is obvious once you've found it.
Kemp

Re:Incorrect RAM count with INT 15h

Post by Kemp »

This works, don't start making me doubt it even more :P each pair of characters that this creates are in the right order (ie, a single run through will give the correct result). I see what you're saying, but I don't mind how the 0000111111110000 is stored in memory as I never write it to or read it from there, it's just applied to the contents of the register.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Incorrect RAM count with INT 15h

Post by Solar »

Just thinking that you might be masking the wrong nibbles... I'd need pen and paper to really figure out what you're doing, and Intel data notation already gives me a headache without worrying about NASM notation... :-D
Every good solution is obvious once you've found it.
Kemp

Re:Incorrect RAM count with INT 15h

Post by Kemp »

It is backwards, but it cancels out the number being read in backwards (if my working out is correct). Also, I'm using TASM, just for extra syntax differences ;D
Post Reply