0

I know people going to hate me for not even showing any code, but in theory, how can an assembly program, for example, show a functioning menu and play a song at the same time? or like play a game and have a timer at the same time, how it is possible?

I don't see how this can be done because the processor has only one code segment, maybe I can make 2 assembly files and the processor somehow will work with it?

Erik Gelfat
  • 293
  • 1
  • 9
  • Assembly is just a lower-level representation of what you want the computer to do. If you can multitask in any other programming language, you can multitask in assembly. – Thomas Jager Aug 07 '19 at 17:21
  • @ThomasJager well it's obvious, but I am asking how it's possible – Erik Gelfat Aug 07 '19 at 17:27
  • 1
    In your title and most of your first paragraph you explicitly ask whether or not it's possible. In your second paragraph you state that you don't see how it is possible. So the fact that you're now saying that it's obvious is confusing. – Thomas Jager Aug 07 '19 at 17:29
  • @ThomasJager alright, I will change it – Erik Gelfat Aug 07 '19 at 17:31
  • There is only one code segment but it can be changed.If you want to have two different processes you could put them in different code segments that don't overlap.You'd also need them to have separate stack. You would have to write code that performs a task switch by saving all the current segment and general purpose registers and then switch to a different CS:IP, SS:SP and restores all the registers of the task you want to switch to. This is quite complex. But my question is - do you want different tasks or are you simply trying to play music in the background while your program runs? – Michael Petch Aug 07 '19 at 17:32
  • @MichaelPetch - thank you for your response, yes this is complex but it's very do-able, thank you very much, for your question, I just want to have the skill to do both, the multitasking and the music, why? is there a better way to do it? – Erik Gelfat Aug 07 '19 at 17:38
  • 2
    Since you tagged this as `tasm` I assume you are writing this for DOS. If your intention is to play background music are you doing it through the PC speaker or are you playing music through a sound device like soundblaster, adlib etc.? It is possible to write an interrupt routine that hooks to the timer interrupt that plays the music in the case of the PC speaker. With other devices you may be able to use DMA to play music. – Michael Petch Aug 07 '19 at 17:42
  • @MichaelPetch You are totally right, I am writing this for DOS, how you can see my school uses the latest tech ;D, and yes I am using the PC speaker, thank you for your answer – Erik Gelfat Aug 07 '19 at 17:48
  • 1
    This other question (and there is an answer with some different idea) may be helpful: https://stackoverflow.com/questions/48507031/assembly-playing-audio-file-tasm-16-bit/48521522#48521522 – Michael Petch Aug 07 '19 at 17:51
  • DOS is not dead it is very much alive in this world. Are you running an x86 pc perhaps, couldnt have bought it because it cant be built without dos. – old_timer Aug 08 '19 at 02:46
  • assembly language really isnt relevant here. C, C++, whatever these all boil down to assembly and or machine code which you get from assembly. even interpreted languages like python and java, the virtual machine is written in a non-virtual langauge and compiled. you can have one assembly language file and multi task that with a multi-core/threaded processor and or by time slicing and giving some time to some of the code and some time to the other. you can do this in one code segment, that is not relevant either. – old_timer Aug 08 '19 at 02:48
  • the concept is either you have separate processors running code from the same or separate places. or if you dont have multiple processors then one processor runs one thing at a time and you ping pong between things fast enough to make it look like two things are happening. sometimes the OS helps, sometimes the hardware helps. – old_timer Aug 08 '19 at 02:49
  • google TSR if you have not already, terminate and stay resident. that was the classic way to do this you run a program it saves all or part of itself resident in memory, it hooks an interrupt or few, and releases dos back. Unless the next program takes over that/those interrupt(s) then your other program can continue to handle them. the hard part comes when you want to use dos/bios calls, you have to preserve the state of other programs that are running, do your thing, then restore their state. – old_timer Aug 08 '19 at 02:52
  • I thought the newer dos clones (as in new 15 years ago, still strong today), already took care of multithreading? it has been decades for me now, but you can easily hook one of the timers by putting your handler in there then calling the prior handler. terminate and stay resident, and have your program every so many interrupts do something visible or audible to the outside without using a dos/bios call. send a character out the uart/serial port, etc...start there and work your way up... – old_timer Aug 08 '19 at 02:55
  • if you have not done interrupts yet then start there without doing any tsr stuff. that is enough fun as is, and work from there. – old_timer Aug 08 '19 at 02:58
  • do you want to play the game and play music with the music not being managed by the game? if they are connected, then make one program that manages all of it and not try to get into multi-tasking. probably easier to get a $2-$20 arm based board and start there bare metal than try to deal with dos and x86, dos does a lot for you but x86 isnt all that fun. you need to learn to program the peripheral in question, you need to learn about interrupts, and if on dos then dos/bios internals, etc, etc. – old_timer Aug 08 '19 at 03:00
  • originally windows was simply a baremetal program that ran on dos. and took over the system. now it doesnt need dos to boot. you can take that approach to a dos program or dos launched program that manages all of these things together, non-dos programs running in "parallel"...hard to tell what you are asking here. – old_timer Aug 08 '19 at 03:02

2 Answers2

5

If I understand your question properly, you want to know how multi-tasking -- the continuous forward progress of unrelated programs -- works. If you have as many cpus as things to do, it is easy -- use a cpu for each. If you don't, you need to share them, by rapidly switching between the programs. This rapid switching works well if either the programs spend a significant time waiting for external I/O to operate, or do not require the entire computational ability of the cpu.

For example, if you wanted to generate a pure sine wave on the speaker, you would need to produce an audio sample every 22 microseconds (usec) which is 1 / 44,000, the standard rate for audio reproduction. If it took 0.5usec to switch between processes; 0.1usec to compute sin(), and 1 usec to toggle the speaker; you would only use (0.5+0.1+1)/22 about 7% of the cpu to do this, leaving 93% of the cpu available for other programs.

There are hidden complexities and simplifications in this example. Something needs to know that your code needs to be run every 22 usec; and that a failure to run your code has dire consequences (if pop and crackle are dire). But once you fill in the details, that is about it.

OK, the actual question:

A single program can also split its attention between multiple activities. The most common method people use for this is threads. Two threads share an address space, but have private register sets, and somewhat private stacks. In a system that supports fully independent threads, one could perform the audio operation outlined above, while another remained in a more typical MVC pattern. A potential problem is that various runtimes might have hidden synchronization, which could cause unexpected latency.

Without threads, it becomes increasingly difficult. The UNIX signal concept permits a relatively asynchronous function call to be scheduled with respect to some event, like a timer going off. So the audio example could be performed by a signal handler. The complexity here can be harrowing, since your library may have to deal (perfectly) with system calls that sporadically fail with EAGAIN; while many system calls are themselves restartible this is not guaranteed. A related problem is that some system calls (or even library functions) may temporarily inhibit signals, which could cause the audio program to miss its deadlines.

Without signals, it is very difficult. You need to analyze your program to find every point where it waits for an event (eg. reading from a keyboard), and change those to asynchronous operations. Then you have to sprinkle code throughout your program to check if it is time to put an audio sample to the speaker. Given the 22usec requirement, that is a lot of sprinkles. Once you are finished, you will probably be unable to convince anybody that it works.

mevets
  • 10,070
  • 1
  • 21
  • 33
  • I appreciate your answer, but you understood me wrong, even though this answer is really informative and interesting, I meant that a program will do 2 things at a time, not unrelated programs, but I really appreciate your answer. thank you. – Erik Gelfat Aug 12 '19 at 16:26
0

This scheduling of multiple tasks (threads) is usually what an operating system is used for, it provides the overhead to set timers which cause an interrupt at the processor, which makes it save its current program counter and register contents etc and load the program counter and register contents of the next task (thread) and resume working on it.

Timers are often part of an processor so to say, a specific assembly instruction will set it going in the background (=in hardware) without any action required by the processor. Only when the timer expires, an interrupt flag shows up to the processor, which then will save its current state and jumps to a predefined place where you (or the operating system) will have saved the code which will determine what the processor should do next.

Tanque
  • 315
  • 3
  • 16