rbj said:
printf() and scanf() are in C, but they call putc() and getc(). the latter two functions talk to the hardware and may or may not be in C. C is pretty low-level, but i imagine the code that transfers dot patterns to the screen for a particular character are in assembly.
On VGA (CGA, EGA, Hercules) card in text mode you don't have to care about dots, you just put the ASCII code into the card memory (I think starting at 0xB800:0000, but there were some minor diffrerences between cards & modes) and it is displayed using card font. Every character is described by two bytes - one is character itself, the other its attributes (colors of the letter and the background, brightness, blinking). So in the text mode there was no need to draw the points.
Things got more complicated in the graphics modes. If memory serves me well, it was still possible to call BIOS to make it draw a letter using the standard font, but I am not sure if it was guaranteed to work, and BIOS calls for graphic modes were notoriously slow, so it was much better to do all the work by yourself. That was not easy due to the way VGA memory is organized (EGA was similar, and I never worked with CGA). To draw a single pixel in 16 color mode you had to switch between memory planes, as the information about a pixel was stored in 4 different places. On the one hand that meant a programming nightmare in 16 colors, on the other - people were getting creative and half of the PC demoscene was using these modes to get effects that IBM engineers never dreamed about
In 0x13 mode - 320*200*256 colors - things were pretty easy, one memory plane and linear addressing of the pixels, as they all fit in one 64k bank. That was favorite mode for many applications. But there was also another 256 colors mode, so called x-mode, that used memory planes. Addressing was much more tricky, but it was possible to use other resolutions, double or even triple buffering, and in some cases x-mode was faster, as it allowed writing to all four planes with one instruction.
All these things required direct access to the memory and I/O ports. I was doing it in Turbo Pascal at the time. Sadly, when my favorite piece of code made its way to SWAG it didn't bear my name on it (http://webtweakers.com/swag/GRAPHICS/0155.PAS.html ). Perhaps this one: http://webtweakers.com/swag/GRAPHICS/0174.PAS.html shows better the combination of memory and I/O ports access we used at the time.