Comments 94
Везде где mov это ассемблер )
А почему нет хорошего ассемблера типа
MOV R0,(R5)+
положи_в корзину 10
вывали_в кучу из корзину
Это не макрос, если что
Я могу весь ассемблер спрятать в макросы, так что его родная мама не узнает. И можно хоть по русски всё написать:
Надеюсь, хоть это не ассемблер, спрятанный в макросы. А то после ваших слов у меня паранойя :)
#define корзинку R16
#define кучу PORTD
.macro положи_в
ldi @0, @1
.endm
.macro вывали_в
out @0, @1
.endm
;код
положи_в корзинку, 0
вывали_в кучу, корзинку
Я могу ошибаться, но смысл ясен. Профи меня поправят, давно не брал в руки шашек.
Это PDP-11
Русский, в отличие от английского, флективный язык, и поэтому код на нем воспринимается по-другому.
Как перевести print(load()) как "печать" или "напечатать" или "печатай"?
Везде где mov это ассемблер )Это если ассемблер x86.
my_sub: ; Adds 1 to first argument
; Prologue
stwu r1,-16(r1) ; "push"
mflr r0 ; r0 = link register
stw r0,20(r1) ; Save link register
; Body of subroutine:
addi r3, r3, 1
; Epilogue
lwz r0,20(r1)
mtlr r0
addi r1, r1, 16 ; "pop"
blr
Отсюда Но тем не менее, ассемблер узнаваем.
У PPC просто непривычные мнемоники, но логика за ними — вполне типичная для RISC.
Раз уж пошла такая пьянка, пример ассемблера "повеселее" (QDSP, архитектура с явным параллелизмом):
{ if (!p0.new) jump:nt loc_88583308
p0 = cmp.eq(r2, #0x2A)
if (p0.new) r2 = memw(sp + #0x54)
if (!p0.new) memw(r19 + #0x38) = #0 }
{ r3 = add(r2, #4)
memw(sp + #0x54) = r3.new }
{ r2 = memw(r2)
memw(sp + #0x98) = r2 }
- все три if в строках 1,3,4 проверяют результат сравнения из строки 2
- если результат ложный, то выполнится не только переход в строке 1, но и запись в память в строке 4
- переход содержит подсказку предсказателю ветвлений о наиболее вероятном поведении (nt — not taken)
- в строке 6 в память пишется результат предыдущей (5) строки (суффикс .new достаёт результат параллельной операции), а вот в строке 8 — нет (т.к. без .new), туда дойдёт старое значение из строки 3
Это ассемблер для… а нет, ни для чего. Это просто ассемблер. Поддержка конкретного процессора (теоретически любого вообще) там макросами сделана.
И да, люди этим реально пользуются. Чтобы программы для калькуляторов писать.
256Kib оперативка (154KiB доступно пользователю), 3MiB флеша, 24-битный процессор… отличный девайс всего за какие-то €150.
Ну и на чём, кроме ассемблера вы под такую роскошь будете творить? Вроде там даже компилятор C есть (C++ нету), но он кривой и дико неэффективный. А у вас 154KiB (MS DOS отдыхает).
Дааа… смотришь восьмеричные коды и сразу мнемоника перед глазами
Да, ассемблер PDP-11 великолепен.Вот только всё это великолепие — дико неэффективно.
Но, к сожалению, в реальном мире лучшие выживают далеко не всегда.Выживают всегда лучшие. Просто по определению. Вот только «лучшие» — не всегда обозначает «красивые».
Вот только всё это великолепие — дико неэффективно.Наоборот, система команд PDP-11 была намного эффективнее системы команд i8086/i8088. И ДВК-3м2 по производительности уделывал IBM-PC/AT 286.
Выживают всегда лучшие. Просто по определению.Нет, выживают не лучшие, а популярные. Но популярность обеспечивается совсем не качеством.
Процессоры i8086/i8088 были худшими на рынке 16-разрядных процессоров. И архитектура IBM-PC завоевала рынок не потому, что превосходила конкурентов (этого и близко не было), а потому, что была открытой, позволившей «китаю» наладить массовый выпуск клонов.
Более совершенный IBM-PS/2 провалился именно потому, что за его стороннее производство IBM требовала лицензионной платы.
И лицензируемый IEEE-1394 проиграл бесплатному USB совсем не потому, что был хуже.
Наоборот, система команд PDP-11 была намного эффективнее системы команд i8086/i8088.Намного эффективнее с какой точки зрения? “Красивая”, “ортогональная” система команд приводит к тому, что вы тратите ресурсы на реализацию вещей, которые никто и никогда не использует!
И ДВК-3м2 по производительности уделывал IBM-PC/AT 286.Ага, только вот ресурсов на него нужно было раза в два больше (говорю «ресурсов», так как напрямую цены тогда ещё было сравнивать нельзя… но цены на PDP-11 на Западе были гораздо выше, чем на персоналки). А если учесть, что в IBM-PC/AT процессор был искуственно замедлен…
Но популярность обеспечивается совсем не качеством.А чем, извините?
Возможно популярность измеряется не тем качеством, что нравится вам, но если продукт ни по одному параметру другие не превосходит, то популярным ему, увы, не быть.
Процессоры i8086/i8088 были худшими на рынке 16-разрядных процессоров.Зато они позволяли легко переносить программы с 8-битных процессоров. И также (что сыграло свою роль позже) обеспечивали компактный код.
И архитектура IBM-PC завоевала рынок не потому, что превосходила конкурентов (этого и близко не было), а потому, что была открытой, позволившей «китаю» наладить массовый выпуск клонов.Ага. А рабочие станции почему все издохли?
Более совершенный IBM-PS/2 провалился именно потому, что за его стороннее производство IBM требовала лицензионной платы.Он проигрывал по главному критерию качества: соотношению цена/производительность.
Заметьте, что гораздо более дорогие IBM AS/400 дожили до сегодняшнего времени, несмотря на дикие цены. И тут нельзя даже говорить о том, что они выиграли за счёт пожддержки Legacy: они в 1988м году появились, когда персоналки уже было вполне распространены и конкурировали с мини-компьютерами, появившимися раньше — которые те же персоналки успешно уничтожили. А вот AS/400 — не смогли.
Потому что в некоторых условиях — они оказывались дешевле чем другие альтернативы.
И лицензируемый IEEE-1394 проиграл бесплатному USB совсем не потому, что был хуже.Конечно он был хуже! С первыми версиями USB он не мог тягаться по цене, с последующими — по скорости.
Ну и кому он такой нужен?
Интел со своим 8080 отнюдь не был широко известен; в справочнике Титце, Шенка по полупроводниковой схемотехнике тех времен новая глава по микропроцессорам была посвящена не Интелу а Мотороле с ее процессором 6800 или даже 68000, уже точно не помню.
И еще помню как соседний сектор взял на вооружение К580 он же 8080, мы в это время сидели на 1806ВМ3, и долго смеялись когда нам поведали что результаты команд надо сохранять в единственном регистре под смешным названием «аккумулятор», когда мы могли писать в какой угодно от R0 до R5, а также в регистр — указатель стека и счетчик команд — точно также.
Ну вот в результате корявая архитектура выжила и заняла доминирующие позиции. Каждый извлекает из этой истории свой урок
Ну вот в результате корявая архитектура выжила и заняла доминирующие позиции. Каждый извлекает из этой истории свой урок.Самый главный урок просто: красота требует жертв.
Или: победитель — это всегда результат компромисса.
Какой именно компромисс выиграет, по итогу, заранее сказать сложно, но однозначно можно сказать, что вот это вот:
когда мы могли писать в какой угодно от R0 до R5, а также в регистр — указатель стека и счетчик команд — точно также.Никуда не годится. Потому что возможность работать со счётчиком комманд и стеком как с обычными регистром — это круто, конечно (ARM так тоже умеет), но как только вы пытаетесь устроить суперскаляр — так сразу “красота” проблемой становится.
Проигрыш PDP-11 Интелу исключительно по вине руководства DEC, которое заявило что микропроцессоры вообще и в частности 8080 бесперспективны будут продаваться от силы пары десятков в год, а на следующие годы фактический счет пошел на сотни тысяч. Это была стратегическая ошибка DEC с далеко идущими последствиями.Угу. но это не едиственная ошбка была. VAX с его командами аж до 56 байт был, конечно, тупиком, но Alpha же была перегибом в другую сторону!
NOP
MOVL C00000 V=1600.0 ACC=100
MOVJ C00001 VJ=100.00
MOVJ C00002 VJ=100.00
MOVJ C00003 VJ=100.00
MOVJ C00004 VJ=100.00
' APPROACH
MOVJ C00005 VJ=100.00 PL=0
MOVL C00006 V=1600.0 PL=0
WAIT IN#(20)=ON T=0.50
WAIT IN#(21)=ON T=0.50
NOP
CALL JOB:EMERG IF IN#(20)=OFF
CALL JOB:EMERG IF IN#(21)=OFF
RET
END
Это Inform III, язык, на котором программируются роботы Motoman. «Очень высокого уровня». MOVJ и MOVL буквально означают «физически двигайся туда-то» (L — linear, по прямой; J — joint, грубо говоря, как придется).
Несмотря на «очень высокий уровень», вычисления на нем выглядят примерно
GETARG LR000 IARG#(1)
SIN LR001 LR000
COS LR000 LR000
SET LD000 1000000
SET LD001 1000000
MUL LD000 LR000
MUL LD001 LR001
GETARG LD002 IARG#(2)
GETARG LB000 IARG#(3)
GETARG LB001 IARG#(4)
GETS LPX000 $PX000
CNVRT LPX000 LPX000 UF#(LB000)
SUB LP000 LP000
GETE LD003 LP000 (3)
SUB LD003 LD002
SETE LP000 (3) LD003
SET LP001 LP000
SET LP002 LP000
GETE LD003 LP001 (1)
ADD LD003 LD001
SETE LP001 (1) LD003
GETE LD003 LP001 (3)
SUB LD003 LD000
SETE LP001 (3) LD003
GETE LD003 LP002 (2)
ADD LD003 1000000
SETE LP002 (2) LD003
MFRAME UF#(LB001) LPX000 LPX001 LPX002
RET
END
Наткнулся недавно на необычный язык — qhasm. Нечто среднее между ассемблером и C. Так и не разобрался с ним, но, может, кому-то будет интересно глянуть.
Наверное эти наработки станут снова актуальны, когда упремся в предел производительности процессоров. Тогда быстро подъедут хипстерские библиотеки к ассемблеру для создания сайтов в одну строку
это BCPL
Интересно, использование $ как эскейп-символа — наверняка, по той же причине, почему $ используется как терминальный символ строки в CP/M и как разделитель в PL/M.
Но обрывки информации — использование оного как разделителя в PL/M, и в, как видим, BCPL, позволяет предполагать, что это связано с аппаратно-программными ограничениями платформы, на которой Килдал разрабатывал кросс-компилятор PL/M.
Подозреваю, что и сам Килдалл не сможет ответить, почему у него $ обозначает конец строки.
Бакс используется как спецсимвол в самых разных местах, и для окончания строки втч. В языке описания задач и так далее.
Думаю, это ограничение аппаратной платформы, в частности, какой из символов можно легко набрать на клавиатуре какой-то машины(терминала точнее).
Все уверены, что отличат его от «других языков» и от учебника математики за 5 класс?
И там еще, если память не изменяет, был явно задаваемый параллелизм, когда обе квадратуры за за один такт обрабатывались
for each x do:
*p = s0 = x
s1 = tap(3*D, w, p, D)
s2 = tap(3*D, w, p, 2*D)
s3 = tap(3*D, w, p, 3*D)
y = a0 * s0 + a1 * s1 + a2 * s2 + a3 * s3
cdelay(3*D, w, &p)
переводится в
my1 = a0;
mr = mx1 * my1 (ss);
tap(i2, m2, D, my0);
mx0 = a1;
mr = mr + mx0 * my0 (ss);
tap(i2, m2, 2*D, my0);
mx0 = a2;
mr = mr + mx0 * my0 (ss);
tap(i2, m2, 3*D, my0);
mx0 = a3;
mr = mr + mx0 * my0 (rnd);
if mv sat mr;
tapin(i2, m2, mx1);
cdelay(i2, m2);
Спасибо. Хорошее чтение на пятницу-вечер.
Ассемблеры — они с моей "эмпирической" т.з. про "физические" сущности (обычно это регистры и операции над ними).
- Ошибся с WebAssembly (но тут продолжу упорствовать и считать его "ещё чем-то").
- И с ForwardCom. Тут да, "физику" хитро замаскировали ("int64 r0"). Но на "современный" взгляд идея так себе. За ассемблер теперь берутся чтобы "пинать" опкоды, а для других задач есть средства поудобнее…
Я его перепутал с промежуточным кодом LLVM.
github.com/WebAssembly/design/issues/188
Ассемблер это вполне конкретно определенный язык со своими инструкциями.
Все эти ухищрения и синтаксические украшательства это трансляторы с какого-то псевдоязыка в язык ассемблера. Не нужно путать.
"Да, это ассемблер, написанный на ассемблере." так и Си был написан на ассемблере, что-то вот это не особо на асм похоже.
Какой Си написан на ассемблере? И что вы подразумеваете под Си, компилятор/линковщик? Если да, тогда какой/какие ?
Думал что компилятор написан на асме. На вики написано, что Си сделали на Би или его ответвлении(я так и не понял). Но это логично, так как бы это продолжение развития серии языка.
L DBD0
L +12.3E+00
/R
T MD20
NEGR
T MD24
ABS
T MD28
Что-то со стековыми регистрами
LD a
ADD b
MUL (2
ADD b
)
ST a
Ну от русского, матерного я ассемблер точно отличу. Хотя когда писал на ассемблере эти два языка соседствовали.
software.ac.uk/blog/2018-07-13-javacard-execution-environment-you-didnt-know-you-were-using
Разница между кодом для Z80, который не выполняется на вашем телефоне, и джава байт-кодом такая, что из второго довольно неплохо восстанавливается исходный код, а из кода на Z80 нет.
Java-процессоры это странная, нишевая оказия. Байткод ближе к распарсенному AST, чем к машинному коду. В плане производительности выгоднее транслировать джава-байт код в реальный, чем заниматься построением процессора, оптимизированного для выполнения байт-кода. Были ведь процессоры для телефонов с поддержкой байт-кода, но что-то не пошло дальше, хотя в андроиде например явы дофига.
Спускаясь с уровня Си на уровень ассемблера, программист может сделать что-то лучше в плане скорости или размера (затратив, конечно, усилия), а спускаясь с уровня языка Java на Java байт-код — ???
TASM – лучший ассемблер для DOSМожно подумать, тогда был большой выбор.
NASM и FASM вполне живы, причём и под DOS в том числе.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Bubble sort
;; http://rosettacode.org/wiki/Sorting_algorithms/
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.386
.model flat, stdcall
option casemap:none
include msvcrt.inc
include macros.asm
.data
spisok sdword 4, 65, 2, -31, 0, 99, 2, 83, 782, 1
size_spisok = 10
.code
align_proc
bubble_sort proc uses esi edi ebx array:ptr sdword, len:dword
mov edi, array
.for (ebx=len, cl=true: cl: ebx--)
xor cl, cl ;swapped = false;
.for (esi = 1: esi < ebx: esi++)
mov eax, [edi][esi*4 - 1*4]
mov edx, [edi][esi*4]
.if (sdword ptr edx < eax)
mov [edi][esi*4], eax
mov [edi][esi*4 - 1*4], edx
mov cl, true
.endif
.endfor
.endfor
ret
bubble_sort endp
align_proc
main proc C argc:sdword, argv:ptr ptr, envp:ptr
printf("Bubble sort.\n")
.for (esi = 0: esi < size_spisok: esi++)
printf("%d ", spisok[esi*4])
.endfor
printf("\n")
bubble_sort(&spisok, size_spisok)
.for (esi = 0: esi < size_spisok: esi++)
printf("%d ", spisok[esi*4])
.endfor
printf("\n")
xor eax, eax
ret
main endp
main_startup3_END
И ещё сортировка.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Quick sort v1.01
;; http://rosettacode.org/wiki/Sorting_algorithms/
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.386
.model flat, stdcall
option casemap:none
include msvcrt.inc
include macros.asm
.code
align_proc
quicksort proc uses esi edi ebx pBegin:ptr sdword, pEnd:ptr sdword
ASSUME edi:ptr sdword, esi:ptr sdword
mov edi, pBegin ;указатель на первый элемент массива
mov esi, pEnd ;указатель на последний элемент массива
.if (edi!=esi)
;pivot = pBegin[(pEnd - pBegin + 1)/2];//ecx
lea edx, [esi+1*4]
.for (edx-=edi, edx>>=3, ecx=[edi+edx*4]: : edi+=4, esi-=4)
.for (: sdword ptr [edi] < ecx: edi+=4)
.endfor
.for (: sdword ptr [esi] > ecx: esi-=4)
.endfor
.break .if (edi >= esi)
swap [edi], [esi]
.endfor
quicksort(pBegin, &[edi-1*4])
quicksort(edi, pEnd)
.endif
ASSUME edi:nothing, esi:nothing
ret
quicksort endp
createSpisok(spisok, sdword, 4, 65, 2, -31, 0, 99, 2, 83, 782, 1)
main proc C argc:sdword, argv:ptr ptr, envp:ptr
printf("Quick sort.\n")
.for (esi = spisok.pFirst: esi <= spisok.pLast: esi+=4)
printf("%d ", dword ptr [esi])
.endfor
printf("\n")
quicksort(spisok.pFirst, spisok.pLast)
.for (esi = spisok.pFirst: esi <= spisok.pLast: esi+=4)
printf("%d ", dword ptr [esi])
.endfor
printf("\n")
xor eax, eax
ret
main endp
main_startup3_END
Да для компиляции надо скачать мои библиотеки, я их на wasm.in выкладывал.
Уверены, что отличите ассемблер от других языков?