⍕ · 2017-06-14 09:20
A particularly interesting topic that doesn't receive much attention anymore is the loading of a program on a newly started machine. This is a crucial topic in computing and yet a largely monoculture computing world has lead to this being largely forgotten and considered unimportant.
When a computing machine activates, it has a defined state of some sort and generally begins its work; this can include all memory having uncertain contents, other state having uncertain configurations, but also any aspect of the machine having very clearly defined states that can be relied upon, among yet other possibilities; a machine generally begins doing something in order to then load a program, which may be loaded simply to load another program. Follows are some examples:
The IBM PC has a BIOS, which is a ROM that the processor begins executing from a specified address when the machine is powered on. This BIOS then generally aids the process of loading an operating or loading system from the backup storage of the machine. The BIOS also contains procedures for ascertaining what hardware is available and interfacing such and whatnot, along with initializing certain hardware to defined states.
Virtual machines typically load memory with a program using out-of-band control provided by a host and then begin executing from a well defined address. It would be fair to remark that anything else would be inefficient and a waste of cycles, for a machine that doesn't exist with such constraints as physical hardware. Some virtual machines, such as CHIP-8, do have internal state exposed that must be initialized in some form before beginning, but this is also generally done with the host.
The Pilot ACE, mentioned in the images, used mercury delay line memory and so all of these were filled with zeroes upon starting; little other internal state would then be set to zero as the machine began work; the use of all zeroes as a valid instruction was instrumental to how the machine loaded a program, as it would wait for ready input to then directly execute instructions from the input.
Other machines have yet different and interesting methods. Still, the topic receives little attention, nowadays, it seems. Do feel free to explain how a machine you enjoy loads its first program and feel free to delve into more detail on the machines already mentioned. What aspects of these machines do you find interesting; which would you change if given the chance; how would you design a machine with regards to this?
Faye Valentine · 2017-09-11 10:24
I've read about this subject with regard to older video game consoles. They too begin executing code at a specific address after being powered on. The first program was usually included with the machine in the form of basic initialization code that would then jump to the code in the connected cartridge, which also started at a pre-determined address. The software included with CD-based machines was far more elaborate than the ones found in cartridge-based consoles; seems Playstation games would often if not always use it for disc I/O.
I've been reading all I could find on linkers and loaders as well as the ELF object file format. It's one of those things that happen invisibly and nobody even pays them a second thought until it breaks and arcane knowledge is required to figure out why. I wanted to understand how C libraries would get linked together to form actual programs and it's actually a pretty cool format. The kernel's program loader reads in the object file and builds an ELF data structure, allocates and initializes memory for the sections contained in it, resolves symbolic references to variables and functions by replacing them with the addresses within the newly-allocated memory range; it generally takes everything and puts it into place. Really cool. I'm trying to make my own dlopen dlsym dlclose functions as practice.
Hacker · 2017-09-12 00:48
Low-level/embedded stuff incoming.
>AVR Microcontrollers (Atmega328p)
A microcontroller is a small computer. It has a processor, RAM, non-volatile memory (either UV-erasable EPROM in very old microcontrollers, or Flash+EEPROM memory in newer ones) and support for peripherals (like driving input/output ports to light up LEDs or even more complex peripherals like USB or Ethernet MAC/PHY) built into a single integrated circuit.
>Startup
After a power-on event, the AVR will always start execution from the 'Reset Vector', at 0x0000 from flash memory. The reset vector is the first entry in the 'interrupt table', and is usually jmp ResetHandler. This will direct the program flow to your application code. The next entries in the table handle other interrupt sources, like a timer overflow, or if a pin is asserted with a high value. However, if you never use interrupts, you can place all of your application code at 0x0000 and upon reset, your application will start executing immediately.
AVR datasheet - interrupt table section pg. 82
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf
>Getting Code onto an AVR
(the usual method - SPI serial downloading)
The microcontroller comes with internal circuitry that will allow you to use an uploading hardware tool (called an 'in-system programmer' - examples: AVRISP or USBASP dongle) in order to write to the flash memory. The uploading tool uses the SPI protocol and communicates with the microcontroller by holding it in a reset state. Using this, you can upload your compiled/assembled program onto the microcontroller.
ISP programming details:
http://www.atmel.com/Images/Atmel-0943-In-System-Programming_ApplicationNote_AVR910.pdf
(the other method - bootloading)
A bootloader in this case, is application code that will use AVR's flash-programming instructions to read and write to sections of flash memory. This allows you to communicate with the microcontroller using something like USB or UART (allowing updates in the field), and avoid the use of the in-system programming hardware.