Hello list, I just recently answered a question about this, it is at https://stackoverflow.com/questions/22409680/interrupt-21-h-function-31-h-dx-value/57762787#57762787
Quoting the relevant part not mentioned in this thread yet: > Another issue is that the calculation can be done at build > time instead of at run time. That is too arcane for most > programs, indicated by the fact that the mov \ shr > combination is fairly common in 86-DOS programs. It may > need some tricky handling, depending on the assembler. > Here's an answer to a different question, with an example > of build-time calculation written for NASM: > > https://stackoverflow.com/a/57762635/738287 > To calculate the size of your resident process, use NASM > labels. To allow shift (or divide) operations needed to > figure out a length in paragraphs, only use deltas of > labels. A delta (difference) is a scalar value to NASM, > so can be used in calculations. A (non-struc) label alone > is not a scalar. > The size calculation computes the delta of two labels, [...] > adds 15 to make the shift-division round up, then shifts down > into an amount of paragraphs. Regards, ecm On at 2019-09-21 16:53 +0800, TK Chia wrote: > Hello Quinton, > > In case you are not already aware: the 16-bit x86 uses segment:offset > pairs for memory addresses, where a 16-bit segment and 16-bit offset is > combined to allow about 1 MiB of memory to be addressed: > > PhysicalAddress = Segment * 16 + Offset > > (see https://wiki.osdev.org/Real_Mode). This is why counting 16-byte > paragraphs is something that figures quite a lot in 16-bit code. > > Thank you! > > On 9/21/19 16:38, TK Chia wrote: >> Hello Quinton, hello Mark, >> >> I am looking at (I believe) a slightly more recent version of the >> FreeDOS kernel source code (https://github.com/FDOS/kernel), but I think >> the same reasoning applies. >> >> Basically the kernel is trying at this point to move its IGROUP >> (initialization code), I_GROUP (initialization data), and (I think) >> HMA_TEXT, to the top of conventional memory. Before doing that, it >> needs to calculate a memory address where it can move IGROUP, I_GROUP, >> and HMA_TEXT to. >> >> int 12h ; move init text+data to higher memory >> mov cl,6 >> shl ax,cl ; convert kb to para >> >> The BIOS's int 0x12 returns the amount of conventional memory in ax, as >> a Kbyte count (e.g. 640). By multiplying by 1,024 / 16 = 64, we can >> converts this to a count of 16-byte paragraphs. For 640 KiB of >> conventional memory, this will be 0xa000. >> >> Conventional memory starts at real mode address 0:0, so the paragraph >> count also gives the real mode segment base of the _top_ of conventional >> memory --- 0xa000:0. >> >> mov dx,15 + INITSIZE >> mov cl,4 >> shr dx,cl >> >> This tries to calculate the number of paragraphs needed by the I_GROUP >> (initialization data) segment. >> >> The init_end symbol marks the end of the whole I_GROUP segment. >> However, it may not be placed at a 16-byte-aligned address --- it is >> defined in the IB_E segment, and the linker will place IB_E's contents >> into I_GROUP output after other input segments that contribute to >> I_GROUP (ID_B, ID, ID_E, IC, etc.). >> >> So to get the correct number of paragraphs, the kernel needs to round >> _up_ the address of init_end when dividing it by 16, which is why it >> adds 15 first. Without adding 15, a `shr' by 4 will instead round down >> the address of init_end, which will not be correct. >> >> sub ax,dx >> >> ax from the earlier `int 12h' holds the address of the top of >> conventional memory. By subtracting the number of paragraphs needed by >> the I_GROUP segment, the kernel can get the address of a memory area >> near the conventional memory top where it can move I_GROUP to. >> >> I hope this helps a bit. Thank you! >> >> On 9/21/19 10:52, Mark Olesen wrote: >>> Howdy, >>> >>> Your aligning by 16 byte paragraph >>> >>> On Fri, Sep 20, 2019 at 7:45 PM Quinton Cook <quinton.c...@gmail.com> >>> wrote: >>> >>>> Hello all, >>>> >>>> I have recently taken an academic interest in the freedos project. My >>>> current goal is to understand how the kernel was implemented. >>>> >>>> While reading the kernel.asm file located >>>> in freedos-svn/kernel/branches/jhall/kernel I have inferred that the >>>> routine "kernel_start" is calculating the overall memory available to >>>> the >>>> system. but I came across a snippet of code that confused me. >>>> Starting on >>>> line 128 >>>> it goes >>>> >>>> mov dx,init_end+15 >>>> mov cl,4 >>>> shr dx,cl >>>> sub ax,dx >>>> >>>> why is 15 added to the end of the address of the symbol init_end if you >>>> just shift the value right by 4, doesn't that just undo the addition? >>>> Is it >>>> related to memory addresses having to be divisible by 16? >>>> Segmentation or >>>> something like that? >>>> >>>> Also is that last sub calculating the amount of room needed for the >>>> kernel? >>>> >>>> I hope all is well and get back to me when it is convenient for you, >>>> thanks >>>> -- >>>> *Quinton Cook* >>>> _______________________________________________ >>>> Freedos-devel mailing list >>>> Freedos-devel@lists.sourceforge.net >>>> https://lists.sourceforge.net/lists/listinfo/freedos-devel >>>> >>> >>> >>> >>> _______________________________________________ >>> Freedos-devel mailing list >>> Freedos-devel@lists.sourceforge.net >>> https://lists.sourceforge.net/lists/listinfo/freedos-devel >>> >> >> >> >> _______________________________________________ >> Freedos-devel mailing list >> Freedos-devel@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/freedos-devel >> > > > > _______________________________________________ > Freedos-devel mailing list > Freedos-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/freedos-devel _______________________________________________ Freedos-devel mailing list Freedos-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/freedos-devel