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

в 15:01, , рубрики: ruvds_перевод, Блог компании RUVDS.com, ненормальное программирование, Программирование

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

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

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

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

К сожалению, в современной цифровой среде исходит это мнение от людей, которые, как правило, плохо представляют, как реально выглядят современные языки ассемблера. Этот стиль программирования не застрял в 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://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js