[ASM] Universele code schrijven

Pagina: 1
Acties:

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
Klein vraagje voor mezelf.

Stel, ik heb twee OS'en, Windows en Linux, en deze zouden hetzelfde executable formaat hebben, b.v. PE.

Als ik dan in assembly een programma schrijf dat géén software interrupts aanroept, alleen hardware interrupts. Ik kan niet superveel met het programma zonder soft-interrupts, maargoed... alleen de hardware aanspreekt, en niet het OS...

Heb ik dan een OS-onafhankelijk programma?

[ Voor 11% gewijzigd door Vinnienerd op 17-06-2005 12:24 . Reden: Haalde hardware en software interrupts door elkaar :x ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, wat is het verschil tussen een software interrupt en een hardware interrupt volgens jou?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
.oisyn schreef op vrijdag 17 juni 2005 @ 12:18:
Nee, wat is het verschil tussen een software interrupt en een hardware interrupt volgens jou?
Hardware interrupts zijn toch per definitie OS-onafhankelijk? Omdat je de hardware direct aanspreekt en niet het OS?

Pardon, ik zie het al, ik haal dingen door elkaar.

[ Voor 9% gewijzigd door Vinnienerd op 17-06-2005 12:23 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Nee - geen enkel modern OS laat toe dat je HW interrupts aanroept.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Precies :)

Het verschil is dat een hardware interrupt wordt getriggered door hardware, en een software interrupt door software. Er zit geen verschil in afhandeling, dat gebeurt altijd door software. En "de hardware interrupts" zelf gaan aanroepen heeft weinig nut. Je kunt dus wel OS-onafhankelijke code schrijven als de layout van de executable hetzelfde is, maar verder kun je niets want je kunt geen OS calls doen. Iets op het scherm zetten oid is er niet bij.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 05-05 14:48
De term "interrupt aanroepen" is in OS'en zoals Windows en Linux niet echt van toepassing. In DOS programma's riep je op die manier functies aan van DOS en het BIOS (een interrupt aanroepen is niets anders dan een jump naar een adres uit de interrupt table). Zoals oisyn uitlegde kan je in je programma zelf dus alleen maar "software" interrupts genereren.

In een Windows/Linux programma "call" je gewoon een functie uit een DLL of so en gebruik je helemaal niet de "int" instructie.

Het executable formaat maakt voor je asm programma niet zo gek veel uit, daar heb je de linker voor.

Indien je specifiek het aanspreken van hardware bedoeld; in Windows en Linux gebruik je hier ook gewoon API calls voor als je een driver maakt (wat normaliter gewoon zonder asm kan).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

matthijsln schreef op vrijdag 17 juni 2005 @ 13:00:
In een Windows/Linux programma "call" je gewoon een functie uit een DLL of so en gebruik je helemaal niet de "int" instructie.
Hoe denk je dat die DLL's hun kernel calls weer doorrouten dan? Juist, met int's. En die kun je dus ook prima zelf doen. Geldt ook voor linux overigens.
Het executable formaat maakt voor je asm programma niet zo gek veel uit, daar heb je de linker voor.
Het ging er volgens mij om dat de binary op beide OS'en werkte zonder verder nog een vertaalslag te maken. Overigens zal alleen linken je er niet bij helpen, het ELF formaat gebruikt bijvoorbeeld relative positioning zodat je alle dataaccess via een bepaalde globale offset moet doen. Dat betekent compleet andere machinecode die je zelf moet schrijven.

[ Voor 38% gewijzigd door .oisyn op 17-06-2005 13:16 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 05-05 14:48
.oisyn schreef op vrijdag 17 juni 2005 @ 13:07:
[...]
Hoe denk je dat die DLL's hun kernel calls weer doorrouten dan? Juist, met int's. En die kun je dus ook prima zelf doen. Geldt ook voor linux overigens.
Dat is om te switchen naar kernel mode inderdaad. Echter doen "normale" programma's dat niet zelf en laten dat aan de DLL's van het OS over, alleen virussen/buffer overflow code e.d. doen dat onder Windows direct. Die int aanroepen zijn niet gedocumenteerd dus om dat zelf te doen lijkt me niet zo'n goed idee. Dat het kan betekent niet dat je het zo moet doen...

Ik geloof dat Linux met int 80h wel een soort int-api heeft maar dat dat niet een "officiele" gedocumenteerde API is.
Het ging er volgens mij om dat de binary op beide OS'en werkte zonder verder nog een vertaalslag te maken. Overigens zal alleen linken je er niet bij helpen, het ELF formaat gebruikt bijvoorbeeld relative positioning zodat je alle dataaccess via een bepaalde globale offset moet doen. Dat betekent compleet andere machinecode die je zelf moet schrijven.
Mijn commentaar was op de TS, uiteraard moet je hiermee rekening mee houden net als bijvoorbeeld de calling conventie van API functies e.d. door bijvoorbeeld macro's te gebruiken.

[ Voor 5% gewijzigd door matthijsln op 17-06-2005 13:52 ]


  • Rukapul
  • Registratie: Februari 2000
  • Laatst online: 22:37
In zekere zin bestaat dit, hoewel er vaak wel wat glue / compatiblitity code is:
- Linux binaries kunnen draaien op FreeBSD
- Mplayer is in staat Windows DLL's te laden als codecs
- Diverse Linux device drivers berusten op het aanroepen van de Windows DLL drivers.
- wine

Met name voor typische input-process-output code zoals codecs hoeft dit niet moeilijk te zijn, omdat er weinig interactie met de omgeving plaatsvindt. De ASM code zelf is in z'n algemeenheid niet OS afhankelijk.

[ Voor 3% gewijzigd door Rukapul op 17-06-2005 14:20 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
.oisyn schreef op vrijdag 17 juni 2005 @ 13:07:
Hoe denk je dat die DLL's hun kernel calls weer doorrouten dan? Juist, met int's. En die kun je dus ook prima zelf doen. Geldt ook voor linux overigens.
Als ik het me goed herinner deed Windows op de 386 dat niet met een INT instructie, maar met een illegale opcode. Daarmee knalt de processor naar een exception handler in privileged mode die het maar moet af handelen et voila, we hebben een trap!

Moraal van het verhaal is natuurlijk dat je je daar niet mee bezig moet houden. Als je portable assembly wil schrijven (portable tussen verschillende operating systems op hetzelfde hardware platform) dan moet je gewoon zorgen dat je geen system calls doet en je functies aan de C calling convention laat voldoen. Code die wel system calls doet kun je hoogstwaarschijnlijk beter in C schrijven.

[ Voor 29% gewijzigd door Soultaker op 17-06-2005 14:58 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 05-05 18:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op vrijdag 17 juni 2005 @ 14:55:
[...]

Als ik het me goed herinner deed Windows op de 386 dat niet met een INT instructie, maar met een illegale opcode. Daarmee knalt de processor naar een exception handler in privileged mode die het maar moet af handelen et voila, we hebben een trap!
Als dat zo is, waarom zouden ze in hemelsnaam die keuze gemaakt hebben? Een int voldoet toch ook prima, heb je bovendien meer mogelijkheden. En wat als een bepaalde executable 'toevallig' een illegal opcode gebruikt, als er een random kernel functie wordt aangeroepen heb je de poppen natuurlijk aan het dansen :). Waarom er überhaupt nooit callgates worden gebruikt is me sowieso al een raadsel, die zijn speciaal ontworpen om naar een ander privilegelevel te springen en ondersteunen zelfs parameter passing over de stack (er worden x bytes gekopieërd van de stack van het programma naar de stack van de handler)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
Ik vermoed om dezelfde reden als een triple fault om de 286 te resetten in plaats van via de keyboardcontroller: het zal wel marginaal sneller zijn.

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
Dus dat je met ASM direct de processor aanspreekt klopt wel, maar zodra je int 19h }) aanroept zal het OS dat zien en zeggen "Jammerrrrrrrrrrrr" :+ en de call wordt onderschept en dus niet uitgevoerd? Zo ja, kun je dan de hardware dus alleen nog zelf direct aanspreken als je een eigen OS schrijft en op een floppy propt?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
Je kunt alleen hardware aanspreken door een kernel module/driver te schrijven. Maar je kunt best interrupts genereren, alleen bepaalt het besturingssysteem wat er mee gebeurt.

[ Voor 59% gewijzigd door Soultaker op 17-06-2005 15:33 ]


  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
Soultaker schreef op vrijdag 17 juni 2005 @ 15:28:
Je kunt alleen hardware aanspreken door een kernel module/driver te schrijven. Maar je kunt best interrupts genereren, alleen bepaalt het besturingssysteem wat er mee gebeurt.
Ok. Dus vanuit userland (is dat de goeie term? :+ ) direct hardware aanspreken kon alleen dus in DOS? Dan iswas DOS eigenlijk een soort van half besturingssysteem, waarin je de hardware wel direct kon aanspreken, wat DOS weer overbodig maakte. Dat verklaart ook waarom je zoveel met de Win4.x kernel kon, het draaide natuurlijk vanuit DOS, maar omzeilde het tegelijkertijd ook. }:O

[ Voor 28% gewijzigd door Vinnienerd op 17-06-2005 15:50 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
Uhm, DOS draaide alles in real mode. In feite was elk programma gewoon een kernel module, maar ik vind kernel wat te veel eer voor een OS dat niets aan scheduling en praktisch niets aan beheer van resources deed.

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
Soultaker schreef op vrijdag 17 juni 2005 @ 16:03:
Uhm, DOS draaide alles in real mode. In feite was elk programma gewoon een kernel module, maar ik vind kernel wat te veel eer voor een OS dat niets aan scheduling en praktisch niets aan beheer van resources deed.
Dus DOS was gewoon geen OS, alleen een shellprogramma om de uitvoer van andere programma's aan te roepen?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Nee, DOS had een grote collectie van wat we nu operating system calls zouden noemen. De hele interface rondom int 21h was dos. int 10h waren bios calls.

Bovendien had DOS een filesystem (disk operating system...) En uiteraard werd er niet aan multi processings of scheduling gedaan, want de target processor ondersteunde dat niet (8086 etc). Pas op de 80386 was dat mogelijk (286 had geen goeie 'protected' protected mode...) en voila, daar was windows.

[ Voor 51% gewijzigd door Zoijar op 17-06-2005 16:18 ]


  • JoetjeF
  • Registratie: Juni 2003
  • Laatst online: 10-11-2012

JoetjeF

Mo Chuisneoir

Vinnienerd schreef op vrijdag 17 juni 2005 @ 16:10:
Dus DOS was gewoon geen OS, alleen een shellprogramma om de uitvoer van andere programma's aan te roepen?
In principe is een Kernel/OS een layer tussen de applicaties en de hardware. Je zou het dus wel degelijk kunnen zien als een Kernel/OS. Mijn perceptie is dat de Kernel een onderdeel van het OS is, maar andere zeggen misschien dat dit hetzelfde betekend. Maar ja, dit is eigenlijk een beetje off-topic :P

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Vinnienerd schreef op vrijdag 17 juni 2005 @ 15:44:
Dus vanuit userland (is dat de goeie term? :+ ) direct hardware aanspreken kon alleen dus in DOS?
Uiteraard, probeer maar eens een fatsoenlijk multi-user systeem op te zetten waarbij elke user controle heeft over alle hardware. DirectX is om die reden best wel complex, daar kun je relatief direct bij de hardware.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
Zoijar schreef op vrijdag 17 juni 2005 @ 16:14:
Nee, DOS had een grote collectie van wat we nu operating system calls zouden noemen. De hele interface rondom int 21h was dos. int 10h waren bios calls.
Wat dat betreft was het dus een shell met een leuke library erbij die processen kunnen gebruiken. Wat je een OS noemt is een kwestie van definitie en dat is niet zo'n interessante discussie, maar tegenwoordig werdt van een OS verwacht dat het op z'n minst processen van elkaar afschermd, wat DOS duidelijk niet deed.
Bovendien had DOS een filesystem (disk operating system...) En uiteraard werd er niet aan multi processings of scheduling gedaan, want de target processor ondersteunde dat niet (8086 etc). Pas op de 80386 was dat mogelijk (286 had geen goeie 'protected' protected mode...) en voila, daar was windows.
Windows 1.0 enzo deed anders multiprocessing zonder hardware support. Niet echt afgeschermd natuurlijk, maar toch. Bovendien had de 8086 allang timer interrupts en daar kun je dus mee schedulen/timeslicen.

[ Voor 57% gewijzigd door Soultaker op 17-06-2005 16:38 ]


  • miw
  • Registratie: November 2002
  • Laatst online: 23-02 13:02

miw

Maar wat is hardware? Software kan nooit achterhalen of de code door een CPU of een emulator wordt uitgevoerd. De vraag gaat eerder over de mogelijkheid om 1 binary in verschillende te kunnen laten draaien. Dat is in principe natuurlijk mogelijk. De problemen ontstaan wanneer je een interactie wilt aangaan met de gebruiker of andere applicaties. Voor dit soort taken maak je gebruik van OS specifieke API's. Het lijkt me verstandiger of een OS detectie routine te schrijven en dan de juiste aanroepen te plegen voor de functies die je in een applicatie nodig hebt. Dan krijg je uiteindelijk een universele binary die op een groot aantal OS/CPU combinaties kan draaien.

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
Als ik alle posts een beetje kan samenvatting, was DOS eigenlijk zowel een layer naast de programma's, waardoor programma's direct de hardware konden aanspreken en zo dus eigenlijk een soort kernel(modules) waren (met ints dus), als dat DOS een laag tussen de hardware en de programma's was (dus functies als printf(); aanspreken).

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
suntsu schreef op vrijdag 17 juni 2005 @ 16:27:
Maar wat is hardware? Software kan nooit achterhalen of de code door een CPU of een emulator wordt uitgevoerd. De vraag gaat eerder over de mogelijkheid om 1 binary in verschillende te kunnen laten draaien. Dat is in principe natuurlijk mogelijk. De problemen ontstaan wanneer je een interactie wilt aangaan met de gebruiker of andere applicaties. Voor dit soort taken maak je gebruik van OS specifieke API's. Het lijkt me verstandiger of een OS detectie routine te schrijven en dan de juiste aanroepen te plegen voor de functies die je in een applicatie nodig hebt. Dan krijg je uiteindelijk een universele binary die op een groot aantal OS/CPU combinaties kan draaien.
[theorie]Dus om een echte universal binary te schrijven (niet zo'n OS X ding) moet je in je code precies weten met welk OS je te maken hebt en welke interrupts je daarin mag aanroepen. Je zou zelfs multi-processor binaries kunnen maken, zolang de code waarmee je de CPU detecteert maar onder alle processors kan draaien.[/theorie]

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
Dan moeten alle OS'es ook nog hetzelfde binary formaat gebruiken en dan moet je dus elk mogelijk OS kunnen detecteren met bepaalde code die je applicatie nergens laat crashen; lijkt me erg lastig en ook niet zo zinnig, want wat je dan voorstelt is een andere library laden afhankelijk van op welk OS je draait; neem dan gewoon de libraries die op het OS voor handen zijn.

  • downtime
  • Registratie: Januari 2000
  • Niet online

downtime

Everybody lies

Werkelijk universele code schrijven is een utopie wanneer je programma vanuit een OS gestart moet worden. Alleen wanneer je iets schrijft wat z'n eigen mini-kernel bevat kun je OS onafhankelijk zijn. Helaas heb je dan feitelijk je eigen (beperkte) OS gemaakt.

Betere alternatieven zijn:

- Java of een geinterpreteerde taal/script
- C/C++ en gebruik van een POSIX API (die beheerst ieder modern OS wel). Maar dan heb je nog steeds geen universele binary maar kun je wel je programma simpel hercompileren voor een nieuw OS.

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
/downtime/ schreef op vrijdag 17 juni 2005 @ 16:59:
Werkelijk universele code schrijven is een utopie wanneer je programma vanuit een OS gestart moet worden. Alleen wanneer je iets schrijft wat z'n eigen mini-kernel bevat kun je OS onafhankelijk zijn. Helaas heb je dan feitelijk je eigen (beperkte) OS gemaakt.

Betere alternatieven zijn:

- Java of een geinterpreteerde taal/script
- C/C++ en gebruik van een POSIX API (die beheerst ieder modern OS wel). Maar dan heb je nog steeds geen universele binary maar kun je wel je programma simpel hercompileren voor een nieuw OS.
Wat ik opper is héél moeilijk, maar zou toch opzich kunnen wanneer je geen eigen kernel wil schrijven?

  • downtime
  • Registratie: Januari 2000
  • Niet online

downtime

Everybody lies

Vinnienerd schreef op vrijdag 17 juni 2005 @ 17:06:
Wat ik opper is héél moeilijk, maar zou toch opzich kunnen wanneer je geen eigen kernel wil schrijven?
Misschien. Maar is jouw vraag alleen maar filosofisch of heb je ook een praktische reden om zoiets te willen doen?
In het laatste geval kunnen we ons misschien beter richten op het probleem wat jij denkt op te lossen met een universele binary.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
/downtime/ schreef op vrijdag 17 juni 2005 @ 16:59:
- C/C++ en gebruik van een POSIX API (die beheerst ieder modern OS wel). Maar dan heb je nog steeds geen universele binary maar kun je wel je programma simpel hercompileren voor een nieuw OS.
Als Windows nu POSIX-compliant zou zijn, dan konden we er nog wat mee. ;) Voor de meeste toepassingen is Windows nogal een belangrijk platform; met je beperken tot POSIX ben je er dus helaas niet.

[ Voor 6% gewijzigd door Soultaker op 17-06-2005 17:17 ]


  • downtime
  • Registratie: Januari 2000
  • Niet online

downtime

Everybody lies

Soultaker schreef op vrijdag 17 juni 2005 @ 17:17:
Als Windows nu POSIX-compliant zou zijn, dan konden we er nog wat mee. ;) Voor de meeste toepassingen is Windows nogal een belangrijk platform; met je beperken tot POSIX ben je er dus helaas niet.
Windows (de NT-varianten tenminste) is POSIX compliant.

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 05-05 14:48
Vinnienerd schreef op vrijdag 17 juni 2005 @ 17:06:
[...]
Wat ik opper is héél moeilijk, maar zou toch opzich kunnen wanneer je geen eigen kernel wil schrijven?
Wat wil je met wat je oppert ("een universele binary") bereiken? Voor portabiliteit van software zijn goede oplossingen beschikbaar.

[ Voor 5% gewijzigd door matthijsln op 17-06-2005 19:15 ]


  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 17:59
Ik opper het als een leuk experiment/challenge, maar praktisch gezien is het natuurlijk onzin. Dan kun je beter een wrapper-library schrijven.

[ Voor 4% gewijzigd door Vinnienerd op 17-06-2005 20:24 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
/downtime/ schreef op vrijdag 17 juni 2005 @ 17:21:
Windows (de NT-varianten tenminste) is POSIX compliant.
Echt onzin; POSIX.1 misschien. Maar de meest simpele calls als select of fcntl zijn niet geïmplementeerd; van FAT32 klopt sowieso niets. Verder zijn er geen POSIX threads, komt het access/security model niet overeen, geen signals, enzovoorts enzovoorts. Het is makkelijker om te zeggen welke POSIX features Windows wel ondersteund dan op te sommen op welke punten ze allemaal te kort schieten.

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 05-05 14:48
Soultaker schreef op vrijdag 17 juni 2005 @ 20:32:
[...]

Echt onzin; POSIX.1 misschien. Maar de meest simpele calls als select of fcntl zijn niet geïmplementeerd; van FAT32 klopt sowieso niets. Verder zijn er geen POSIX threads, komt het access/security model niet overeen, geen signals, enzovoorts enzovoorts. Het is makkelijker om te zeggen welke POSIX features Windows wel ondersteund dan op te sommen op welke punten ze allemaal te kort schieten.
Ik moet zeggen dat de POSIX ondersteuning van Windows XP voor mij wel handig was; via de normale Windows weg was het niet mogelijk om een directory met spaties aan het eind van de naam te verwijderen (hoe die is onstaan is mij nog een raadsel), met een tool uit Microsoft Services For Unix die de POSIX laag gebruikte was het wel mogelijk :)

Maar inderdaad, niemand gebruikt volgens mij serieus de POSIX laag van Windows om portable applicaties voor te schrijven. Meestal wordt er gewoon een laag bovenop de Windows API gemaakt; zoals bijvoorbeeld SDL, apr, 1000 en 1 GUI toolkits etc.

Naar ik heb gehoord is de POSIX laag alleen ontwikkeld omdat het een vereiste was van de Amerikaanse overheid.

Verwijderd

.oisyn schreef op vrijdag 17 juni 2005 @ 15:16:
[...]

Als dat zo is, waarom zouden ze in hemelsnaam die keuze gemaakt hebben? Een int voldoet toch ook prima, heb je bovendien meer mogelijkheden.
Een illegal instruction exception was een paar cycles sneller, en dat scheelde genoeg.
/downtime/ schreef op vrijdag 17 juni 2005 @ 17:21:
[...]

Windows (de NT-varianten tenminste) is POSIX compliant.
Alleen POSIX 1, dus dat was alleen nuttig om Windows te verkopen aan managers.
Pagina: 1