Jeśli chodzi o Assemblera to bym polecił stronkę
http://bogdro.ciki.me/ ale niestety ostatnimi czasy nie działa a ja posiadam zarchiwizowane materiały jedynie pod Linuxa. Mogę jeszcze zaproponować
https://pl.wikibooks.org/wiki/Asembler_x86 z którego często korzystam przy zabawie w asm.
Co do kodu, "int 21h" jest to przerwanie DOSowe, powoduje że procesor zaczyna wykonywać w tym momencie "program" systemowy. Tak w skrócie, do rejestrów wstawiasz odpowiednie wartości np. do rejestru dx wstawiasz offset "napisu" czyli wskaźnik na pierwszy bajt twojej zmiennej czyli na "H". Do rejestru ah wstawiasz 09h ( h oznacza że jest to liczba szesnastkowa) co przy przerwaniu informuje jaki typ operacji żądasz, w tym przypadku wypisania łańcucha znaków. Następnie masz "int 21h", w tym momencie procesor zaczyna wykonywać kod systemowy. Mniej więcej wygląda to tak że jakiś kod porównuje to co jest w ah, jako że jest tam wartość 09h to przeskakuje do części kodu odpowiadającej za wypisywanie liter, tam program zaczyna operować na rejestrze dx, sczytuje kolejne bajty aż napotyka '$' co oznacza że to koniec tekstu i następuje powrót do twojego programu. Analogicznie jest z zakończeniem programu, również umieszczasz w rejestrze ax wartość i wykonujemy przerwanie. Podana wartość dla systemu oznacza że program ma się zakończyć (system zwalnia pamięci, usuwa proces itp.)
A teraz dlaczego ax i ah wpływa zdawało by się tak samo na przerwanie? Masz to tutaj:
https://pl.wikibooks.org/wiki/Asembler_x86/Architektura#Rejestry_og.C3.B3lnego_przeznaczenia
Podeślę jeszcze zarchiwizowane materiały ze strony bogdro.ciki.me dla Linuxa:
https://www.zeta-uploader.com/1328114545 może się przyda.