# hello.s - Hello World for LoongArch64 (Linux) # Build: loongarch64-linux-gnu-as -o hello.o hello.s # loongarch64-linux-gnu-ld -o hello hello.o .section .rodata msg: .ascii "Hello, World!\n" .equ msg_len, . - msg .section .text .globl _start .type _start, @function _start: # write(1, msg, msg_len) li.w $a0, 1 # fd = stdout la.local $a1, msg # buf = msg li.w $a2, msg_len # count li.w $a7, 64 # syscall number: write syscall 0 # exit(0) li.w $a0, 0 li.w $a7, 93 # syscall number: exit syscall 0
На нт тоже можно одним сервисом, тем который шелл пробивал. Только там сервисы имеют имена, в отличие от мсдос стиля линуксов. Зачем память тратить на имена, оно же для микроконтроллеров с 2к ПЗУ тоже.. - обфускация?, незачем сурки читать нужно делать нечитаемо =)
Вообще конечно китайцы молодцы - устали лицензировать армы и мипсы и фигакнули своё какое то видение ISA для RISC твёрдо стоящее всеми ногами в тех же концепциях. Зато теперь лицензировать не надо. Подозреваю что само изменение ISA изначально было таким чтобы просто взять лицензированный MIPS и перестроить ему декодер и на этом новый процессор заканчивается.
Вообще это вот интересная черта всех этих RISC-ов и тихим сапом она же пробралась и в i86-64. Но начнём разговор с рисков. Как правило там фиксированный вовсю размер инструкций и как правило он равен 32 битам. Это где то примерно тот размер когда в одну инструкцию можно уместить кучу всего. Забегая далеко вперёд есть и попытки сэкономить на байтах в виде архитектуры ARM Thumb 1/2 где инструкции могли быть 16-битными, но иногда расширятся могли до 32 бит. Это был на самом деле довольно заметный компромисс между CISC и RISC и он скорее всего работал в вашем телефоне лет 10 назад. Однако продолжаем разговор - когда размер инструкций фиксирован 32 битами и всегда одинаков то конечно конвеер жутко доволен на входе и декодер инструкций шуршит плавно и шелестяще. Но какой ценой? А вот той самой ценой, что встроить даже 32-битный immediate в поток инструкций надо за две инструкции где (как минимум) 16 бит immediate и в 16 битах опкода говорится в какую половинку какого регистра их засунуть. Это еще куда бы ни шло - загрузка 32-битного immediate за две инструкции длиной 64 бит ну... норм. На самом деле норм. Конечно в таблице RELOC тут нужны прям отдельные CASE OF от того в какие биты разрозненных слов это дело править - но терпимо конечно. Но когда мы переходим к 64-битным архитектурам, то это конечно начинает быть напряжным. Если неистово гнуть линию партии, то можно загрузить 64-битную константу в регистр за четыре 32-битных инструкции в каком то сумрачном состоянии истерии. Но это конечно гонево и на самом деле еще на 32-ух битах стали использовать трюк с адресацией относительно IP/PC (указателя инструкции) когда слово с immediate лежит где то рядом с потоком инструкций в текущем месте, но с ним не пересекается! Однако в инструкции можно из него грузануть полноценное данное указав только смещение от текущей инструкции, а смещение ну смешное может быть - плюс-минус десятки килобайт и не более того. Можно эти константы распихивать в кармашки до или после функций - норм будет в подавляющем большинстве случаев. И вот этот вот RISC-овый подход он довлеет довлеет довлеет и даже оказал в итоге влияние на архитектуру x86-64 где теперь тоже по умолчанию вменяется режим адресации "position independent code" и 64-битные immediate изначально были недоступны - как и с FPU нужно было грузить константы откуда то из памяти по смещению. Потом уже с каким то новым обновлением архитектуры 64-битные immediate стали доступны, но если мне память не изменяет только в варианте REG64 <- IMM64 Такие вот дела. Лонгуснг судя по всему ну вот в точности тот же зверь что все остальные РИСКи и несет те же фишки и проблемы. Отсюда и la.global vs la.local. Причём про глобальную таблицу идентификаторов GOT (Global Offset Table) я даже не заикался. Очень интересные темы.
la.local раскрывается в: Код (ASM): pcalau12i $rd, %pc_hi20(sym) addi.d $rd, $rd, %pc_lo12(sym) 32-битный локальный адрес - это знаковое целое pc_hi20 - 20 битное смещение страницы pc_lo12 - адрес переменной Т.е. 64-битный адрес хитрым образом собирается из 3 частей: PC, pc_hi20, pc_lo12 la.global - аналогично, но в привязке к GOT: got_pc_hi20 и got_pc_lo12 Почему Intel и AMD пошли путём банального наращивания РОН до 64 бит - не вполне ясно. Представляется, что в угоду плоской модели памяти. А получилось так, что старшие 32 бита недоступны напрямую. При этом 8, 16 и 32-битные целочисленные аргументы хранятся и передаются в 64-битных регистрах. Т.е. регистр al так греется, что аж светится, середина регистра eax такая горячая, что на ней можно жарить яичницу, а биты 63-32 регистра rax стоят холодные и покрытые пылью и паутиной. Теперь Intel анонсировала APX, в которой собирается добавить ещё 16 таких же полупокерных регистров. Почему на этапе перехода к 64-архитектуре не сделали регистры r8..r15 32-битными, а адресацию через пары 32-битных регистров?
У меня хмурая мысль уже давно гуляет в черепушке что почему бы не дать всем этим RISC-ам полноценные имеедиейты. Но вот как? И хмурая мысль эта она вот какая - пусть все инструкции будут 32 бита, но если самый старший бит зажжён, то это имеедиейт предыдущей инструкции, а значение этого самого бита в ней и храниться. Со всех теоретических точек зрения что я рассматривал это будет идеал - конвеер просто не выполняет слова в которых зажжён верхний бит, а кеширует их содержимое для инструкций и так далее. Может быть я уже долларовый миллиардер если запатентую сей скверный разрыв между мирами CISC и RISC, но ясен же пень что нет.
Размерность данных имеется в виду? Это будет: а) несколько новых типов данных (как минимум, два: 31-битное целое и float с укороченной мантиссой); б) обратная несовместимость; в) защита от вредоносного ПО почище DEP. Проще тогда данные оставить как есть, а опкоды метить префиксами или суффиксами.
Имеется ввиду то, что в основном инструкции RISC чаще всего фиксированы по ширине в 32 бита и конвеер их выгребает из выгребной кучи памяти вообще без оглядки на то данные это или что потому что там могут быть только 32-битные опкоды смешанные со всевозможными 20-битными (или типа того) оффсетами зашитыми в этом опкоде. Именно поэтому возникают такие конструкты как la.local когда в две инструкции в регистр помещается адрес константной строки. Мы реально потратили 64 бита потока инструкций и потребушили кеш данных чтобы это сделать. Моя мысль в том чтобы было такое сочетание битов в инструкции что мол дескать "возьми следующие 31 бита из слова за инструкцией, а 1 бит вот тут лежит здеся". и вуаля. а чтобы не нужно было конвееер напрягать логикой что есть инструкция а что данное просто оторвать бит под это.