/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Allokering af hukommelse til variable/data
Fra : Preben


Dato : 11-02-04 15:14

Hej alle

For at være ærlig har jeg ikke den store erfaring med C - faktisk
ingen, kun arbejdet med assembler og java. Men nu forholder det sig
sådan at vi sidder nogle i en projektgruppe og skal lave et
operativ-system til en 186 embedded processor.

Nå, men spørgsmålet lyder altså, hvordan allokeres hukommelse til
variable? Lægges disse på stacken eller allokeres der hukommelse vha.
operativsystemet? Hvis det gøres vha. operativsystem - hvordan med
parameteroverførsel osv?

Hvad angår data-område? Her må operativsystemet skulle angive, hvor
data-området er i hukommelsen? Hvordan er denne parameteroverførsel
fra/til operativsystem?


Mvh / Preben & projektgruppe

 
 
Mogens Hansen (11-02-2004)
Kommentar
Fra : Mogens Hansen


Dato : 11-02-04 16:01


"Preben" <preben@cyberserver.dk> wrote:

[8<8<8<]
> Nå, men spørgsmålet lyder altså, hvordan allokeres hukommelse til
> variable?

Variable kan i C og C++ allokeres 3 steder:
1. statiks (globale variable)
2. automatisk (på stakken)
3. dynamisk (på heapen)

Ad 1.

int i1; // static storage duration
void foo()
{
static int i2; // static storage duration
}

Ad 2.
void foo()
{
int i; automatic storage duration
}


Ad 3.
void foo()
{
int* pi = malloc(sizeof(int)); // dynamic storage duration
free(pi);

pi = new int; // dynamic storage duration
delete pi;
}


> Lægges disse på stacken eller allokeres der hukommelse vha.
> operativsystemet?

Normal (men strengt taget ikke påkrævet) er automatisk allokerede variable
(lokale, ikke static variable i funktioner) allokeret på stakken.

> Hvis det gøres vha. operativsystem - hvordan med
> parameteroverførsel osv?
>
> Hvad angår data-område? Her må operativsystemet skulle angive, hvor
> data-området er i hukommelsen?

Operativsystemet vil typisk være involveret i at allokere en
eksekveringsstak.
Desuden vil operativsystemet typisk have funktioner til dynamisk at allokere
hukommelse, og derved understøtte malloc/free (og new/delete i C++).

> Hvordan er denne parameteroverførsel
> fra/til operativsystem?

Det vil typisk ske på eksekveringsstakken.

Venlig hilsen

Mogens Hansen



Preben Holm (11-02-2004)
Kommentar
Fra : Preben Holm


Dato : 11-02-04 19:39

Hej igen

> Variable kan i C og C++ allokeres 3 steder:
> 1. statiks (globale variable)
> 2. automatisk (på stakken)
> 3. dynamisk (på heapen)

Hvordan anvender man heaps til data-allokering af hukommelse?

Normalt ville jeg tro, at der blev reserveret et hukommelses-område,
hvor operativ-systemet blot opdaterede en tabel for allokeret hukommelse!!!


> Ad 1.
>
> int i1; // static storage duration
> void foo()
> {
> static int i2; // static storage duration
> }

Selvom du angiver int i1, så ligger variablen vel ikke som en del af
maskin-koden, og bliver modificeret deri?


> Ad 2.
> void foo()
> {
> int i; automatic storage duration
> }
>
>
> Ad 3.
> void foo()
> {
> int* pi = malloc(sizeof(int)); // dynamic storage duration
> free(pi);
>
> pi = new int; // dynamic storage duration
> delete pi;
> }
>
>
>
>>Lægges disse på stacken eller allokeres der hukommelse vha.
>>operativsystemet?
>
> Normal (men strengt taget ikke påkrævet) er automatisk allokerede variable
> (lokale, ikke static variable i funktioner) allokeret på stakken.

Og dvs. her udelades operativ-systemet for videre arbejde og processen
kan klare alt selv.


> Operativsystemet vil typisk være involveret i at allokere en
> eksekveringsstak.
> Desuden vil operativsystemet typisk have funktioner til dynamisk at allokere
> hukommelse, og derved understøtte malloc/free (og new/delete i C++).

Hvordan ved compileren, hvordan den skal oversætte koden fra malloc
(såfremt os håndterer dynamisk allokering af hukommelse)? Dvs. hvordan
kan compileren lave et system-kald (med mindre den kender til systemet i
forvejen)? Kan dette angives i en header-fil, hvordan det skal gøres
eller hvad?

Problemet ligger jo i, når vi selv skal konstruere operativ-system og
applikationer og dertil få C til at arbejde sammen.


Mvh / Preben


Mogens Hansen (11-02-2004)
Kommentar
Fra : Mogens Hansen


Dato : 11-02-04 20:05


"Preben Holm" <64bitNOSPAM@mailme.dk> wrote:

[8<8<8<]
> Hvordan anvender man heaps til data-allokering af hukommelse?

Der er mulighed fra begrebsforvirring.
Der hvor man allokerer dynamiske variable (med malloc eller new) kaldes ofte
"the heap", "dynamic memory" (som ikke har noget med DRAM at gøre) eller
"free store".
Det har således _ikke_ noget med datastrukturen heap at gøre.
Det er blot den hukommelses-blok, hvorfra man dynamisk kan få allokeret
hukommele.

> Normalt ville jeg tro, at der blev reserveret et hukommelses-område,
> hvor operativ-systemet blot opdaterede en tabel for allokeret
hukommelse!!!

Ja - konceptuelt.

>
>
> > Ad 1.
> >
> > int i1; // static storage duration
> > void foo()
> > {
> > static int i2; // static storage duration
> > }
>
> Selvom du angiver int i1, så ligger variablen vel ikke som en del af
> maskin-koden, og bliver modificeret deri?

Nej, maskinkoden bliver eksekveret og variable bliver læst og skrevet.
Hvordan hukommelse bliver fortolket, er vel primært et spørgsmål om man
tilgår den med program-counteren eller ej.
Et selvmodificerende program, vil det ene øjeblik opfatte et memory-område
som en variable (f.eks. af typen array of char) og det næste øjeblik som
program.

Bortset fra det, hvis man laver en global variabel

const i1 = 7;

vil den sagtens kunne komme til at ligge samme sted som programmet.
Det kan f.eks. være i ROM i et embedded system, eller i et
hukommelsesområde, der er markeret som logisk skrivebeskyttet på en PC. I så
fald kan den _ikke_ modificeres.

[8<8<8<]
> > Ad 3.
> > void foo()
> > {
> > int* pi = malloc(sizeof(int)); // dynamic storage duration
> > free(pi);
> >
> > pi = new int; // dynamic storage duration
> > delete pi;
> > }
> >
> >
> >
> >>Lægges disse på stacken eller allokeres der hukommelse vha.
> >>operativsystemet?

Variablen "pi" allokeres på stakken, men det som "pi" peger på ligger på
heapen.
Hukommelsen som udgør programmets heap, kan nemt være allokeret vha.
operativsystemet.

På MS-Windows var funktionen "malloc" til Microsoft C compileren engang
implementeret ved at kalde operativsystem funktionen GlobalAlloc direkte.
Sådan er det ikke længere, fordi det ikke er specielt smart.
Dels er mindste blok der _faktisk_ allokeres 4 kbyte og dels er det
langsomt.

[8<8<8<]
> Og dvs. her udelades operativ-systemet for videre arbejde og processen
> kan klare alt selv.

Ja.
Det er typisk blot at sætte lidt ekstra plads af på eksekveringsstakken.
På en almindelig PC, vil man i starten af en funktion se noget i retningen
af følgende assembler funktions prolog
push ebp
mov ebp, esp
add esp, -0x0c
hvor den sidste instruktion sætter plads af til de lokale variable

>
>
> > Operativsystemet vil typisk være involveret i at allokere en
> > eksekveringsstak.
> > Desuden vil operativsystemet typisk have funktioner til dynamisk at
allokere
> > hukommelse, og derved understøtte malloc/free (og new/delete i C++).
>
> Hvordan ved compileren, hvordan den skal oversætte koden fra malloc
> (såfremt os håndterer dynamisk allokering af hukommelse)?

Det er bestemt af compileren selv.
Typisk vil det være en funktion i runtime biblioteket

> Dvs. hvordan
> kan compileren lave et system-kald (med mindre den kender til systemet i
> forvejen)? Kan dette angives i en header-fil, hvordan det skal gøres
> eller hvad?

Hvis man skal kalde operativsystem funktioner, skal man inkludere en
headerfil der hører til det.

"malloc" er ikke en del af operativsystemet - det er en del af compilerens
runtime bibliotek, og er erklæret i "stdlib.h" i C (og "cstdlib" i C++).

Venlig hilsen

Mogens Hansen



Preben Holm (11-02-2004)
Kommentar
Fra : Preben Holm


Dato : 11-02-04 22:10

> Der er mulighed fra begrebsforvirring.
> Der hvor man allokerer dynamiske variable (med malloc eller new) kaldes ofte
> "the heap", "dynamic memory" (som ikke har noget med DRAM at gøre) eller
> "free store".
> Det har således _ikke_ noget med datastrukturen heap at gøre.
> Det er blot den hukommelses-blok, hvorfra man dynamisk kan få allokeret
> hukommele.

Ok.


> Nej, maskinkoden bliver eksekveret og variable bliver læst og skrevet.

Ok, ja, men så er vi da enige... Blev lige bange :)


>>>Ad 3.
>>>void foo()
>>>{
>>> int* pi = malloc(sizeof(int)); // dynamic storage duration
>>> free(pi);
>>>
>>> pi = new int; // dynamic storage duration
>>> delete pi;
>>>}
>>>
>>>
>>>
>>>
>>>>Lægges disse på stacken eller allokeres der hukommelse vha.
>>>>operativsystemet?
>
>
> Variablen "pi" allokeres på stakken, men det som "pi" peger på ligger på
> heapen.
> Hukommelsen som udgør programmets heap, kan nemt være allokeret vha.
> operativsystemet.

Ja, ok... men noget som jeg ikke helt forstår her er flg.:

Hvad sker der når programmets loades i operativsystemet?

Der afsættes noget hukommelse til processen eller hvad? Men hvor meget
hukommelses afsættes der? Hvordan ved operativsystemet hvor stort et
område der skal tildeles til processen for at den ikke overskriver noget
andet?


> På MS-Windows var funktionen "malloc" til Microsoft C compileren engang
> implementeret ved at kalde operativsystem funktionen GlobalAlloc direkte.
> Sådan er det ikke længere, fordi det ikke er specielt smart.
> Dels er mindste blok der _faktisk_ allokeres 4 kbyte og dels er det
> langsomt.

Altså det som jeg har lidt svært ved at forstå er hvordan processen ved
at den ved hukommelses-allokering ikke overskriver/læser data fra andre
processor der kører på systemet (husk at jeg ikke har paging eller noget
andet hardware tilgængeligt på en 186 cpu som kan hjælpe til beskyttelse)

For det andet skal jeg lige være sikker på noget...

Jeg har på fornemmelse, at hvis OS reserverer den fornødne plads som
programmet kommer til at bruge i eksekveringstiden, så kan C-programmet
selv håndtere at reservere den fornødne plads til programmet!


>>Og dvs. her udelades operativ-systemet for videre arbejde og processen
>>kan klare alt selv.
>
>
> Ja.
> Det er typisk blot at sætte lidt ekstra plads af på eksekveringsstakken.
> På en almindelig PC, vil man i starten af en funktion se noget i retningen
> af følgende assembler funktions prolog
> push ebp
> mov ebp, esp
> add esp, -0x0c
> hvor den sidste instruktion sætter plads af til de lokale variable

Ja, det er til lokal-variable og intet andet - vel?

Btw. med esp mener du stack-pointer - ikke? Men hvad med ebp? base pointer?

Ja, normalt har vi i undervisningen (læser jo) anvendt

SP som stackpointer
BP som base pointer

SS stack segment
ES ekstra segment
DS data segment
CS code segment



Ok, det er nok mest hvordan operativsystemet giver processen lov til at
anvende hukommelse der lige er mit største problem nu..

Så hvis der kunne lægges lidt vægt på dette ville det være lækkert.


Takker mange gange for de gode svar..

Mvh / Preben


Mogens Hansen (11-02-2004)
Kommentar
Fra : Mogens Hansen


Dato : 11-02-04 21:41



"Preben Holm" <64bitNOSPAM@mailme.dk> wrote:

[8<8<8<]
> Hvad sker der når programmets loades i operativsystemet?

Det er op til operativsystemet af bestemme.
At kigge på hvordan DOS gjorde, således som du spurgte til på
dk.edb.programmering, er sikkert en glimrende ide.

>
> Der afsættes noget hukommelse til processen eller hvad? Men hvor meget
> hukommelses afsættes der? Hvordan ved operativsystemet hvor stort et
> område der skal tildeles til processen for at den ikke overskriver noget
> andet?

Det må jo stå på en eller anden form i programmet - linkeren har jo regnet
ud hvor meget statisk data og program der er.
Heap-forbrug kan ikke forudsiges - operativsystemets eneste mulighed er at
sige stop, hvis programmet bliver for grådigt.
Til MS-Windows kan man (men ofte gør man det ikke) specificere
heap-størrelse og stak-størrelse i en speciel fil (Module Definition File -
DEF) til linkeren.
Noget tilsvarende gør sig gældende til nogle embeddede systemer, hvor man
også kan angive hvilke adresseområder, der indeholder hvilke typer
hukommelse.

[8<8<8<]
> Altså det som jeg har lidt svært ved at forstå er hvordan processen ved
> at den ved hukommelses-allokering ikke overskriver/læser data fra andre
> processor der kører på systemet (husk at jeg ikke har paging eller noget
> andet hardware tilgængeligt på en 186 cpu som kan hjælpe til beskyttelse)

Det er operativsystemets ansvar ikke at dele samme klump ud til 2 programmer
samtidig, og det er så processens ansvar kun at bruge den hukommelse der er
blevet den tildelt.


[8<8<8<]
> Ja, det er til lokal-variable og intet andet - vel?

Netop

> Btw. med esp mener du stack-pointer - ikke? Men hvad med ebp? base
pointer?

32 bit registrene i x86 arkitekturen foranstilles med E, i forhold til 16
bit registrene.
Det vil sige at hvad der i 80186 hedder AX hedder EAX i 80386 (og opefter)
(AX findes stadig i 80386 - det er de nedre 16 bit i EAX).
Så ESP er en 32 bit stack-pointer og EBP er en 32 bit base-pointer.


[8<8<8<]
> Ok, det er nok mest hvordan operativsystemet giver processen lov til at
> anvende hukommelse der lige er mit største problem nu..

Programmet spørger pænt operativsystemet om at få råderet over en klump
hukommelse.
Operativsystemet har retten til at fordele _al_ hukommelsen i hele systemet.
Operativsystemet stiller en funktion til rådighed for processen

Venlig hilsen

Mogens Hansen



Preben (11-02-2004)
Kommentar
Fra : Preben


Dato : 11-02-04 22:36

Hej igen


> Programmet spørger pænt operativsystemet om at få råderet over en klump
> hukommelse.
> Operativsystemet har retten til at fordele _al_ hukommelsen i hele systemet.
> Operativsystemet stiller en funktion til rådighed for processen

Ok, men lad os tage fat her igen..

Programmet spørger pænt om adgang til hukommelsen - meget fint, men men
men...

Hvis man nu skrev det i assembler ville man jo hele tiden holde styr på
pladsforbrug pga. adresseringen, men i C forholder det vel sig noget
anderledes (fortæl mig hvis det er forkert)...

For hvordan angiver jeg til C-compileren at man efter et systemkald til
styresystemet skal starte i data-segment adresse 0x1FFF(0) og må anvende
4kbyte derudover.
Skal jeg selv holde styr på de 4 kbyte eller kan C gøre det for mig. Der
er jo ingen der siger, at jeg ved hvordan programmet vil opføre sig, det
kan jo være det i nogle tilfælde har brug for at anvende 2x4kbyte men i
andre tilfælde ikke, selvom det måske er samme funktion der bliver kaldt.

For hvis jeg ønsker at allokere noget hukommelse i C bruger man jo
malloc, men hvis jeg nu ønsker at allokere 16 byte i første omgang,
derefter 20byte og så måske lige pludselig 4kbyte, så skal jeg jo spørge
styresystemet om lov til dette, og dernæst skal C-compileren vel vide
hvor i det hele taget den skal starte med at lægge disse data, for hvis
den ikke ved det, når malloc eksekveres vil den vel kunne lægge det hvor
som helst i hukommelsen? (Jeg aner som sagt ikke særlig meget om C)

Dvs. hvor vidt kan jeg regne med at C-compileren ikke lige pludselig
finder på at ændre data-segmentet angivet af operativ-systemet.

Og hvordan ved jeg om der anvendes data-segment eller ekstra-segment?



Mvh / Preben


--
If your Dell laptop is unstable, try change the power supply - it works!
But the Dell will still stink! Nothing can change that!!!


Mogens Hansen (11-02-2004)
Kommentar
Fra : Mogens Hansen


Dato : 11-02-04 23:10


"Preben" <64bitATtheNet@mailme.dk> wrote:

[8<8<8<]
> Hvis man nu skrev det i assembler ville man jo hele tiden holde styr på
> pladsforbrug pga. adresseringen, men i C forholder det vel sig noget
> anderledes (fortæl mig hvis det er forkert)...

Det forekommer mig umiddelbart at være upræcist - det kommer an på
omgivelserne.

Et DOS program skrevet i assembler skal spørge DOS om at allokere en klump
hukommelse vha. et "int 21" (eller noget i den stil), svarende til at
anvende malloc i C.
Et C program kan skrive i adresse 0x1fff hvis man er _pokkers_ sikker på
hvad man laver
static_cast<char*>(0x1fff) = 'H';

Du har de samme muligheder for at allokere variable i C og assembler,
bortset fra register allokering: statisk, på stakken og dynamisk.

>
> For hvordan angiver jeg til C-compileren at man efter et systemkald til
> styresystemet skal starte i data-segment adresse 0x1FFF(0) og må anvende
> 4kbyte derudover.

Inden main i C programmet kaldes, kører der noget initialiseringskode som
sætter en række ting op (f.eks. initialiserer heap manageren og eventuel
initialisering af hardware).
Denne initialiseringskode er typisk noget der er meget specifik for
compileren, operativsystemet og hardware arkitekturen.

Det lyder som du skal bruge noget af den kode der skal køre umiddelbart
efter reset af 80186'eren.
Det fortæller man typisk ikke C compileren - det skriver man i assembler som
en del af initilialiseringkoden, inden man overgiver kontrollen til main i C
programmet (eller noget andet i et system med et mere reelt operativsystem).

Hvad er det for et fag du har ?

[8<8<8<]
> For hvis jeg ønsker at allokere noget hukommelse i C bruger man jo
> malloc, men hvis jeg nu ønsker at allokere 16 byte i første omgang,
> derefter 20byte og så måske lige pludselig 4kbyte, så skal jeg jo spørge
> styresystemet om lov til dette, og dernæst skal C-compileren vel vide
> hvor i det hele taget den skal starte med at lægge disse data, for hvis
> den ikke ved det, når malloc eksekveres vil den vel kunne lægge det hvor
> som helst i hukommelsen? (Jeg aner som sagt ikke særlig meget om C)

Hvis du først skal bruge 16 byte, derefter 20 byte og pludselig 4 kbyte i C,
starter du med at allokere med malloc, og derefter allokere mere hukommelse
med realloc.
Du ved ikke _hvor_ hukommelsen ligger - og er typisk også ligeglad. Det
eneste der spiller en rolle er om du fik hukommelsen tildelt eller ej.

>
> Dvs. hvor vidt kan jeg regne med at C-compileren ikke lige pludselig
> finder på at ændre data-segmentet angivet af operativ-systemet.

Det sikrer kalde-konventioner som er en aftale mellem C-compileren og
operativ-systemet om hvilke registre der skal være uberørt efter kald etc.

>
> Og hvordan ved jeg om der anvendes data-segment eller ekstra-segment?

Hvilken rolle spiller det ?
Til 16 bit x86 processorer har C compileren typisk forskellige pointer typer
(near, far og huge) og forskellige hukommelses modeller.
Compileren håndterer det for dig ?


Venlig hilsen

Mogens Hansen



Preben (12-02-2004)
Kommentar
Fra : Preben


Dato : 12-02-04 06:29

Hej igen igen

> Et DOS program skrevet i assembler skal spørge DOS om at allokere en klump
> hukommelse vha. et "int 21" (eller noget i den stil), svarende til at
> anvende malloc i C.

Ok, men malloc kalder intet interrupt jo - jævnfør tidligere thread.
Dvs. C aner intet om hvorledes den har tilladelse til at lægge data her?

Enten er man derfor nødsaget til at vide hvordan C-compileren ligger
data i hukommelsen (i Dos starter alle adresser fra 0x0000) for at man
kan reservere plads til data'ene i hukommelsen og derved gå ind og rette
alle program-referencer til den korrekte adresse før programmet eksekveres.


>>For hvordan angiver jeg til C-compileren at man efter et systemkald til
>>styresystemet skal starte i data-segment adresse 0x1FFF(0) og må anvende
>>4kbyte derudover.
>
>
> Inden main i C programmet kaldes, kører der noget initialiseringskode som
> sætter en række ting op (f.eks. initialiserer heap manageren og eventuel
> initialisering af hardware).
> Denne initialiseringskode er typisk noget der er meget specifik for
> compileren, operativsystemet og hardware arkitekturen.

Ok, men nu skal vi jo selv lave vores system, så jeg tror vi foregiver
et DOS-operativsystem og indbygger den nødvendige funktionalitet heri.


> Det lyder som du skal bruge noget af den kode der skal køre umiddelbart
> efter reset af 80186'eren.
> Det fortæller man typisk ikke C compileren - det skriver man i assembler som
> en del af initilialiseringkoden, inden man overgiver kontrollen til main i C
> programmet (eller noget andet i et system med et mere reelt operativsystem).


Jaja, initialiseringskode i asm er fint nok til operativsystemet, men
hvad angår processerne bliver det jo lidt mere kompliceret da vi skal
lave en loader...

Loaderen skal jo placere programmet i hukommelsen - og ser man på DOS,
lader det til at en proces får et helt kode-segment for sig selv.

> Hvad er det for et fag du har ?

Faget hedder bare Projekt C, men bygger på faget operativsystemer, hvor
vi har brugt bogen skrevet af Silbershatz, Galvin og Gagne - desværre er
der langt fra at skrive et "operativsystem" i Java, som de giver en
masse del-eksempler i, til at skrive noget rigtig kode i C.
Grunden til, at vi ikke bare skriver det hele i ASM skyldes, at vi skal
skrive det i C - det er et krav, men nu har vi bare aldrig haft et
C-kursus, og får det heller ikke, så det forventer de vi lige spytter ud
af ærmet.



>>For hvis jeg ønsker at allokere noget hukommelse i C bruger man jo
>>malloc, men hvis jeg nu ønsker at allokere 16 byte i første omgang,
>>derefter 20byte og så måske lige pludselig 4kbyte, så skal jeg jo spørge
>>styresystemet om lov til dette, og dernæst skal C-compileren vel vide
>>hvor i det hele taget den skal starte med at lægge disse data, for hvis
>>den ikke ved det, når malloc eksekveres vil den vel kunne lægge det hvor
>>som helst i hukommelsen? (Jeg aner som sagt ikke særlig meget om C)
>
>
> Hvis du først skal bruge 16 byte, derefter 20 byte og pludselig 4 kbyte i C,
> starter du med at allokere med malloc, og derefter allokere mere hukommelse
> med realloc.
> Du ved ikke _hvor_ hukommelsen ligger - og er typisk også ligeglad. Det
> eneste der spiller en rolle er om du fik hukommelsen tildelt eller ej.

Ja, men det der spiller en rolle er jo netop om man fik hukommelsen
tildelt eller ej, men så må malloc/realloc da også forespørge
operativsystemet?

Ok, men hvis jeg skriver malloc i en DOS C-compiler - hvad sker der så?
Nogen der kan svare på det?

Altså en præcis angivelse af hvad der sker?


>>Dvs. hvor vidt kan jeg regne med at C-compileren ikke lige pludselig
>>finder på at ændre data-segmentet angivet af operativ-systemet.
>
> Det sikrer kalde-konventioner som er en aftale mellem C-compileren og
> operativ-systemet om hvilke registre der skal være uberørt efter kald etc.
>
>>Og hvordan ved jeg om der anvendes data-segment eller ekstra-segment?
>
>
> Hvilken rolle spiller det ?
> Til 16 bit x86 processorer har C compileren typisk forskellige pointer typer
> (near, far og huge) og forskellige hukommelses modeller.
> Compileren håndterer det for dig ?

Ja, men hvis operativ-systemet skal tildele de rigtige adresser er man
jo nødt til at vide hvordan C-compileren oversætter ens kode.



Mvh / Preben


--
If your Dell laptop is unstable, try change the power supply - it works!
But the Dell will still stink! Nothing can change that!!!


Mogens Hansen (12-02-2004)
Kommentar
Fra : Mogens Hansen


Dato : 12-02-04 17:20


"Preben" <64bitATtheNet@mailme.dk> wrote:
> Hej igen igen
>
> > Et DOS program skrevet i assembler skal spørge DOS om at allokere en
> > klump hukommelse vha. et "int 21" (eller noget i den stil), svarende
> > til at anvende malloc i C.
>
> Ok, men malloc kalder intet interrupt jo - jævnfør tidligere thread.

Jeg forstår ikke hvad du mener.

Mit eksempel gik på at under MS-DOS man i et assembler program bruger int 21
funktion 48h (Allocate Memory) til dynamisk at allokere hukommelse og int 21
funktion 49h til at frigive dynamisk allokeret hukommelse igen.

En simpel måde at implementere "malloc" og "free" i et MS-DOS program er at
kalde disse MS-DOS operativsystem funktioner via int 21 direkte.
På den måde spørger C runtime biblioteket (ikke compileren) pænt
operativsystemet om hukommele.

> Dvs. C aner intet om hvorledes den har tilladelse til at lægge data her?

Ikke selve compileren.
Men implementeringen af "malloc" og "free" ved om de spørger et
operativsystem eller om de på en anden måde ved hvilke hukommelsesområder de
har råderet over

Prøv at se om du kan få fat på nogle gamle DOS bøger, f.eks. manualerne til
Borland Turbo C eller
Microsoft MS-DOS Programmer's Reference
ISBN 1-55615-329-5


> Enten er man derfor nødsaget til at vide hvordan C-compileren ligger
> data i hukommelsen (i Dos starter alle adresser fra 0x0000) for at man
> kan reservere plads til data'ene i hukommelsen og derved gå ind og rette
> alle program-referencer til den korrekte adresse før programmet
eksekveres.

Linkeren ved hvilke statiske variable et program har, og om de skal
initialiseres eller ej.
Linkeren kan således, ud fra lidt ekstra information om systemet, finde ud
af på hvilken adresse en given statisk variabel skal ligge.
De dynamisk allokerede variable har ikke en på forhånd kendt adresse - det
kan i sagens natur først ske på runtime.


[8<8<8<]
> Ja, men det der spiller en rolle er jo netop om man fik hukommelsen
> tildelt eller ej, men så må malloc/realloc da også forespørge
> operativsystemet?

Ja, principielt.

I praksis er det almindeligt at programmet har sin egen heap-manager, der
beder operativsystemet om større blokke af hukommelse, som malloc så deler
ud i småbidder til processen.

>
> Ok, men hvis jeg skriver malloc i en DOS C-compiler - hvad sker der
> så?

Enten får du en peger til en klump hukommelse, der mindst har den størrelse
du bad om - ellers får du NULL tilbage.

> Nogen der kan svare på det?
>
> Altså en præcis angivelse af hvad der sker?

Det kan ikke siges med sikkerhed.
Det kommer an på hvilken compiler vi snakker om. Kig i sourcen til
compilerens runtime bibliotek.

En simpel implementering er som nævnt at kalde DOS int 21 funktion 48.
Hvad DOS så gør er egentlig uinteressant for malloc.

[8<8<8<]
> > Hvilken rolle spiller det ?
> > Til 16 bit x86 processorer har C compileren typisk forskellige
> > pointer typer (near, far og huge) og forskellige hukommelses
> > modeller. Compileren håndterer det for dig ?
>
> Ja, men hvis operativ-systemet skal tildele de rigtige adresser er man
> jo nødt til at vide hvordan C-compileren oversætter ens kode.

Operativsystemet bestemmer hvor der kan allokeres hukommelse.
Det er så compileren og dens runtime biblioteks opgave at tilpasse sig
operativsystemet på den ene side og C sproget på den anden side.


Venlig hilsen

Mogens Hansen




Bertel Lund Hansen (12-02-2004)
Kommentar
Fra : Bertel Lund Hansen


Dato : 12-02-04 20:14

Mogens Hansen skrev:

>Prøv at se om du kan få fat på nogle gamle DOS bøger, f.eks. manualerne til
>Borland Turbo C eller
> Microsoft MS-DOS Programmer's Reference
> ISBN 1-55615-329-5

Dengang da der var rigtige computere til, var Ralf Browns lister
en uvurderlig hjælp til DOS-programmering. Det ser ud til at de
ligger her:

HTML:   http://www.ctyme.com/rbrown.htm

Download:
http://www-2.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html

Det er ikke egentlig gennemgang af DOS, men et opslagsværk med
alle DOS-interrupts.

--
Bertel
http://bertel.lundhansen.dk/   FIDUSO: http://fiduso.dk/

Byrial Jensen (12-02-2004)
Kommentar
Fra : Byrial Jensen


Dato : 12-02-04 21:20

Mogens Hansen wrote:
> 32 bit registrene i x86 arkitekturen foranstilles med E, i forhold til 16
> bit registrene.
> Det vil sige at hvad der i 80186 hedder AX hedder EAX i 80386 (og opefter)
> (AX findes stadig i 80386 - det er de nedre 16 bit i EAX).
> Så ESP er en 32 bit stack-pointer og EBP er en 32 bit base-pointer.

Det er ikke forkert, men det undrer mig at du lige netop nævner 80186.
Grundmodellen i x86-serien er 8086.

80186 blev ikke brugt i ret mange pc'er. Den svarer til en 8086, men har
flere enheder indbygget i chippen. Udvidelserne omfatter: 2 DMA-kanaler,
3 timere, interrupt controller og clock generator.

Instruktionssættet er også udvidet lidt. Nye instruktioner i 80186 er:
INS/OUTS, PUSHI, IMUL, PUSHA/POPA, shift/rotate by immediate value,
BOUND, ENTER, LEAVE.

80186 var også den første x86-processor som lavede interrupt ved en
ukendt instruktion.


Preben Holm (12-02-2004)
Kommentar
Fra : Preben Holm


Dato : 12-02-04 22:40

Hej igen

>> 32 bit registrene i x86 arkitekturen foranstilles med E, i forhold til 16
>> bit registrene.
>> Det vil sige at hvad der i 80186 hedder AX hedder EAX i 80386 (og
>> opefter)
>> (AX findes stadig i 80386 - det er de nedre 16 bit i EAX).
>> Så ESP er en 32 bit stack-pointer og EBP er en 32 bit base-pointer.
>
>
> Det er ikke forkert, men det undrer mig at du lige netop nævner 80186.
> Grundmodellen i x86-serien er 8086.

Jep, faktisk havde jeg aldrig hørt om 186-cpu'en før for ca. 1 års tid
siden, men det er altså den vi udvikler på og skal udvikle på.

Det skyldes nok at den har en rimelig funktionalitet men stadig er
"simpel" at overskue.


> 80186 blev ikke brugt i ret mange pc'er. Den svarer til en 8086, men har
> flere enheder indbygget i chippen. Udvidelserne omfatter: 2 DMA-kanaler,
> 3 timere, interrupt controller og clock generator.
>
> Instruktionssættet er også udvidet lidt. Nye instruktioner i 80186 er:
> INS/OUTS, PUSHI, IMUL, PUSHA/POPA, shift/rotate by immediate value,
> BOUND, ENTER, LEAVE.
>
> 80186 var også den første x86-processor som lavede interrupt ved en
> ukendt instruktion.

Det vidste jeg så ikke, men tak for det :)


Men læs mere om det kit vi udvikler på, på:
http://old.iot.dk/sine/186forum/


Mvh / Preben


Byrial Jensen (12-02-2004)
Kommentar
Fra : Byrial Jensen


Dato : 12-02-04 22:10

Preben Holm wrote:
>>
>> Det er ikke forkert, men det undrer mig at du lige netop nævner 80186.
>> Grundmodellen i x86-serien er 8086.
>
> Jep, faktisk havde jeg aldrig hørt om 186-cpu'en før for ca. 1 års tid
> siden, men det er altså den vi udvikler på og skal udvikle på.

Ah ja, det havde jeg overset (selvom jeg nu kan se at du skrev det i det
første indlæg, og det forklarer jo min undren.

> Det skyldes nok at den har en rimelig funktionalitet men stadig er
> "simpel" at overskue.

Tja, men det er noget rod at lave registerallokering fordi mange
instruktioner kun virker med bestemte registre. Og den (primært
8086'eren) bærer præg af at det skulle let at konvertere kode til Intels
8-bit processorer (8080 og 8085) til den.

Så andre arkitekturer havde nok været endnu simplere at overskue.


Mogens Hansen (13-02-2004)
Kommentar
Fra : Mogens Hansen


Dato : 13-02-04 16:27


"Byrial Jensen" <bjensen@nospam.dk> wrote:

[8<8<8<]
> Tja, men det er noget rod at lave registerallokering fordi mange
> instruktioner kun virker med bestemte registre. Og den (primært
> 8086'eren) bærer præg af at det skulle let at konvertere kode til Intels
> 8-bit processorer (8080 og 8085) til den.

Det er et interessant og lærerigt stykke evolutionshistorie.

8086 fik ved overgangen til 16 bit nogle lidt akavede konstruktioner (f.eks.
segmenteret hukommelses adressering) for at være kompatibel med 8085 og
8085.
Det blev videreført i 32 bit verdenen med 80386, som egentlig heller ikke
kan beskyldes for at være det mest rene design.
Den arkitektur har haft success på trods af at hurtigere, og angiveligt mere
rent designede procesorer som Alpha og PowerPC, eksisterede og f.eks. var
MS-Windows tilgængelig til dem.
AMD har, tilsynelandende rimeligt successfuldt, gentaget nummeret med deres
64 bit Athlon og Opteron processorer. Så successfuldt at Intel ser ud til at
blive tvunget til at lave noget tilsvarende, på trods af at de har Itanium
arkitekturen.

Hvad disse x86 processorer end måtte have af mærkværdigheder, er det ikke
værre end at det er til at håndtere og at det reelt ikke spiller den store
rolle for daglig anvendelse. Computerbrugere er ikke klar over det, og for
programmører tager compilere og fortolkere som regel sig af det.

Der findes en del tilsvarende eksempler i computer historien.

Bagud kompatibilitet er vigtig.
Den bedste teknologi er ikke tilstrækkelig til at opnå succes.

Venlig hilsen

Mogens Hansen




Mogens Hansen (13-02-2004)
Kommentar
Fra : Mogens Hansen


Dato : 13-02-04 06:44


"Byrial Jensen" <bjensen@nospam.dk> wrote:

[8<8<8<]
> Det er ikke forkert, men det undrer mig at du lige netop nævner 80186.
> Grundmodellen i x86-serien er 8086.

Jeps, den er jeg med på.
Grunden til at jeg nævnte 80186 var at Preben Holm nævnte i starten af
tråden at det var denne processor han anvendte og han tilsynelandende ikke
kendte x86-serien generelt.

Venlig hilsen

Mogens Hansen



Preben Holm (13-02-2004)
Kommentar
Fra : Preben Holm


Dato : 13-02-04 22:40

> Grunden til at jeg nævnte 80186 var at Preben Holm nævnte i starten af
> tråden at det var denne processor han anvendte og han tilsynelandende ikke
> kendte x86-serien generelt.

Nej, arkitektur-mæssigt er jeg slet ikke inde i de senere modeller af
80286 og fremefter. Det har ligget udenfor pensum i vores fag og tiden
er simpelthen ikke til at sætte sig ind i det. Så det er korrekt forstået.

Generelt om 8086 har vi jo haft noget alligevel - ikke mindst om 186'eren.


Ole Nielsby (11-02-2004)
Kommentar
Fra : Ole Nielsby


Dato : 11-02-04 20:30


Preben Holm skrev:

> [...]
>
> > static int i2; // static storage duration
>
> Selvom du angiver int i1, så ligger variablen vel ikke som en del af
> maskin-koden, og bliver modificeret deri?

Compileren genererer 3 segmenter:

1. Et read-only-segment til kode og konstanter
2. Et initialiseret read/write segment til statiske,
compile-time-initialiserede variable
3. Et nul-initialiseret eller uinitialiseret segment
til statiske variable som initialiseres pr runtime.

Linkeren sørger for at koden i kodesegmentet bruger de rigtige adresser
i de andre segmenter.

1. og 2. behandles ens bort set fra at 1. sættes til readonly i
pagetabellen.
(For viderekomne: 2. behandles i visse systemer som copy-on-write,
dvs. den er readonly og fælles mellem flere samtidige kørsler af
samme program indtil den skrives til, så kopieres den pågældende page.)

> Hvordan ved compileren, hvordan den skal oversætte koden fra malloc
> (såfremt os håndterer dynamisk allokering af hukommelse)? Dvs. hvordan
> kan compileren lave et system-kald (med mindre den kender til systemet i
> forvejen)? Kan dette angives i en header-fil, hvordan det skal gøres
> eller hvad?
>
> Problemet ligger jo i, når vi selv skal konstruere operativ-system og
> applikationer og dertil få C til at arbejde sammen.

Afhænger af hvordan jeres OS er opbygget.

I Win32 linkes en reference ind til en funktion i kernel32.dll - det
sker via en hoptabel som udfyldes af loaderen. Funktionen forsøger
først at reservere fra de pages som allerede er allokerede - i processens
heap der vistnok administreres via nogle datastrukturer som tilgås via
fs-segmentregisteret. Hvis det ikke kan lade sig gøre, laver den et
kernel mode kald - som er en call-instruktion der har angivet et segment
hvis descriptor fortæller at det er beskyttet kode...

Under Linux tror jeg der linkes statisk til en stump kode der laver et
systemkald via ínt-instruktionen.

C-compileren skal under alle omstændigheder bare linke til en
biblioteksfunktion.



Søg
Reklame
Statistik
Spørgsmål : 177459
Tips : 31964
Nyheder : 719565
Indlæg : 6408182
Brugere : 218881

Månedens bedste
Årets bedste
Sidste års bedste