Уверены, что отличите ассемблер от других языков?

от автора

Немногие смело признают, что могут ошибиться в идентификации ассемблера, ведь это по-своему особенный язык. Однако не спешите с выводами, а лучше пройдите небольшой тест, который не просто позволит взгялуть на него в ином свете, но и проверит вашу осведомленность в этой сфере.

Программирование на ассемблере сегодня в лучшем случае занимает нишевое положение и чаще воспринимается как неоправданно педантичное, требовательное и затратное даже для своей ниши.

Ассемблер непрост. Он недружелюбен. Программирование на этом языке происходит медленно и зачастую сопряжено с ошибками — таково общепринятое мнение.

К сожалению, в современной цифровой среде исходит это мнение от людей, которые, как правило, плохо представляют, как реально выглядят современные языки ассемблера. Этот стиль программирования не застрял в 50-х, он развивался вместе с высокоуровневыми языками, вбирая в себя структурные, функциональные и объектно-ориентированные элементы. Он отлично дружит с современными API и DOM. Конечно же, принципиально это низкоуровневый язык, но вы можете с тем же успехом создавать поверх него и высокоуровневые абстракции.

Честно говоря, я даже не уверен, что кто-нибудь сможет легко отличить код ассемблера от какого-нибудь высокоуровневого кода без помощи гугла. Вот вы сможете?

1. GUI

Ниже приведен фрагмент кода. Он создает окно с WinAPI и запускает для него цикл обработки сообщений.

Прошу вас, ознакомьтесь с ним и ответьте, написан ли он на одном из видов ассемблера или же на высокоуровневом языке?

nMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD     LOCAL wc:WNDCLASSEX       ; создает локальные переменные в стеке      LOCAL msg:MSG     LOCAL hwnd:HWND      mov   wc.cbSize,SIZEOF WNDCLASSEX      ; заполняет значения в членах wc      mov   wc.style, CS_HREDRAW or CS_VREDRAW     mov   wc.lpfnWndProc, OFFSET WndProc     mov   wc.cbClsExtra,NULL     mov   wc.cbWndExtra,NULL     push  hInstance     pop   wc.hInstance     mov   wc.hbrBackground,COLOR_WINDOW+1     mov   wc.lpszMenuName,NULL     mov   wc.lpszClassName,OFFSET ClassName     invoke LoadIcon,NULL,IDI_APPLICATION     mov   wc.hIcon,eax     mov   wc.hIconSm,eax     invoke LoadCursor,NULL,IDC_ARROW     mov   wc.hCursor,eax     invoke RegisterClassEx, addr wc        ; регистрирует класс window      invoke CreateWindowEx,NULL,         ADDR ClassName, ADDR AppName,\         WS_OVERLAPPEDWINDOW,\         CW_USEDEFAULT, CW_USEDEFAULT,\         CW_USEDEFAULT, CW_USEDEFAULT,\         NULL, NULL, hInst, NULL     mov   hwnd,eax     invoke ShowWindow, hwnd,CmdShow        ; отображает окно на рабочем столе      invoke UpdateWindow, hwnd              ; обновляет клиентскую область      .WHILE TRUE                            ; вход в цикл сообщений                  invoke GetMessage, ADDR msg,NULL,0,0                 .BREAK .IF (!eax)                 invoke TranslateMessage, ADDR msg                 invoke DispatchMessage, ADDR msg    .ENDW     mov     eax,msg.wParam                 ; возврат кода выхода в eax      ret WinMain endp

Это ассемблер

Код написан на MASM32, который, по сути, является набором макросов и библиотек поверх Microsoft Assembler. Он чудесно работает с WinAPI и прост в освоении. И хотя обслуживание крупных приложений с его помощью все еще вызывает сложности, создание простых, чистых и быстрых программ на этом языке дается без проблем.
Источник: Iczelion’s Win32 Assembly Homepage, Tutorial 3: A Simple Window. win32assembly.programminghorizon.com/tut3.html

Это что-то другое

Код написан на MASM32, который, по сути, является набором макросов и библиотек поверх Microsoft Assembler. Он чудесно работает с WinAPI и прост в освоении. И хотя обслуживание крупных приложений с его помощью все еще вызывает сложности, создание простых, чистых и быстрых программ на этом языке дается без проблем.
Источник: Iczelion’s Win32 Assembly Homepage, Tutorial 3: A Simple Window. win32assembly.programminghorizon.com/tut3.html

2. Библиотеки

Ниже дан пример функциональной библиотеки. Функция “add” просто складывает два целых числа и возвращает их сумму.

(module   (func $add (param $lhs i32) (param $rhs i32) (result i32)     get_local $lhs     get_local $rhs     i32.add)   (export "add" (func $add)) )

Это ассемблер

Это WebAssembly. И хотя основная его идея состоит в предоставлении двоичного кода для веб независимо от исходного языка, он и сам по себе является вполне легитимным языком ассемблера. В нем можно непосредственно писать программы для веб, и он может сам выступать исходным языком.
Источник: примеры WebAssembly с официального сайта: developer.mozilla.org/en-US/docs/WebAssembly.

Это что-то другое

Это WebAssembly. И хотя основная его идея состоит в предоставлении двоичного кода для веб независимо от исходного языка, он и сам по себе является вполне легитимным языком ассемблера. В нем можно непосредственно писать программы для веб, и он может сам выступать исходным языком.
Источник: примеры WebAssembly с официального сайта: developer.mozilla.org/en-US/docs/WebAssembly.

3. Алгоритмы

Это реализация алгоритма TPK. Она содержит функцию, несколько циклов, массив и инструкцию вывода в консоль.

1   c@VA t@IC x@½C y@RC z@NC 2   INTEGERS +5 →c 3           →t 4       +t      TESTA Z 5       -t 6               ENTRY Z 7   SUBROUTINE 6→z 8       +tt→y→z 9       +tx→y→x 10  +z+cx   CLOSE WRITE 1  11  a@/½ b@MA c@GA d@OA e@PA f#HA i@VE x@ME 12  INTEGERS +20 →b +10 →c +400 →d +999 →e +1 →f 13  LOOP 10n 14      n→x 15  +b-x→x 16      x→q 17  SUBROUTINE 5 →aq 18  REPEAT n 16      +c →i 20  LOOP 10n 21      +an SUBROUTINE 1 →y 22      +d-y TESTA Z 23      +i SUBROUTINE 3 24      +e SUBROUTINE 4 25              CONTROL X 26              ENTRY Z 27      +i SUBROUTINE 3 28      +y SUBROUTINE 4 29              ENTRY X 30      +i→f→i 31  REPEAT n 32  ENTRY A CONTROL A WRITE 2 START 2

Это ассемблер

Это не ассемблер. Перед вами разработка Алика Гленни — AUTOCODE– один из первых высокоуровневых языков.
источник: The Early Development Of Programming Languages by Donald E. Knuth, Luis Trabb Pardo, 1976.

Кстати, TPK означает «Typical Pardo Knuth» (типичный Пардо Кнут, от имени его создателя) Это не настоящий алгоритм, и создавался он для демонстрации нескольких языков в одном примере.

Это что-то другое

Это не ассемблер. Перед вами разработка Алика Гленни — AUTOCODE– один из первых высокоуровневых языков.
источник: The Early Development Of Programming Languages by Donald E. Knuth, Luis Trabb Pardo, 1976.
Кстати, TPK означает «Typical Pardo Knuth» (типичный Пардо Кнут, от имени его создателя) Это не настоящий алгоритм, и создавался он для демонстрации нескольких языков в одном примере.

4. Структурное программирование

Вот пример вычисления суперскалярной суммы.

v0 = my_vector              // нам нужна горизонтальная сумма следующего int64 r0 = get_len ( v0 ) int64 r0 = round_u2 ( r0 ) float v0 = set_len ( r0 , v0 ) while ( uint64 r0 > 4) { 	uint64 r0 > >= 1 	float v1 = shift_reduce ( r0 , v0 ) 	float v0 = v1 + v0 } // Теперь сумма представлена скаляром в v0 

Это ассемблер

Это язык ассемблера ForwardCom. Агнер Фог, который, помимо прочего, является автором популярных мануалов оптимизации и живым вдохновением для всех нас, позиционирует этот синтаксис как более дружественный для программистов. По существу, он не предназначен для компьютеров, но раз Си оказывается для большинства людей более удобен, чем операционный код, то идея сделать программирование на ассемблере более Си-подобным выглядит вполне актуальной.
Источник: примеры кода из ForwardCom: An open-standard instruction set for high-performance microprocessors by Agner Fog.

Это что-то другое

Это язык ассемблера ForwardCom. Агнер Фог, который, помимо прочего, является автором популярных мануалов оптимизации и живым вдохновением для всех нас, позиционирует этот синтаксис как более дружественный для программистов. По существу, он не предназначен для компьютеров, но раз Си оказывается для большинства людей более удобен, чем операционный код, то идея сделать программирование на ассемблере более Си-подобным выглядит вполне актуальной.
Источник: примеры кода из ForwardCom: An open-standard instruction set for high-performance microprocessors by Agner Fog.

5. Еще структурное программирование

Это решение задачи о восьми ферзях с выводом в консоль. Его платформенная зависимость минимальна, но при этом оно не обогащено высокоуровневыми возможностями вроде классов, шаблонов или встроенных контейнеров.

GET "LIBHDR"  GLOBAL $(         COUNT: 200         ALL: 201 $)  LET TRY(LD, ROW, RD) BE         TEST ROW = ALL THEN                 COUNT := COUNT + 1         ELSE $(                 LET POSS = ALL & ~(LD | ROW | RD)                 UNTIL POSS = 0 DO $(                         LET P = POSS & -POSS                         POSS := POSS - P                         TRY(LD + P << 1, ROW + P, RD + P >> 1)                 $)         $)  LET START() = VALOF $(         ALL := 1         FOR I = 1 TO 12 DO $(                 COUNT := 0                 TRY(0, 0, 0)                 WRITEF("%I2-QUEENS PROBLEM HAS %I5 SOLUTIONS*N", I, COUNT)                 ALL := 2 * ALL + 1         $)         RESULTIS 0 $)

Это ассемблер

Это не ассемблер. Знакомьтесь – это BCPL – язык, на основе которого родился B и Си. А из Си, как вы знаете, произошел C++, Java, C# и даже в некотором смысле JavaScript. Это высокоуровневый язык, который не так уж стар. Появился он после Fortran, Algol, Cobol, Lisp, APL. Его сильной стороной в свое время была простота, но не передовые возможности. Тем не менее самая первая программа Hello World была написана именно на BCPL. То же касается и первой MMORPG.
Источник: BCPL From Wikipedia, the free encyclopedia.

Это что-то другое

Это не ассемблер. Знакомьтесь – это BCPL – язык, на основе которого родился B и Си. А из Си, как вы знаете, произошел C++, Java, C# и даже в некотором смысле JavaScript. Это высокоуровневый язык, который не так уж стар. Появился он после Fortran, Algol, Cobol, Lisp, APL. Его сильной стороной в свое время была простота, но не передовые возможности. Тем не менее самая первая программа Hello World была написана именно на BCPL. То же касается и первой MMORPG.
Источник: BCPL From Wikipedia, the free encyclopedia.

6. ООП (с классами и методами)

Вот ассемблер .NET (не путать с ассемблером в «языке ассемблера»). Он состоит из одного модуля с одним классом, имеющим один метод, который выводит в консоль “Hello World”.

// Metadata version: v2.0.50215 .assembly extern mscorlib {   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )   .ver 2:0:0:0 } .assembly sample {   .custom instance void [mscorlib]System.Runtime.CompilerServices     .CompilationRelaxationsAttribute::.ctor(int32) =       ( 01 00 08 00 00 00 00 00 )   .hash algorithm 0x00008004   .ver 0:0:0:0 } .module sample.exe // MVID: {A224F460-A049-4A03-9E71-80A36DBBBCD3} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003       // WINDOWS_CUI .corflags 0x00000001    //  ILONLY // Image base: 0x02F20000  // =============== CLASS MEMBERS DECLARATION ===================  .class public auto ansi beforefieldinit Hello        extends [mscorlib]System.Object {   .method public hidebysig static void  Main(string[] args) cil managed   {     .entrypoint     // Размер кода       13 (0xd)     .maxstack  8     IL_0000:  nop     IL_0001:  ldstr      "Hello World!"     IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)     IL_000b:  nop     IL_000c:  ret   } // конец метода Hello::Main    .method public hidebysig specialname rtspecialname           instance void  .ctor() cil managed   {     // Размер кода       7 (0x7)     .maxstack  8     IL_0000:  ldarg.0     IL_0001:  call       instance void [mscorlib]System.Object::.ctor()     IL_0006:  ret   } // конец метода Hello::.ctor  } // конец класса Hello 

Это ассемблер

Да, это ассемблер, написанный на ассемблере. Это ILAsm (промежуточный язык ассемблера), который ассемблируется в промежуточный язык .NET.
Вы вольны использовать все возможности .NET: GUI, обращение к базе данных, сетевые функции – все это при одновременном наличии низкоуровневого контроля деталей. Да, такой вариант может показаться чересчур многословным и неоправданно подробным, но все равно он представляет весьма мощный вариант ассемблера. Помимо классов и методов в качестве встроенных типов он предлагает исключения и строки.
Источник: docs.microsoft.com/en-us/dotnet/framework/tools/ilasm-exe-il-assembler.
Бессовестная реклама: пару лет назад я начал вводить в ILAsm макросы, создавая MILasm. Это вполне рабочее доказательство концепции. С ним интересно играться, хотя для продакшена он не совсем готов ввиду наследственных проблем с производительностью.

Это что-то другое

Да, это ассемблер, написанный на ассемблере. Это ILAsm (промежуточный язык ассемблера), который ассемблируется в промежуточный язык .NET.
Вы вольны использовать все возможности .NET: GUI, обращение к базе данных, сетевые функции – все это при одновременном наличии низкоуровневого контроля деталей. Да, такой вариант может показаться чересчур многословным и неоправданно подробным, но все равно он представляет весьма мощный вариант ассемблера. Помимо классов и методов в качестве встроенных типов он предлагает исключения и строки.
Источник: docs.microsoft.com/en-us/dotnet/framework/tools/ilasm-exe-il-assembler.
Бессовестная реклама: пару лет назад я начал вводить в ILAsm макросы, создавая MILasm. Это вполне рабочее доказательство концепции. С ним интересно играться, хотя для продакшена он не совсем готов ввиду наследственных проблем с производительностью.

7. ООП (с объектами и сообщениями)

Это пример TCP-сервера. В нем есть объекты и методы, а работает он в собственной среде.

Namespace current addSubspace: #SimpleTCP! Namespace current: SimpleTCP!  "A simple TCP server" Object subclass: #Server   instanceVariableNames: 'serverSocket socketHandler'   classVariableNames: ''   poolDictionaries: ''   category: ''!  !Server class methodsFor: 'instance creation'!  new: aServerSocket handler: aHandler   | simpleServer |   simpleServer := super new.   simpleServer socket: aServerSocket.   simpleServer handler: aHandler.   simpleServer init.   ^simpleServer !!  !Server methodsFor: 'initialization'!  init   ^self !!  !Server methodsFor: 'accessing'!  socket   ^serverSocket !  socket: aServerSocket   serverSocket := aServerSocket.   ^self !  handler   ^socketHandler !  handler: aHandler   socketHandler := aHandler.   ^self !!  !Server methodsFor: 'running'!  run   | s |   [     serverSocket waitForConnection.     s := (serverSocket accept).     self handle: s   ] repeat !  !Server methodsFor: 'handling'!  handle: aSocket   socketHandler handle: aSocket !!

Это ассемблер

Это не ассемблер. Перед вами GNU SmallTalk – один из наиболее влиятельных ранних языков ООП. У него не совсем удобный синтаксис, но с программированием на ассемблере ничего общего этот язык не имеет. Более того, он максимально далек от низкоуровневого платформо-зависимого программирования.
Источник: Building a simple chat server with GNU Smalltalk using class inheritance из smalltalk.gnu.org/wiki/examples\

Это что-то другое

Это не ассемблер. Перед вами GNU SmallTalk – один из наиболее влиятельных ранних языков ООП. У него не совсем удобный синтаксис, но с программированием на ассемблере ничего общего этот язык не имеет. Более того, он максимально далек от низкоуровневого платформо-зависимого программирования.
Источник: Building a simple chat server with GNU Smalltalk using class inheritance из smalltalk.gnu.org/wiki/examples\

Заключение

Современное программирование на ассемблере не обязательно связано с инструкциями процессора и регистрами. Да, код всегда начинается с низов, но его можно оснастить функциями, классами и макросами, сделав до нужной степени высокоуровневым.

Программировать на этом языке не всегда трудно, и он не всегда оказывается чрезмерно педантичен. Просто каждому нужно подобрать подходящий для работы уровень.

ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/554910/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *