Ratch:
True. Not scientifically correct, but it sure would be easier than reading compiled LISP or COBOL in assembly.
True. Not scientifically correct, but it sure would be easier than reading compiled LISP or COBOL in assembly.
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
No it does not, the difference is that exceptional programmers can make a computer run dozens, hundreds, if not thousands of times more efficiently if they're applied properly. The comparison to the human example you gave would be a runner that can run 1000 miles per hour.
Also if I ever need precise cycle accurate timing, I would go for a CPLD/FPGA + micro solution rather than a processor based solution. The moment you use 1 interrupt, your adding some timing uncertainty.
It's all horses for courses at the end of the day. Some people want to get a job done in the shortest time (which is where my hobby projects fall in these days), where as others will enjoy (or be forced in industry!) the learning process of using say a slightly underpowered micro to do something impressive.
Have you ever programmed microcontrollers with C? Can you show an example where ASM "has far more control and precision" than C.
Hi MrT,
It's very hard to know what kind of code a C compiler is going to produce. You can look at the source code for some compilers but i dont know too many people who want to take the time to do that..
I started out with microsoft assembler using MASM611 programming 8086, 286 and 386. Then I dabbled with C++ and Visual C++, was not long before I went back to assembly.
Was not impressed with overhead and using someone else's programs that I had no control of or limited amount of control.
I once wrote a simple multitasking kernel with C and inline assembly. To make the whole system "for general use", I had to save (and load) the whole execution context on every task switch. This means pushing 32+ registers to the stack and then popping another set of registers from another stack.. waste of time and memory, but that is usually the case when you have to write something that is "general purpose".
IMPLEMENTATION MODULE NEWSYS; (*$S-,$T- *)
FROM SYSTEM IMPORT ADDRESS,CODE,SETREG,REGISTER,ADR;
FROM GEMDOS IMPORT Super,Alloc,Free;
TYPE trappointer = POINTER TO PROC;
processpointer = POINTER TO ADDRESS;
TYPE iotype = RECORD
p1 : processpointer;
p2 : processpointer;
device : ADDRESS;
END;
VAR pc,ssv : ADDRESS;
io1,io2 : processpointer;
sr,function : CARDINAL;
iotranspointer : iotype;
trap : trappointer;
pr1,pr2,wsp : ADDRESS;
n : LONGCARD;
init : BOOLEAN;
PROCEDURE NEWPROCESS(processProc : PROC;
workspace : ADDRESS;
worksize : LONGCARD;
VAR process : ADDRESS);
BEGIN
IF NOT init THEN
INITPROCESSES;
END;
workspace:=workspace+ADDRESS(worksize);
SETREG(6,ADDRESS(processProc));
SETREG(8,workspace);
CODE(2106H); (* move.l d6,-(a0) PC *)
CODE(313cH,0300H); (* move.w $0300,-(a0) CCR *)
CODE(48e0H,0fffeH); (* movem.l d0-d7/a0-a6,-(a0) *)
process:=REGISTER(8);
END NEWPROCESS;
PROCEDURE TRANSFER(VAR p1,p2: ADDRESS);
BEGIN (* pass p1 and p2 as the location of these variables *)
IF NOT init THEN
INITPROCESSES;
END;
SETREG(0,ADR(p2));
CODE(2f00H); (* move.l d0,-(sp) *)
SETREG(0,ADR(p1));
CODE(2f00H); (* move.l d0,-(sp) *)
CODE(3f3cH,1); (* move.w #1,-(sp) *)
CODE(4e49H); (* trap #9 *)
CODE(0dffcH,0,10); (* add.l #10,sp *)
END TRANSFER;
PROCEDURE IOTRANSFER(VAR p1,p2: ADDRESS; device: ADDRESS);
BEGIN (* pass p1 and p2 as the location of these variables *)
IF NOT init THEN
INITPROCESSES;
END;
SETREG(0,device);
CODE(2f00H); (* move.l d0,-(sp) *)
SETREG(0,ADR(p2));
CODE(2f00H); (* move.l d0,-(sp) *)
SETREG(0,ADR(p1));
CODE(2f00H); (* move.l d0,-(sp) *)
CODE(3f3cH,2); (* move.w #2,-(sp) *)
CODE(4e49H); (* trap #9 *)
CODE(0dffcH,0,14); (* add.l #14,sp *)
END IOTRANSFER;
(*$P- *)
PROCEDURE PTRAP;
BEGIN
CODE(043374B,2700H); (* disable ints *)
CODE(48e7H,0fffeH); (* save regs movem *)
CODE(306fH,60); (* move.w 60(a7),a0 get sr *)
sr:=CARDINAL(REGISTER(8));
IF sr>3fffH THEN (* called from supermode, not valid *)
CODE(4cdfH,7fffH); (* restore regs movem *)
CODE(4e73H); (* rte go back to where we came from *)
END;
CODE(4e69H); (* move.l usp,a1 *)
CODE(3069H,0); (* move.w 0(a1),a0 *)
function:=CARDINAL(REGISTER(8));
CODE(4e69H); (* move.l usp,a1 *)
CODE(2069H,2); (* move.l 2(a1),a0 *)
iotranspointer.p1:=REGISTER(8);
CODE(4e69H); (* move.l usp,a1 *)
CODE(2069H,6); (* move.l 6(a1),a0 *)
iotranspointer.p2:=REGISTER(8);
CODE(4e69H); (* move.l usp,a1 *)
CODE(2069H,10); (* move.l 10(a1),a0 *)
iotranspointer.device:=REGISTER(8);
CASE function OF
1 : CODE(4e68H); (* move.l usp,a0 TRANSFER *) (* SAVE *)
CODE(0dffcH,0,42H); (* add.l #66,sp *)
CODE(2127H); (* move.l -(sp),-(a0) D0 *)
CODE(2127H); (* move.l -(sp),-(a0) D1 *)
CODE(2127H); (* move.l -(sp),-(a0) D2 *)
CODE(2127H); (* move.l -(sp),-(a0) D3 *)
CODE(2127H); (* move.l -(sp),-(a0) D4 *)
CODE(2127H); (* move.l -(sp),-(a0) D5 *)
CODE(2127H); (* move.l -(sp),-(a0) D6 *)
CODE(2127H); (* move.l -(sp),-(a0) D7 *)
CODE(2127H); (* move.l -(sp),-(a0) A0 *)
CODE(2127H); (* move.l -(sp),-(a0) A1 *)
CODE(2127H); (* move.l -(sp),-(a0) A2 *)
CODE(2127H); (* move.l -(sp),-(a0) A3 *)
CODE(2127H); (* move.l -(sp),-(a0) A4 *)
CODE(2127H); (* move.l -(sp),-(a0) A5 *)
CODE(2127H); (* move.l -(sp),-(a0) A6 *)
CODE(3127H); (* move.w -(sp),-(a0) SR *)
CODE(2127H); (* move.l -(sp),-(a0) PC *)
iotranspointer.p1^:=REGISTER(8); (* set p1 to process *)
SETREG(8,iotranspointer.p2^); (* load p2 to a0 RESTORE *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D0 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D1 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D2 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D3 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D4 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D5 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D6 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D7 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A0 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A1 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A2 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A3 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A4 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A5 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A6 *)
CODE(3ed8H); (* move.w (a0)+,(sp)+ SR *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ PC *)
CODE(9ffcH,0,42H); (* sub.l #66,sp *)
CODE(4e60H); (* move.l a0,usp *)
CODE(4cdfH,7fffH); (* restore regs movem *)
CODE(4e73H); | (* rte *)
2 : CODE(4e68H); (* move.l usp,a0 IOTRANSFER *) (* SAVE *)
CODE(0dffcH,0,42H); (* add.l #66,sp *)
CODE(2127H); (* move.l -(sp),-(a0) D0 *)
CODE(2127H); (* move.l -(sp),-(a0) D1 *)
CODE(2127H); (* move.l -(sp),-(a0) D2 *)
CODE(2127H); (* move.l -(sp),-(a0) D3 *)
CODE(2127H); (* move.l -(sp),-(a0) D4 *)
CODE(2127H); (* move.l -(sp),-(a0) D5 *)
CODE(2127H); (* move.l -(sp),-(a0) D6 *)
CODE(2127H); (* move.l -(sp),-(a0) D7 *)
CODE(2127H); (* move.l -(sp),-(a0) A0 *)
CODE(2127H); (* move.l -(sp),-(a0) A1 *)
CODE(2127H); (* move.l -(sp),-(a0) A2 *)
CODE(2127H); (* move.l -(sp),-(a0) A3 *)
CODE(2127H); (* move.l -(sp),-(a0) A4 *)
CODE(2127H); (* move.l -(sp),-(a0) A5 *)
CODE(2127H); (* move.l -(sp),-(a0) A6 *)
CODE(3127H); (* move.w -(sp),-(a0) SR *)
CODE(2127H); (* move.l -(sp),-(a0) PC *)
iotranspointer.p1^:=REGISTER(8); (* set p1 to process *)
io1:=iotranspointer.p1;
io2:=iotranspointer.p2;
SETREG(8,iotranspointer.p2^); (* load p2 to a0 RESTORE *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D0 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D1 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D2 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D3 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D4 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D5 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D6 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D7 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A0 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A1 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A2 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A3 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A4 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A5 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A6 *)
CODE(3ed8H); (* move.w (a0)+,(sp)+ SR *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ PC *)
CODE(9ffcH,0,42H); (* sub.l #66,sp *)
CODE(4e60H); (* move.l a0,usp *)
trap:=trappointer(iotranspointer.device); (* TRAP ADR *)
trap^:=ITRAP; (* set trap to IOTRANSFER int code *)
CODE(4cdfH,7fffH); (* restore regs movem *)
CODE(4e73H); | (* rte *)
END;
CODE(4cdfH,7fffH); (* restore regs movem *)
CODE(4e73H); (* rte *)
END PTRAP;
(*$P+ *)
(*$P- *)
PROCEDURE ITRAP;
BEGIN
CODE(043374B,2700H); (* disable ints *)
CODE(48e7H,0fffeH); (* save regs movem *)
CODE(4e68H); (* move.l usp,a0 TRANSFER *) (* SAVE *)
CODE(0dffcH,0,42H); (* add.l #66,sp *)
CODE(2127H); (* move.l -(sp),-(a0) D0 *)
CODE(2127H); (* move.l -(sp),-(a0) D1 *)
CODE(2127H); (* move.l -(sp),-(a0) D2 *)
CODE(2127H); (* move.l -(sp),-(a0) D3 *)
CODE(2127H); (* move.l -(sp),-(a0) D4 *)
CODE(2127H); (* move.l -(sp),-(a0) D5 *)
CODE(2127H); (* move.l -(sp),-(a0) D6 *)
CODE(2127H); (* move.l -(sp),-(a0) D7 *)
CODE(2127H); (* move.l -(sp),-(a0) A0 *)
CODE(2127H); (* move.l -(sp),-(a0) A1 *)
CODE(2127H); (* move.l -(sp),-(a0) A2 *)
CODE(2127H); (* move.l -(sp),-(a0) A3 *)
CODE(2127H); (* move.l -(sp),-(a0) A4 *)
CODE(2127H); (* move.l -(sp),-(a0) A5 *)
CODE(2127H); (* move.l -(sp),-(a0) A6 *)
CODE(3127H); (* move.w -(sp),-(a0) SR *)
CODE(2127H); (* move.l -(sp),-(a0) PC *)
io2^:=REGISTER(8); (* set interrupted process to process *)
SETREG(8,io1^); (* load iotransfer process to a0 RESTORE *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D0 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D1 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D2 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D3 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D4 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D5 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D6 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ D7 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A0 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A1 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A2 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A3 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A4 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A5 *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ A6 *)
CODE(3ed8H); (* move.w (a0)+,(sp)+ SR *)
CODE(2ed8H); (* move.l (a0)+,(sp)+ PC *)
CODE(9ffcH,0,42H); (* sub.l #66,sp *)
CODE(4e60H); (* move.l a0,usp *)
CODE(4cdfH,7fffH); (* restore regs movem *)
CODE(4e73H); (* rte *)
END ITRAP;
(*$P+ *)
PROCEDURE INITPROCESSES;
BEGIN
ssv:=0;
Super(ssv);
trap:=trappointer(TRAP);
trap^:=PTRAP;
Super(ssv);
init:=TRUE;
END INITPROCESSES;
BEGIN
END NEWSYS.
The 68000 used on the ST had a few instructions that could not be virtualized or had hidden processor state and had no real memory protection that made a true multitasking system impossible but you could fake it with most programs.
The web never forgets, I found an old email about MX2! https://www.megalextoria.com/usenet-archive/news109f1/b132/comp/sys/atari/st/00018621.html
That was an ST limitation, not a 68000 one - the far superior Amiga used a 68000 and multitasked perfectly fine, FAR, FAR better than PC's managed until relatively recently.
Can you show an example where ASM "has far more control and precision" than C.
I do not understand why you think C is a high level language.. it really is not far away from ASM. C is the next closest thing to "hardware level" programming. It is very efficient and powerful.. if you would just take some time and learn the language before comparing it to asm.
It's so close that I still prefer to use ASM. You miss out the middle man of a compiler and its bugs. Many of the major players in compilers still have bugs in their compilers that have been reported ages ago. You can also find bugs in the hardware (and they do exist) very quickly if you understand what the CPU is doing because you wrote the low level code and not someone elses interpretation of what you are trying to achieve via some third party library that for example in C++, may use function overloading and make debugging very difficult.
That was an ST limitation, not a 68000 one - the far superior Amiga used a 68000 and multitasking perfectly fine, FAR, FAR better than PC's managed until relatively recently.
I trust you are not being flippant) but you are correct. Linux is a powerful OS but I would never use it on anything critical.