I am interested in building certain components of computer processors with the use of discrete components only. I want to build on the individual component level (transistors, resistors, caps) and not on the gate level (quad and gate or hex inverter ic) and I have run into some problems.
I have a few questions and they are large. If you can answer any of them I would be glad but could you number them so I know which one you are talking about.
((1)) My first question is about how to build logic gates with discrete components. I have seen some schematic diagrams for and gates, or gates and inverters; they all seem to have some problems. For example, an and gate might have two bjt's where the base of each is an input.

My question stems from the saturation voltage of transistors. I assume that in logic circuits you want a transistor to act as a switch, and thus would want to make sure that the voltage drop is 0. I learned that to do this, you find the resistance value of the load you are trying to run and figure how much current it would take for the voltage drop to be Vcc. (Light bulb has a resistance of 100ohms, Vcc is 10V, V=IR dictates that the current running through the light bulb would be .1A). Then you divide this current by B (gain of transistor) to find the current that needs to be running through the base emitter path.
How do you find the load of a computer, where the output of a circuit might run through paths of great or little resistance? Is there a way to make logic circuits with transistors acting like switches while avoiding finding the saturation voltage?
((2)) How are computers made so that they can sit idle and then respond to inputs. This might sound like a stupid question but from a programming perspective the only way I could think to do it would be to create an infinite loop that constantly checks for inputs or a 1 in some input register.
The more I think about it the more it seems possible that this is how computers do it now; I know that the're able to run many programs at once so it seems possible. However, how did early computers do it? If a computer had only the capacity to run one program at a time then it seems a program accepting inputs would always have to come to a halt when an input is requires.
Is this truely the only way? How do modern computers accept inputs, how do computers that can only run 1 program at a time accept inputs?
((3)) I am also interested in memory circuitry. Looking at the types of ram, dram seems to be pretty strait forward. As I understand it sram is essentially memory made of logic grates where an outside signal initially acts as an input. The output of the logic circuit is then feed back in as an input and the circuit hold "itself" high or low (this description might be totally wrong). The problem is I have only seen schematics that show sram using CMOS. Is there a way to build sram using bjt's?
((4)) I have also had a chance to look at how rewritable rom (despite being read only) such as flash memory works. My first question is, why is this called read only? I get that it is nonvolatile so it's not ram, but it surely isn't read only memory either!
Are there any ways to make rewritable rom with discrete components? Flash involves, to my understanding, trapping electrons with some kind of tunneling. As far as I know, this can only be done in silicon. If I were to make some sort of computer (or more accurately: a device that demonstrates the properties of a computer) would the non volatile memory be limited to non-electrical things (brain, punch card, magnetic memory)?
((5)) How are jumps done in the opcode level? Assembly has specific commands for different types of jumps. Lets say you are running an 8 bit computer that had 8 bits of memory at each address, can't you only address 256 addresses (0 to 255)? Lets say the 8 bit computer processor has 128 unique operations, and an unconditional jump happens to be the 100th operation. In the memory you write your program to, the jump would be written as 1100100 (100 in decimal, the jump command). There would only be 1 bit left, hardly enough room to write the address of where you are actually trying to jump to.
My only conclusion is that you would tack a 0 to the front of the jump command making 01100100 and filling up the whole byte of memory. Then, when the computer reads the byte it recognizes the opcode for unconditional jump and reads the next byte of memory as the location of the jump and not as a specific jump. Thus if you were trying to write an unconditional jump to address zero, the program would look like:
........
........
01100100
00000000
Is this how computers perform operations containing operational code and memory addresses that are written as one line in assembly code?