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

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

Твой программист




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


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


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


К сожалению, в современной цифровой среде исходит это мнение от людей, которые, как правило, плохо представляют, как реально выглядят современные языки ассемблера. Этот стиль программирования не застрял в 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


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


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



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))
)


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


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



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


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


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



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 


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


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



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
$)


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


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



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


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


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



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
!!


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


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



Заключение


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


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

Report Page