Comments 33
Не было там таких "нативных" команд — кроме случая косвенной адрессации посредством регистра, но и то с ограничениями (*x++ и *--x
).
В свете вышесказанного, INC и DEC — не “нативные”? Макросы, что ли?
А сишное:
while (*dst++ = *src++)
;
компилируемое в:
MOV #SRC, R2
MOV #DST, R1
1$: MOV (R2)+, (R1)+
BNE 1$
тоже что-то не то? Выходит, я на каких-то не тех ЭВМ работал :)
Насколько я помню, в системе команд PDP-11 (не PDP-8, про PDP-7 не знаю) операции типа *p++ для указателя можно скомпилировать в ОДНУ команду с косвенной автоинкрементной регистровой адресацией (если адрес-указатель в регистре, естественно).
Режимы адресации с автоинкрементом/декрементом и inc/dec появились на PDP-11. У PDP-7 таких инструкций не было: http://bitsavers.trailing-edge.com/pdf/dec/pdp7/F-75P_PDP7prelimUM_Dec64.pdf
Оказывается всё было совсем не так. Операторы пре- и постинкремента/декремента появились уже в B, который разрабатывался на PDP-7. inc и dec на PDP-7 не было, но там были автоувеличивающиеся ячейки памяти (страница 3-12 в мануале). Вероятно, это и натолкнуло на идею введения таких операторов.
Информация отсюда: http://cm.bell-labs.co/who/dmr/chist.html, раздел "More history"
Простите, нахлынуло как-то :)
1. Современным «писателям» не знакомо само понятие «ассемблер». Не знакомо оно по простой причине: они не понимают, что именно он «собирает». А «собирает» он программу из макрокоманд, потому что это «макро ассемблер» — именно макро, потому что без «макро» слово «ассемблер» звучит совершенно бессмысленно.
Если открыть исходные коды основной OS PDP-11, RSX-11, то мы, внезапно, не увидим там ни какого «языка высокого уровня». (Кто там говорил о том, что ОС не пишутся на ассемблере?) Мало того, мы практически не увидим там и команд процессора (внезапно). Вместо этого, там будут сплошные вызовы макрокоманд из системных макробиблиотек.
К стати, авторы статьи специально не упомянули об одной из ключевых особенностей языка «C», препроцессоре и развитых макробиблиотеках?
2. Как было указано выше, язык «C» удивительным образом напоминает систему команд PDP-11. Сходство усиливается, если обратить внимание на схожую практику использования макросов, делающую язык удивительно похожим на макроассемблер. (Ещё более удивительным кажется структура OS Unix, в сравнении с RSX-11, но это уже ни кто не помнит). Учитывая, что в то время языки высокого уровня компилировались через ассемблер, любой желающий мог видеть, что код «C» на PDP-11 компилируется практически слово в слово, а на 8086 порождает, порой, довольно кучерявые конструкции (чего никогда не будет с тем же «Паскалем» или «Фортраном»).
Я бы сказал, что язык «C» больше напоминает язык «Эль», являющийся «ассемблером высокого уровня» для ЭВМ «Эльбрус».
В силу вышесказанного, статья выглядит как разрозненный набор нагугленных данных, кое-как связанных с помощью фантазий автора.
И таки да, я неоднократно собирал RSX-11 на PDP-11. И Unix я тоже собирал.
Хотя, конечно же, это были не PDP-11, а СМ-4 и СМ-1420; не Unix, а «Demos»; но среди ОС-РВ и ДОС-РВ, был и RSX-11, и RT-11 (преимущественно XM).
Я написал на ассемблере небольшой графический редактор для десятикадровой анимации — 3kB исполняемый com-файла (на Поиске, на компиляцию программ на «С» в нем памяти не хватало — с одной платой расширения ), не используя макросы macro-assembler-a, так что думаю осмысленно звучит «ассемблер» без «макро», разве что не эффективно так программы писать на asm-е. 21е прерывание (DOS подпрограммы) даже вроде не использовал — только 10е и 16е. Потом осознал, что не нужно выпендриваться — с макросами проще и быстрее.
Помню, нарисовал в этом редакторе переливающуюся надпись “T2 terminator 2”, вышедшего за год то этого фильма (по-пиксельно, без мыши).
Похожий контент про С на NDC был представлен
https://youtu.be/xGVRF-Y--hI
Мало того, мы практически не увидим там и команд процессора (внезапно). Вместо этого, там будут сплошные вызовы макрокоманд из системных макробиблиотек.
Ну, уважаемый, столь откровенную чушь-то пороть не надо. Вот под спойлером один из модулей ядра RSX-11, отвечающий за запуск ядра.
.TITLE INITL
.IDENT /10/
;
; COPYRIGHT 1974, 1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; VERSION 10
;
; D. N. CUTLER 23-AUG-73
;
; PREVIOUSLY MODIFIED BY:
;
; D. N. CUTLER
; T. J. MILLER
;
; MODIFIED BY:
;
; B. SCHREIBER 28-JUL-77
;
; BS004 -- CHANGE TO V3.1.
;
; T. J. MILLER 14-SEP-77
;
; TM103 -- ENHANCE CLOCK SETUP AND ALIGN POOL ON EVEN
; BOUNDARY.
;
; TM104 -- PROPERLY INITIALIZE VECTORS FOR HANDLING
; FLOATING POINT PROCESSOR EXCEPTION CONDITIONS.
;
; TM105 -- ADD SUPPORT FOR ODD CSR'S AND DEVICE UNIT
; NUMBERS OVER 127.
;
; SYSTEM START UP AND INITIALIZATION ROUTINE
;
; MACRO LIBRARY CALLS
;
.MCALL HWDDF$
HWDDF$ ;DEFINE HARDWARE REGISTERS
;
; LOCAL DATA
;
; SYSTEM IDENTIFICATION MESSAGES
;
$POOL:: ;START OF POOL
.IF NDF R$$11S
SYSMG: .ASCII <15><12>/RSX11M V3.1 BL/
.IFF
SYSMG: .ASCII <15><12>/RSX11S V2.1 BL/
.ENDC
SYSID: .ASCIZ /XXXX/<15><12><12> ;
DEVMG: .ASCIZ <15><177><177><12>/ DEVICE DDUU: NOT IN CONFIGURATION/<15> ;
PROMT: .ASCIZ <15><12>/>/ ;
.EVEN
;+
; **-$INITL-SYSTEM TRANSFER ADDRESS
;
; THIS ROUTINE CONTAINS THE TRANSFER POINT OF THE RESIDENT EXECUTIVE. WHEN
; THE SYSTEM IS BOOTED, CONTROL IS TRANSFERED HERE TO INITIALIZE AND START
; UP THE SYSTEM
;-
$INITL::RESET ;RESET PROCESSOR
MOV #$SYSIZ+2,R0 ;POINT TO SYSTEM CONFIGURATION VECTOR
MOVB R3,(R0)+ ;SAVE UNIT NUMBER
MOVB R1,(R0)+ ;SAVE LBN OF LOAD IMAGE
MOV R2,(R0)+ ;
MOV R4,(R0)+ ;SAVE DEVICE NAME
MOV R5,(R0)+ ;SAVE LENGTH OF LOAD FILE
.IF DF M$$MGE
MOV #PMODE+PR7,PS ;SET MODE BITS AND LOCK OUT INTERRUPTS
MOV #$STACK-20,SP ;SETUP EXEC STACK POINTER
MOV #KISAR0,R0 ;POINT TO KERNEL PAR 0
MOV #KISDR0,R1 ;POINT TO KERNEL PDR 0
MOV #UISAR0,R2 ;POINT TO USER PAR 0
MOV #UISDR0,R3 ;POINT TO USER PDR 0
MOV #8.,R4 ;SET LOOP COUNT
CLR R5 ;START AT BOTTOM OF MEMORY
10$: MOV R5,(R0)+ ;SET KERNEL AND USER RELOCATION BIAS
MOV R5,(R2)+ ;
MOV #77406,(R1) ;SET KERNEL AND USER DESCRIPTOR REGISTERS
MOV (R1)+,(R3)+ ;
ADD #200,R5 ;ADVANCE TO NEXT 4K BLOCK
DEC R4 ;ANY MORE REGISTERS TO LOAD?
BGT 10$ ;IF GT YES
MOV #177600,-(R0) ;SET KERNEL PAR 7 TO I/O PAGE
INC SR0 ;AND AWAY WE GO
.IF DF M$$EXT
MOV #UBMPR,R0 ;POINT TO FIRST UNIBUS MAPPING REG
CLR R1 ;SET INITIAL ADDRESS TO ZERO
MOV #5.,R2 ;SET NUMBER OF REGISTER PAIRS TO LOAD
11$: MOV R1,(R0)+ ;LOAD LOW 16 BITS OF ADDRESS
CLR (R0)+ ;CLEAR HIGH 6 BITS OF ADDRESS
ADD #20000,R1 ;ADVANCE 8K BYTES
DEC R2 ;ANY MORE TO LOAD?
BGT 11$ ;IF GT YES
MOV #60,SR3 ;ENABLE 22 BIT ADDRESSING AND UB MAP
.ENDC
.IFF
MTPS #PR7 ;LOCK OUT INTERRUPTS
MOV #$STACK-10,SP ;SETUP EXEC STACK POINTER
.IFTF
MOV @#4,-(SP) ;SAVE ADDRESS OF TRAP 4 ROUTINE
MOV #TRPRT,@#4 ;SET TRAP ADDRESS FOR NONEX MEM
MOV #$SYSID,R0 ;POINT TO SYSTEM IDENTIFICATION
MOV #SYSID,R1 ;POINT TO IDENTIFICATION MESSAGE
MOVB (R0)+,(R1)+ ;MOVE SYSTEM IDENTIFICATION INTO MESSAGE
MOVB (R0)+,(R1)+ ;
MOVB (R0)+,(R1)+ ;
MOVB (R0),(R1) ;
JSR R5,OPMSG ;TELL EVERYBODY WE'RE ON THE AIR
.WORD SYSMG ;
.IFT
MOV #140000,R0 ;SET INITIAL MEMORY ADDRESS
CLR KISAR6 ;SET ZERO RELOCATION BIAS
.IFF
CLR R0 ;SET INITIAL MEMORY ADDRESS
.IFTF
CLR R1 ;ZERO NUMBER OF 32W BLOCKS IN SYSTEM
13$: TST (R0) ;MEMORY EXIST?
BCS 17$ ;IF CS NO
ADD #40,R1 ;UPDATE NUMBER OF 32W BLOCKS
.IFT
ADD #40,KISAR6 ;UPDATE RELOCATION BIAS BY 1K
.IF DF M$$EXT
CMP KISAR6,#170000 ;END OF MEMORY?
.IFF
CMP KISAR6,#7600 ;END OF MEMORY?
.ENDC
BLO 13$ ;IF LO NO
.IFF
ADD #4000,R0 ;UPDATE MEMORY ADDRESS BY 1K
CMP R0,#160000 ;END OF MEMORY?
BLO 13$ ;IF LO NO
.IFTF
17$: MOV R1,$SYSIZ ;SET SIZE OF MEMORY IN 32W BLOCKS
.IFT
MOV #1400,KISAR6 ;RESET MAPPING RELOCATION BIAS
.ENDC
MOV #$DEVHD,R5 ;GET ADDRESS OF FIRST DCB ADDRESS
20$: MOV (R5),R5 ;GET ADDRESS OF NEXT DCB
BEQ 80$ ;IF EQ NO MORE TO SCAN
MOV D.UCB(R5),R4 ;POINT TO FIRST UCB
BIT #DV.PSE,U.CW1(R4) ;PSEUDO DEVICE?
BNE 20$ ;IF NE YES
MOVB D.UNIT(R5),-(SP) ;SET STARTING LOGICAL UNIT NUMBER
MOVB D.UNIT+1(R5),-(SP) ;CALCULATE NUMBER OF UCB'S TO SCAN
SUB D.UNIT(R5),(SP) ;
INCB (SP) ;
INCB (SP) ;
30$: DECB (SP) ;ANY MORE UCB'S TO SCAN?
BNE 40$ ;IF NE YES
CMP (SP)+,(SP)+ ;CLEAN STACK
BR 20$ ;GO AGAIN
40$: CMP $SYSIZ+6,D.NAM(R5) ;DEVICE NAMES MATCH?
BNE 45$ ;IF NE NO
CMPB $SYSIZ+2,2(SP) ;UNIT NUMBERS MATCH?
BNE 45$ ;IF NE NO
MOV R4,.SY0+2 ;REDIRECT SYSTEM DEVICE
MOV R4,.LB0+2 ;REDIRECT LB: AS WELL
45$: MOV U.SCB(R4),R2 ;GET ADDRESS OF SCB
INCB 2(SP) ;UPDATE LOGICAL UNIT NUMBER
TSTB @S.CSR(R2) ;DEVICE IN SYSTEM?
BCC 60$ ;IF CC YES
BISB #US.OFL,U.ST2(R4) ;SET DEVICE OFFLINE
MOVB D.NAM(R5),DEVMG+12. ;INSERT GENERIC DEVICE NAME
MOVB D.NAM+1(R5),DEVMG+13. ;
MOV R4,R0 ;COPY ADDRESS OF UCB
SUB D.UCB(R5),R0 ;CALCULATE ADDRESS OFFSET TO UCB
MOV D.UCBL(R5),R1 ;GET LENGTH OF UCB
CALL $DIV ;CALCULATE RELATIVE UNIT NUMBER
ADD D.UNIT(R5),R0 ;CALCULATE LOGICAL UNIT NUMBER
BIC #177400,R0 ;CLEAR EXTRANEOUS BITS
MOV #8.,R1 ;SET DIVISOR
CALL $DIV ;CONVERT UNIT NUMBER TO 2 DIGITS
ADD #'0,R0 ;ADD CHARACTER BIAS
ADD #'0,R1 ;ADD CHARACTER BIAS
MOVB R0,DEVMG+14. ;INSERT DEVICE UNIT NUMBER
MOVB R1,DEVMG+15. ;
JSR R5,OPMSG ;OUTPUT DEVICE MESSAGE
.WORD DEVMG ;
60$: ADD D.UCBL(R5),R4 ;CALCULATE ADDRESS OF NEXT UCB
BR 30$ ;GO AGAIN
80$: ;REF LABEL
.IF DF P$$RTY
MOV #$PARTB,R0 ;GET ADDRESS OF PARITY CSR ADDRESS TABLE
MOV R0,R1 ;COPY ADDRESS OF TABLE
MOV #1,(R1)+ ;INSERT A ONE IN FIRST TABLE ENTRY
MOV #MPAR-2,R2 ;GET ADDRESS OF FIRST PARITY REGISTER-2
MOV #16.,R3 ;SET NUMBER OF PARITY REGISTERS
90$: ADD #2,R2 ;ADVANCE TO NEXT PARITY CSR REGISTER
MOV R2,(R1)+ ;ASSUME PARITY REGISTER PRESENT
TST (R2) ;PARITY CSR REGISTER PRESENT?
BCC 100$ ;IF CC YES
MOV R0,-2(R1) ;POINT TO FIRST WORD OF TABLE
100$: DEC R3 ;ANY MORE TO SCAN?
BGT 90$ ;IF GT YES
MOV (R1),R1 ;11/70 CACHE PARITY CSR SEARCH DONE?
BEQ 105$ ;IF EQ YES
MOV #MPCSR-10,R2 ;POINT TO FIRST CSR ADDRESS - 2
MOV #6,R3 ;SET COUNT OF REGISTERS
BR 90$ ;SEARCH FOR THEM
105$: ;REF LABEL
.ENDC
.IF DF F$$LPP
TST PIRQ ;IS THERE A PIRQ REGISTER?
BCS 106$ ;IF CS NO
MOV #$FPPRQ,@#240 ;SET UP PIRQ VECTOR
MOV #$FPPR8,@#244 ;SET UP FLOATING POINT EXCEPTION VECTOR
106$: ;REF LABEL
.ENDC
JSR R5,OPMSG ;OUTPUT INITIAL PROMPT MESSAGE
.WORD PROMT ;
.IF DF L$$SI1
MOV #$CKINT,@#100 ;SET CLOCK INTERRUPT VECTOR
.IFF
MOV $CKCSR,R0 ;GET ADDRESS OF CLOCK CSR
TST (R0) ;IS THE GENERATED CLOCK AVAILABLE?
BCC 110$ ;IF CC YES
MOV #172540,R0 ;GET ADDRESS OF KW11-P CSR
MOV R0,$CKCSR ;SETUP FOR KW11-P
MOV #172542,$CKCNT ;
MOV #K$$LDC,$CKLDC ;SET COUNT REGISTER LOAD COUNT
MOV #K$$TPS,$TKPS ;SET TICKS PER SECOND
TST (R0) ;KW11-P?
BCC 110$ ;IF CC YES
MOV #177546,R0 ;GET ADDRESS OF KW11-L CSR
MOV R0,$CKCSR ;SETUP FOR KW11-L
MOV R0,$CKCNT ;
CLR $CKLDC ;
MOV #H$$RTZ,$TKPS ;SET TICKS PER SECOND TO LINE FREQUENCY
110$: MOV #$NONSI,@#100 ;RESET KW11-L INTERRUPT VECTOR
MOV #$CKINT,104 ;SETUP KW11-P VECTOR
CMP #172540,R0 ;KW11-P?
BEQ 120$ ;IF EQ YES
MOV #$CKINT,100 ;SETUP KW11-L VECTOR
MOV #$NONSI,104 ;RESET KW11-P VECTOR
120$: MOV $CKCNT,R1 ;GET ADDRESS OF COUNT REGISTER
MOV $CKLDC,(R1) ;SETUP CLOCK COUNT REGISTER
MOV #K$$IEN,(R0) ;START CLOCK
.ENDC
.IF DF M$$MGE
MOV #PMODE+PR7,PS ;MAKE SURE PS IS SETUP PROPERLY
.ENDC
MOV #SYSMG,R0 ;SET ADDRESS OF BLOCK TO RELEASE
ADD $CRAVL-2,R0 ;ROUND TO NEXT BOUNDARY
BIC $CRAVL-2,R0 ;
MOV #$SYBEG-SYSMG,R1 ;SET LENGTH OF BLOCK TO RELEASE
CALL $DEACB ;DEALLOCATE INITIALIZATION CODE
MOV (SP)+,@#4 ;RESTORE TRAP 4 ROUTINE ADDRESS
JMP $DIRXT ;START UP THE SYSTEM
;
; SUBROUTINE TO OUTPUT A MESSAGE TO THE SYSTEM CONSOLE TERMINAL
;
OPMSG: MOV (R5)+,R1 ;GET ADDRESS OF OUTPUT MESSAGE
10$: MOVB (R1)+,R0 ;GET NEXT BYTE TO OUTPUT
BEQ 30$ ;IF EQ DONE
MOVB R0,TPS+2 ;LOAD BYTE IN OUTPUT BUFFER
20$: TSTB TPS ;PRINTER BUSY?
BCS 30$ ;IF CS NO CONSOLE TERMINAL
BPL 20$ ;IF PL YES
BR 10$ ;GO AGAIN
30$: RTS R5 ;
;
; NONEX MEM TRAP ROUTINE
;
TRPRT: BIS #1,2(SP) ;SET CARRY BIT
RTI ;
;
; END OF DYNAMIC STORAGE REGION
;
.IF NE <.-SYSMG>&3
.BLKB <.-SYSMG>&3
.ENDC
;
; BEGINNING OF DYNAMIC STORAGE REGION
;
$SYBEG::.WORD 0 ;LINK TO NEXT BLOCK IN FREE LIST
.WORD <<<C$$ORE*2>+3>&177774> ;LENGTH OF FREE BLOCK
.BLKB <<<C$$ORE*2>+3>&177774>-4 ;ALLOCATE REMAINING STORAGE
$SYTOP:: ;LAST ADDRESS IN EXECUTIVE
.END $INITL
>
Много ты здесь видишь “сплошных вызовов макрокоманд из системных библиотек”? А я вот вижу считанные единицы —
CALL
(который в макросе в зависимости от некоторых условий расширяется либо в JSR PC,SUBR
, либо в JSR R5,SUBR
), RETURN
(который просто RTS PC
), MTPS
(который всего лишь либо чистит PSW, если аргумент #0, CLR @#PS
, либо загоняет аргумент в младший байт PSW, MOVB ARG,@#PS
). Прочее — самые что ни на есть чистые команды процессора (внезапно).Могу показать RSXMC.MAC и RSXMC0.MAC — это как раз те самые “системные макрокоманды”, активно используемые в ядре. Активность использования — где-то в районе один макрос на 50 строк кода. Далековато от “сплошных вызовов макрокоманд”.
Для остальных, замечу, что «ядро» у RSX-11, это не Linux — даже файловая система загружена как отдельная резидентная библиотека.
Как собирается система, с использованием отдельного интерпретатора, это отдельная история. Боюсь, даже REXX известен гораздо больше, чем язык скриптов RSX-11
Активность использования — где-то в районе один макрос на 50 строк кода.
Ладно, ладно, много там команд вне макро условий `.IF’?
Реальный фокус MACRO-11, это ж когда мегабайты сложной программы/ОС, внезапно, укладываются в считанные килобайты ОЗУ.
Буквально вчера наш сотрудник сформулировал:
«Жизнь вещь сложная. Но если её писать не на ассемблере, а на Си, то не очень».
Я выбрал для нового языка имя C++, поскольку оно было коротким, имело симпатичные интерпретации и не содержало прилагательных к «С». "++" в зависимости от контекста можно прочесть как «следующий» или «увеличить», хотя обычно произносят «плюс плюс». Предложил это название Рик Маскитти (Rick Mascitti). Впервые я употребил сочетание «C++» в декабре 1983 г.
Когда у тебя есть всего 4 тысячи слов для работы, сокращение «x=x+1» до «x++» экономит приличное количество места.
Думаю если бы дело было в этом то и прочие служебные конструкции скатились бы до уровня пары символов на команду, в оригинальном С служебных слов было сильно не много.
C сбежал из Bell Labs почти так же, как это произошло с Unix. Он способствовал тому, что PDP-11 быстро стал одним из наиболее успешных мини-компьютеров на рынке, однако наиболее привлекательной его делала цена Unix. Любой ...
Успех PDP-11, которые, заметим, по сию пору производится и поддерживается, хотя уже и в виде аппаратных эмуляторов, но полностью электрически и программно совместимых, конечно же не имеет отношения ни к C, ни к Unix, которые совершенно неэффективны и совершенно не приспособлены к небольшим объёмам ОЗУ. Поэтому, и C, и Unix, быстро сбежали на более мощные компьютеры. А для PDP-11 вообще ж, лично я нормального компилятора C так и не лицезрел.
А PDP-11/VAX-11, конечно же, славны своим MACRO-11. А может это «11» — магическое число?
Группа работающих над языком исследователей встречалась в Кембридже или в Лондоне, а также в Лондонском университете, но иногда они собирались в мастерской кенсингтонского таунхауса
Переводчик не догадался, что и Лондонский университет, и кенсингтонский таунхаус расположены в Лондоне?
Автор перечисляет не четыре, а три места встреч — одно в Кембридже и два в Лондоне.
"В то время и память, и процессорные такты компьютера стоили целое состояние, поэтому это было важным аспектом программирования."
Очень жаль что сейчас совершенно другие приоритеты у большей массы разрабов и даже контор.
«Чертовски глупое решение»: история появления языка C