So things are quite different in Turbo C. There are different models in
Turbo C. In tiny/small model all variables are in one segment and SS has
the same value with DS. In large data models the variables may locate in
different segments so they may have different DS, and the variables in SS
may have a different segment value. No variables in CS for all models.
1. MOV AX,DS is an alternative method to get the segment value,
it should be correct at least in tiny/small model of Turbo C:
unsigned getDS()
{
asm mov ax,ds
}
main()
{
char a;
printf("Address of a: %4.4X:%4.4X\n", getDS(), &a);
}
you can also use %p to format &a in the printf statement here for tiny and
small models. For large data models, %p gives both the segment and
offset value of a variable, so getDS() is useless.
2. Professionals would say "char a" is not addressed in DS, but in SS.
Yes. strictly, in Turbo C, global variables and local static variables
are in the DATA segment (using DS), others in STACK(SS). For example,
int a, b=0;
foo(int c)
{ static int x=0;
int y=1;
char z[8]="abcdefg";
...
}
a,b,x are in the DATA segment, c, y, z are in the STACK (allocated at
runtime). You will find &c,&y and z have offsets near 0xFFFF, while
&a, &b and &x are rather lower.
But SS has the same value as DS in tiny/small model in Turbo C. So all
the variables are in the same segment in tiny/small model and the above
code should run well.
3. As MisterNobody recommended, FP_SEG(&a) and FP_OFF(&a) always give
the right segment and offset of variable "a" for all models. It's much safer
to use these macros defined in <dos.h>:
#define FP_OFF(fp) ((unsigned)(fp))
#define FP_SEG(fp) ((unsigned)((unsigned long)(fp)>>16))
At the first glance of the macro definitions in dos.h, it seems NG for
tiny/small model, because &a is not a far pointer. However, in the
executable it really gives MOV DX,DS or MOV DX,SS if you assign &a as
the argument; otherwise, if you assign a as the argument, it gives CWD.
i still wonder how the compiler does the macros so clever.
4. les di,[a] puts the word value of a+0 in DI and the word value of
a+2 to ES. so you can get neither the offset nor the segment of the
variable "a".
Example:
int x=0x1234,y=0x5678;
asm les di,[x]
You will get es=0x5678, di=0x1234. Neither the segment nor the offset
of x, but the two successive word values stored at x.
i think, however, it's not very necessary to get the segment value of a
variable. i cannot imagine even what the use of it.
Jennings