Di solito ho trovato reference integrati con i compilatori, vedi MSDN del Visual Studio. Molto probabilmente ce ne sono sulle librerie standard C e C++; di sicuro so solo che la Win32 API Reference ufficiale Microsoft in giro si trova, perché io ce l'ho. Ma riguarda solo Windows. Cmq mi pare che hmesfet avesse postato qualcosa a riguardo di recente, quindi magari fai una piccola ricerca nel forum...
DOS e Windows? Beh sono diversi!
Io da parte mia adoro il DOS perché ti permette di accedere direttamente a memoria e hardware, e quindi ti permette anche di "destreggiarti" con l'assembly in modo proficuo. In Windows accedi a tutto tramite l'API, quindi l'uso dell'assembly è limitatissimo.
C'è da fare tuttavia una grossa differenziazione fra DOS in modalità reale 16-bit (quella naturale) e DOS in modalità protetta 32-bit (accessibile tramite i leggendari DOS-extenders come il DOS4GW, quello di tanti giochi DOS, per intenderci..). Il DOS a 32-bit è molto simile a Windows per certi aspetti, dato che anche Windows gira in modalità protetta 32-bit.
Stesso discorso non vale invece per il DOS reale! A me capitava spessissimo di chiedermi, soprattutto quando provavo a far partire qualche vecchio videogioco per DOS, per quale motivo digitando /mem e avendo ben 16 MB di RAM (un'infinità a quei tempi!) il PC vedesse solo quei miseri 640 kb di memoria! Uno strazio! E allora ci si metteva a smanettare con i DEVICEHIGH nel Config.sys e i LH nell'Autoexec.bat ... e dopo tanto penare il gioco partiva. Il motivo risiedeva nella disposizione della memoria in modalità reale 16-bit: la memoria segmentata.
Già l'80386 aveva registri a 32-bit, eppure il DOS ha sempre sfruttato, di sua natura, la modalità reale 16-bit. In C (e sugli Intel), 16-bit corrispondono ad uno 'short', ovvero un numero che varia da 0 a 65535 (0xFFFF in esadecimale), per un totale di 65536 valori assumibili (65536 bytes = 64 kb). In pratica, con un registro si potevano indirizzare fino a 64 kb di memoria (puntatore near, vicino, nello stesso segmento), pochina per noi, ma ai tempi della progettazione anche sufficiente. Tuttavia ci si "preparò al futuro", e ci si inventò un nuovo metodo di indirizzamento, segmentoffset (puntatore far, lontano, con overriding del segmento), costituito da due registri a 16-bit, ma che in effetti era un indirizzo a 20-bit (2^20 bytes = 1 MB):
segmentoffset = segmento * 16 + offset = segmento * 10h + offset (16 è 10h in esadecimale)
A000:000F (segmentato) = A000 * 10 + F = A000F (lineare)
Quindi 20 bits di cui i meno significativi sono i 4 bits meno significativi dell'offset, e gli altri 16 sono costituiti dall'intero registro di segmento.
Con questo metodo di indirizzamento (senza scendere nei particolari dell'implementazione) si poteva quindi indirizzare 1 MB di memoria, che allora era tantissimo!
Quindi, a prescindere dalla memoria totale che possieda un PC, un processore Intel in modalità reale 16-bit può accedere solo al primo MB di RAM. Perché 640 kb? Perché i restanti 384 kb (640 + 384 = 1024 kb = 1 MB) sono riservati al BIOS e al sistema operativo. Diciamo che questa è la principale difficoltà della programmazione in DOS reale.
Cmq se programmi in C/C++ le differenze fra DOS e Windows appaiono relativamente, perché i problemi della memoria se li accolla il compilatore. Programmare in assembly per DOS reale invece è davvero una cosa PAZZESCA e oramai anche parecchio obsoleta, soprattutto se poi vuoi accedere a tutta la RAM e non solo ai 640 kb di memoria convenzionale, attraverso quindi XMS (memoria estesa) ed EMS (memoria espansa).
Invece in Windows e in DOS 32-bit il tipo indirizzamento è lineare (FLAT) a 32-bit (che spiega la dimensione fissa di 4 bytes di un qualsiasi puntatore, equivalente ad un 'long' in C/C++, sempre parlando dei processori Intel, s'intende), e quindi un puntatore può indirizzare fino a 2^32 = 4 GB di RAM! Bel cambiamento eh? E supportato dall'80386 fino ad ora, almeno per quanto riguarda gli Intel. Ma arriverà sicuramente il momento in cui sarà obsoleta anche questa architettura...
Ciao.