Page 2 of 2

Posted: Mon Jul 02, 2007 1:14 pm
by Combuster
the part that i dont understand about the macro is well first off its a macro. havn't bothered to understand how they work.
:shock:

A macro is a piece of code where you can fill in the parameters at compile (assemble) time.

if you'd take the macro from above

Code: Select all

macro gdt_entry base,limit,flags  {
   dw   limit and 0xFFFF
   dw   base  and 0xFFFF
   db   (base shr 16)  and 0xFF
   db   flags
   db   ((limit shr 16) and 0xF) or 0xC0
   db   (base shr 24)  and 0xFF 
}

gdt_entry   0x00000000, 0xFFFFF, 10010010b
the first parts defines a macro called gdt_entry that takes three parameters: base, limit, flags. The last line is a macro invocation. It takes the contents of the macro and subtitutes all instances of base with 0x000000000, limit with 0xffff, and flags with 10010010b. the assembler then uses the result instead of the original. So where you see gdt_entry ..., ..., ... the assember sees this:

Code: Select all

   dw   0xFFFFF and 0xFFFF
   dw   0x00000000  and 0xFFFF
   db   (0x00000000 shr 16)  and 0xFF
   db   10010010b
   db   ((0xFFFFF shr 16) and 0xF) or 0xC0
   db   (0x00000000 shr 24)  and 0xFF 
another question i have is the granularity (g).
if im not mistaken the g is 1 bit and is either on or off. if g is set is the max mem 4gigs and if its not is the max 1 gig. or did just just not understand what they were saying at all.
The G bit determines how the limit field should be interpreted. if its set, the limit is multiplied by 4096, if its clear, its multiplied with 1.

a limit of 0xfffff with the G bit set results in a limit of 0xffffffff. if the g bit is clear, the actual limit used will be 0x000fffff. (=1MB)

Posted: Mon Jul 02, 2007 1:24 pm
by hailstorm
First of all, the granularity bit. The granularity is a sort of speaking term.
It means that when the bit is on, the limit is interpreted as a number of pages. When it's off, the limit is interpreted as a number of bytes.
These two segment limits are both equal:
granularity=0, limit=0x1000 (real limit is 4096 bytes)
granularity=1, limit=1 (real limit 4096 bytes).

Second, the macro. Please understand that the parameters of macro are not variables. In these macros, you can't pass ax as a parameter for example, the assembler would not understand and shall start screaming.
The only things that can be passed are numbers. And while declaring a word in the datasegment, you may use bit operators like AND, OR and so on.

About the segment confusion. You're right, people should talk about segments as memory regions, segment registers as, well, you know...

Posted: Mon Jul 02, 2007 1:45 pm
by Combuster
hailstorm wrote:These two segment limits are both equal:
granularity=0, limit=0x1000 (real limit is 4096 bytes)
granularity=1, limit=1 (real limit 4096 bytes).
Not quite. the first allows writes to bytes between 0x0 and 0x1000, the second between 0x0 and 0x1fff. That's because the processor compares below than or equal to the computed limit.

i.e. with granularity off the last byte that can be written = limit (if its 0, you can write exactly one byte: the one at address 0x0)
when its on, the last byte = 4096 * limit + 0xfff. if the limit field = 0, you can access exactly 4096 bytes: 0x0-0xfff

(Intel III, Chapter 4 verse 3)

Posted: Mon Jul 02, 2007 4:22 pm
by Ninjarider
it just got a little brighter in my dark world. i was looking at combustors explanation of macros and noticed it resenbles a sub routine in basic. didn't know about that in a subroutine you can only declare data and use bit peraters.

Posted: Mon Jul 02, 2007 10:33 pm
by Candy
Ninjarider wrote:it just got a little brighter in my dark world. i was looking at combustors explanation of macros and noticed it resenbles a sub routine in basic. didn't know about that in a subroutine you can only declare data and use bit peraters.
Sort of. A macro is literally text substitution, where it replaces the first pattern (with comma-separated things) by the second (replacing each name from the parameter list with the actual textual content of its parameter). That also explains why this works:

Code: Select all

#define SIX 1+5
#define NINE 8+1

int main() {
   printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
}
This expands to 1+5*8+1 (literally), making the computer evaluate 8*5 (=40) + 2 (=42), not 6*9 (=54).

Posted: Tue Jul 03, 2007 12:55 am
by hailstorm
Combuster wrote:
hailstorm wrote:These two segment limits are both equal:
granularity=0, limit=0x1000 (real limit is 4096 bytes)
granularity=1, limit=1 (real limit 4096 bytes).
Not quite. the first allows writes to bytes between 0x0 and 0x1000, the second between 0x0 and 0x1fff. That's because the processor compares below than or equal to the computed limit.

i.e. with granularity off the last byte that can be written = limit (if its 0, you can write exactly one byte: the one at address 0x0)
when its on, the last byte = 4096 * limit + 0xfff. if the limit field = 0, you can access exactly 4096 bytes: 0x0-0xfff

(Intel III, Chapter 4 verse 3)
Yep! You are totally right! How could I be so stupid, I must honestly say that I didn't even realise that 0xfff should be added when the granularity bit is set... Thanks for the info! I am never to old to learn...