Ассемблер, я правильно понимаю что по умолчанию в регистрах 0x00?
А если принять к факту, что по умолчанию в регистрах хранится значение 0x00
Ничего в регистрах "по умолчанию" не хранится, кроме того, что в них в последний раз было записано.

я попробовал ничего не записывать в регистр AH и вызвать прерывание 0x16, значит по умолчанию в регистре 0x00.
Нет, это значит только то, что в этом месте твоей программы в этот раз в регистре AH был 0.

в подпрограмме read_keyboard почему то не сохраняют регистр AX
Потому что результат возвращают в нём.

почему сохранили регистр BX - я не понял
…а также cx, dx, si и di. При том, что функция 0 int 16 меняет только AX. Я думаю, что на всякий случай их сохранили, для надёжности.
Я рекомендую обязательно смотреть документацию, чтобы четко понимать какие регистры используют входные данные, и куда помещается результат.
push и pop в данном случае используются чтобы сохранить значения регистров, а затем восстановить их. Однако вызываемые функции НЕ ИСПОЛЬЗУЮТ эти регистры. И сохранение/восстановление не имеет никакого смысла.
int 10
0eH писать символ на активную видео страницу (эмуляция телетайпа)
вход:  AL = записываемый символ (использует существующий атрибут)
           BL = цвет переднего плана (для графических режимов)

display_letter:
mov ah, 0x0E ; код функции которая выводит букву на экран
mov bx, 0x000F ; 00 - нулевая страница; BL - цвет буквы
int 0x10 ; обращаемся к BIOS, чтобы она нарисовала букву
int 16
00H читать (ожидать) следующую нажатую клавишу
выход: AL = ASCII символ (если AL=0, AH содержит расширенный код ASCII )
            AH = сканкод  или расширенный код ASCII

read_keyboard:
mov ah, 0x00 ; код функции считывающей символ с клавиатуры
int 0x16 ; обращаемся к BIOS чтобы выполнить ее