- PVSM.RU - https://www.pvsm.ru -
Немногие смело признают, что могут ошибиться в идентификации ассемблера, ведь это по-своему особенный язык. Однако не спешите с выводами, а лучше пройдите небольшой тест, который не просто позволит взгялуть на него в ином свете, но и проверит вашу осведомленность в этой сфере.
Программирование на ассемблере сегодня в лучшем случае занимает нишевое положение и чаще воспринимается как неоправданно педантичное, требовательное и затратное даже для своей ниши.
Ассемблер непрост. Он недружелюбен. Программирование на этом языке происходит медленно и зачастую сопряжено с ошибками — таково общепринятое мнение.
К сожалению, в современной цифровой среде исходит это мнение от людей, которые, как правило, плохо представляют, как реально выглядят современные языки ассемблера. Этот стиль программирования не застрял в 50-х, он развивался вместе с высокоуровневыми языками, вбирая в себя структурные, функциональные и объектно-ориентированные элементы. Он отлично дружит с современными API и DOM. Конечно же, принципиально это низкоуровневый язык, но вы можете с тем же успехом создавать поверх него и высокоуровневые абстракции.
Честно говоря, я даже не уверен, что кто-нибудь сможет легко отличить код ассемблера от какого-нибудь высокоуровневого кода без помощи гугла. Вот вы сможете?
Ниже приведен фрагмент кода. Он создает окно с 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
Ниже дан пример функциональной библиотеки. Функция “add” просто складывает два целых числа и возвращает их сумму.
(module
(func $add (param $lhs i32) (param $rhs i32) (result i32)
get_local $lhs
get_local $rhs
i32.add)
(export "add" (func $add))
)
Это реализация алгоритма 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
Кстати, TPK означает «Typical Pardo Knuth» (типичный Пардо Кнут, от имени его создателя) Это не настоящий алгоритм, и создавался он для демонстрации нескольких языков в одном примере.
Вот пример вычисления суперскалярной суммы.
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
Это решение задачи о восьми ферзях [3] с выводом в консоль. Его платформенная зависимость минимальна, но при этом оно не обогащено высокоуровневыми возможностями вроде классов, шаблонов или встроенных контейнеров.
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
$)
Вот ассемблер .NET [4] (не путать с ассемблером в «языке ассемблера»). Он состоит из одного модуля с одним классом, имеющим один метод, который выводит в консоль “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
Это пример 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
!!
Современное программирование на ассемблере не обязательно связано с инструкциями процессора и регистрами. Да, код всегда начинается с низов, но его можно оснастить функциями, классами и макросами, сделав до нужной степени высокоуровневым.
Программировать на этом языке не всегда трудно, и он не всегда оказывается чрезмерно педантичен. Просто каждому нужно подобрать подходящий для работы уровень.
Автор: Дмитрий Брайт
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/363808
Ссылки в тексте:
[1] win32assembly.programminghorizon.com/tut3.html: http://win32assembly.programminghorizon.com/tut3.html
[2] developer.mozilla.org/en-US/docs/WebAssembly: https://developer.mozilla.org/en-US/docs/WebAssembly
[3] задачи о восьми ферзях: https://en.wikipedia.org/wiki/Eight_queens_puzzle
[4] ассемблер .NET: https://docs.microsoft.com/en-us/dotnet/standard/assembly/
[5] docs.microsoft.com/en-us/dotnet/framework/tools/ilasm-exe-il-assembler: https://docs.microsoft.com/en-us/dotnet/framework/tools/ilasm-exe-il-assembler
[6] smalltalk.gnu.org/wiki/examples: http://smalltalk.gnu.org/wiki/examples
[7] Источник: https://habr.com/ru/post/554910/?utm_source=habrahabr&utm_medium=rss&utm_campaign=554910
Нажмите здесь для печати.