Skip to content

foxidokun/x64_compiler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Нативный компилятор ReverseLang ΠΏΠΎΠ΄ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ x64

ОписаниС

ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ β€” ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°, пСрСводящая написанный Π½Π° языкС программирования тСкст Π² Π±ΠΈΠ½Π°Ρ€Π½Ρ‹ΠΉ исполняСмый Ρ„Π°ΠΉΠ». Π’ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΌ случаС β€” с ReverseLang Π² исполняСмый ELF Ρ„Π°ΠΉΠ» для Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ amd64. Π‘ синтаксисом ReverseLang ΠΌΠΎΠΆΠ½ΠΎ ознакомится Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ с ΠΊΡ€Π°Ρ‚ΠΊΠΎΠΉ справкой.

ИспользованиС

Π‘Π±ΠΎΡ€ΠΊΠ° компилятора

Для сборки компилятора Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹:

$ git clone https:/foxidokun/x64_compiler # Π‘ΠΊΠ»ΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ
$ cd x64_compiler && make all                         # Π‘ΠΎΠ±Ρ€Π°Ρ‚ΡŒ всС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Π±ΠΈΠ½Π°Ρ€Π½ΠΈΠΊΠΈ

Π’Π΅ΠΏΠ΅Ρ€ΡŒ для сборки ReverseLang достаточно Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ скриптом compile.sh, ΠΏΠ΅Ρ€Π΅Π΄Π°Π² Π΅ΠΌΡƒ Π΄Π²Π° Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° β€” Ρ„Π°ΠΉΠ» с исходным ΠΊΠΎΠ΄ΠΎΠΌ Π½Π° языкС Reverselang ΠΈ ΠΏΡƒΡ‚ΡŒ, ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ скомпилированный исполняСмый Ρ„Π°ΠΉΠ».

НапримСр, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ уравнСния, Π΄ΠΎΡΡ‚ΡƒΠΏΠ½ΡƒΡŽ Π² examples/:

    $ ./compile.sh examples/quad.edoc /tmp/quad.bin
    $ /tmp/quad.bin  
        INPUT: 1     # РСшаСм x^2-4x+3 = 0
        INPUT: -4
        INPUT: 3
        OUTPUT: 2.00 # 2 roots
        OUTPUT: 1.00 # x = 1
        OUTPUT: 3.00 # x = 3

Бинтаксис ReverseLang

  1. ВсС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈΠΌΠ΅ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½ Ρ‚ΠΈΠΏ β€” Π·Π½Π°ΠΊΠΎΠ²Ρ‹Π΅ 64-Π±ΠΈΡ‚Π½Ρ‹Π΅ числа.
  2. ВсС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠΌΠ΅ΡŽΡ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.
  3. Бтандартная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° языка содСрТит 3 Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ: input / output / sqrt.
  4. Π‘ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ²ΠΎΠ΄ΠΈΡ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ матСматичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ: +, -, /, *.
  5. Доступны логичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ сравнСния: >, >=, <, <=, Π° Ρ‚Π°ΠΊΠΆΠ΅ логичСскиС И/Π˜Π›Π˜ (&& ΠΈ ||) ΠΈ ΠΎΡ‚Ρ€ΠΈΡ†Π°Π½ΠΈΠ΅ (!).
  6. Π’ языкС Π΅ΡΡ‚ΡŒ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Ρ†ΠΈΠΊΠ»ΠΎΠ² while ΠΈ if-else Π±Π»ΠΎΠΊΠΎΠ².
Π“Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ°
Program        ::= PROG_BEG (SubProgram | Func)* PROG_END
Func           ::= L_BRACKET (NAME (SEP NAME)) R_BRACKET NAME FN FUNC_OPEN_BLOCK Subprogram FUNC_CLOSE_BLOCK
SubProgram     ::= (FlowBlock)+
FlowBlock      ::= IfBlock | WhileBlock | OPEN_BLOCK Body CLOSE_BLOCK | Body
WhileBlock     ::= L_BRACKET Expression R_BRACKET WHILE OPEN_BLOCK Body CLOSE_BLOCK
IfBlock        ::= L_BRACKET Expression R_BRACKET IF OPEN_BLOCK Body CLOSE_BLOCK (ELSE OPEN_BLOCK Body CLOSE_BLOCK)
Body           ::= (Line)+
Line           ::= BREAK Expression RETURN | BREAK Expression (= NAME (LET))
Expression     ::= OrOperand (|| OrOperand)+
OrOperand      ::= AndOperand (&& AndOperand)+
AndOperand     ::= CompOperand (<=> CompOperand)
CompOperand    ::= AddOperand  ([+-] AddOperand)*
AddOperand     ::= MulOperand  ([/ *] MulOperand )*
MulOperand     ::= GeneralOperand (NOT)
GeneralOperand ::= Quant | L_BRACKET Expression R_BRACKET
Quant          ::= VAR | VAL | INPUT | BuiltInFunc | L_BRACKET (Expression (SEM Expression)) R_BRACKET NAME
BuiltInFunc    ::= L_BRACKET Expression R_BRACKET (PRINT|SQRT|SIN)

Бинтаксис ReverseLang являСтся C-ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹ΠΌ с ΠΎΠ΄Π½ΠΎΠΉ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒΡŽ: ΠΊΠ°ΠΆΠ΄ΡƒΡŽ строку стоит Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ справа Π½Π°Π»Π΅Π²ΠΎ. Π’Π°ΠΊ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄ Π½Π° C

int func (int a, int b, int c) {
    int d = a / b;
    
    if (a > b) {
        return c;
    } else {
        return d;
    }   
}

Π½Π° ReverseLang ΠΏΡ€ΠΈΠΌΠ΅Ρ‚ Π²ΠΈΠ΄

(c, b, a) func fn
[
    ; b / a = d let
    (b > a) if
    {
        ; c return
    } else {
        ; d return
    }
]

ΠŸΠΎΠ»Π½ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ этого ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°, ΠΊΠ°ΠΊ ΠΈ ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ…, ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ examples/

ΠŸΡ€ΠΈΠ½Ρ†ΠΈΠΏ Ρ€Π°Π±ΠΎΡ‚Ρ‹

АрхитСктура компилятора

ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ Ρ€Π°Π·Π±ΠΈΡ‚ Π½Π° Ρ‚Ρ€ΠΈ ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°, поэтапно ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‰ΠΈΡ… исходный ΠΊΠΎΠ΄ ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΡ… Π² качСствС Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ прСдставлСния абстрактноС синтаксичСскоС Π΄Π΅Ρ€Π΅Π²ΠΎ (abstract syntax tree, AST). Π’ синтаксичСском Π΄Π΅Ρ€Π΅Π²Π΅ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠ΅ Π²Π΅Ρ€ΡˆΠΈΠ½Ρ‹ сопоставлСны с ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π°ΠΌΠΈ языка программирования, Π° Π»ΠΈΡΡ‚ΡŒΡ β€” с ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ ΠΎΠΏΠ΅Ρ€Π°Π½Π΄Π°ΠΌΠΈ. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ‚Π°ΠΊΠΎΠ³ΠΎ Π΄Π΅Ρ€Π΅Π²Π° ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ Π² ΠΊΠΎΠ½Ρ†Π΅ этого Ρ€Π°Π·Π΄Π΅Π»Π°.

Π€Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄

  1. ЛСксичСский Π°Π½Π°Π»ΠΈΠ· Ρ€Π°Π·Π±ΠΈΠ²Π°Π΅Ρ‚ исходный ΠΊΠΎΠ΄ Π½Π° логичСскиС ΠΊΠ²Π°Π½Ρ‚Ρ‹ (лСксСмы) β€” числа, ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ слова, ΠΈΠΌΠ΅Π½Π° ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ.
  2. БинтаксичСский Π°Π½Π°Π»ΠΈΠ· собираСт ΠΈΠ· лСксСм синтаксичСскиС конструкции, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Ρ†ΠΈΠΊΠ»Ρ‹, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ рСкурсивного спуска.
  3. Π’ процСссС рСкурсивного спуска строится абстрактноС синтаксичСскоС Π΄Π΅Ρ€Π΅Π²ΠΎ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΈ являСтся ΠΈΡ‚ΠΎΠ³ΠΎΠ²Ρ‹ΠΌ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄Π°.

ΠŸΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΉ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ‚ΠΎΡ€ (middleend)

ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ‚ΠΎΡ€ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π½Π° Π²Ρ…ΠΎΠ΄ AST ΠΈ пытаСтся ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ Π΅Π³ΠΎ, Π½Π΅ Π½Π°Ρ€ΡƒΡˆΠ°Ρ ΠΏΡ€ΠΈ этом Π»ΠΎΠ³ΠΈΠΊΡƒ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Π’ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΈΠ· ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΉ примСняСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ вычислСниС константных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ: ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ² ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ ΠΈΠ· матСматичСских ΠΈΠ»ΠΈ логичСских ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π½Π°Π΄ числами, ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ‚ΠΎΡ€ вычисляСт Π΅Π΅ ΠΈ замСняСт Π½Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚.

БэкСнд

БэкСнд ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π½Π° Π²Ρ…ΠΎΠ΄ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ AST Π΄Π΅Ρ€Π΅Π²ΠΎ ΠΈ, обходя Π΅Π³ΠΎ Π² postorder порядкС, Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π΅Ρ‚ ΠΌΠ°ΡˆΠΈΠ½Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π²Π΅Ρ€ΡˆΠΈΠ½Ρ‹. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΏΡ€ΠΈ исполнСнии ΠΊΠΎΠ΄Π° любой ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ΄ вычислСния Π΅Π΅ ΠΎΠΏΠ΅Ρ€Π°Π½Π΄ΠΎΠ² ΡƒΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½.

ОбоснованиС Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ компилятора

Вакая Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° позволяСт ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±Ρ‰ΠΈΠ΅ куски ΠΏΡ€ΠΈ Π°Π΄Π°ΠΏΡ‚Π°Ρ†ΠΈΠΈ компилятора ΠΏΠΎΠ΄ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ языки ΠΈΠ»ΠΈ ΠΏΠΎΠ΄ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹. Π’Π°ΠΊ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, компиляторы ΠΎΠ΄Π½ΠΎΠ³ΠΎ языка ΠΏΠΎΠ΄ x64 ΠΈ arm ΠΌΠΎΠ³ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±Ρ‰ΠΈΠ΅ Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄ ΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ‚ΠΎΡ€, Π° компиляторы Π΄Π²ΡƒΡ… Ρ€Π°Π·Π½Ρ‹Ρ… языков ΠΏΠΎΠ΄ ΠΎΠ΄Π½Ρƒ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ‚ΠΎΡ€ ΠΈ бэкСнд.

Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄Ρ‹ языков ICPC ΠΈ kaban54's lang Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π°Π½Ρ‹ Π² совмСстном ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅ с ReverseLang ΠΈ ΠΈΠΌΠ΅ΡŽΡ‚ совмСстимый Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ AST, ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ с использованиСм бэкСнда ReverseLang.

Подобная Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π½Π΅ являСтся Ρ‡Π΅ΠΌ-Ρ‚ΠΎ Π½ΠΎΠ²Ρ‹ΠΌ ΠΈ примСняСтся Π² сСмСйствС компиляторов GCC, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π² основанных Π½Π° llvm компиляторах, ΠΏΡ€Π°Π²Π΄Π° Π² Π½ΠΈΡ… Π² качСствС Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ прСдставлСния ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π»ΠΈΠ½Π΅ΠΉΠ½ΠΎΠ΅ прСдставлСниС вмСсто AST.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ AST

ΠŸΠΎΡΡ‚Ρ€ΠΎΠΈΠΌ AST для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΈΠ· синтаксичСской справки:

ΠŸΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°
~sya~

(x) print fn
[
; (x) __builtin_print__ return
]

(c, b, a) func fn
[
    ; b / a = d let
    (b > a) if
    {
        ; c return
    } else {
        ; d return
    }
]

; (1, 2, 3) func = ans let

; (ans) print

~nya~

img.png Визуализация AST для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΈΠ· синтаксичСской справки

Устройство бэкСнда

Π‘Π°ΠΌ бэкСнд Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½ΡƒΡŽ структуру. ΠŸΡ€ΠΎΡ†Π΅ΡΡ компиляции AST Π² ΠΌΠ°ΡˆΠΈΠ½Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ Ρ€Π°Π·Π±ΠΈΡ‚ Π½Π° Ρ‚Ρ€ΠΈ этапа:

  1. AST компилируСтся Π² Π»ΠΈΠ½Π΅ΠΉΠ½ΠΎΠ΅ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ΅ прСдставлСниС (Backend IR) β€” массив структур, ΡΠ²Π»ΡΡŽΡ‰ΠΈΡ…ΡΡ ассСмблСрным ΠΊΠΎΠ΄ΠΎΠΌ для абстрактного стСкового процСссора (ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ Π΄Π°Π»Π΅Π΅ Π² сСкции Backend IR).
  2. ПослС получСния IR ΠΌΠΎΠΆΠ½ΠΎ Π½Π°Ρ‡Π°Ρ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Π΅ ΠΏΡ€ΠΎΡ…ΠΎΠ΄Ρ‹, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΡƒΠ±ΠΈΡ€Π°Ρ‚ΡŒ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ push / pop (backend optimisations). Однако Π² Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π½ΠΈΠΊΠ°ΠΊΠΈΠ΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ Π² бэкСндС Π½Π΅ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ.
  3. Π”Π°Π»Π΅Π΅ этот IR транслируСтся Π² инструкции для ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ процСссора.

ΠŸΡ€ΠΈ этом ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ для Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ адрСсов ΠΌΠ΅Ρ‚ΠΎΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ двухпроходная схСма компиляции (multi-pass compiler), Ρ‚ΠΎ этапы 1 ΠΈ 3 Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ Π΄Π²Π° Ρ€Π°Π·Π°.

ОбоснованиС Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ бэкСнда

БэкСнд построСн Π½Π° Ρ‚Π΅Ρ… ΠΆΠ΅ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π½Ρ‹Ρ… ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ°Ρ…, Ρ‡Ρ‚ΠΎ ΠΈ компилятор Π² Ρ†Π΅Π»ΠΎΠΌ β€” Ρ€Π°Π·Π±ΠΈΠ΅Π½ΠΈΠ΅ Π½Π° этапы для ΠΈΡ… ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΡ. Backend IR позволяСт ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ Ρ‚Ρ€Π°Π½ΡΠ»ΡΡ†ΠΈΡŽ AST Π² Π½Π°Π±ΠΎΡ€ элСмСнтарных дСйствий для процСссорных Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€ схоТСго Ρ‚ΠΈΠΏΠ° ΠΈΠ»ΠΈ для Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Π²Ρ‹Ρ…ΠΎΠ΄Π½Ρ‹Ρ… Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ². Π’Π°ΠΊ, ΠΏΠΎΠΌΠΈΠΌΠΎ компиляции Π² Π±ΠΈΠ½Π°Ρ€Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» Π΄Π°Π½Π½Ρ‹ΠΉ компилятор ΡƒΠΌΠ΅Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² JIT Ρ€Π΅ΠΆΠΈΠΌΠ΅ с ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΌ Π΄ΡƒΠ±Π»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ΄Π°.

Backend IR

Π’ Π΄Π°Π½Π½ΠΎΠΌ компиляторС Π² качСствС IR ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ связный список структур

    struct instruction_t {
        instruction_type_t type;            // Π’ΠΈΠΏ инструкции β€” push / add / call / etc
        struct {                            // КакиС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ΡΡ инструкции
            unsigned char need_imm_arg: 1;  // - ΠšΠΎΠ½ΡΡ‚Π°Π½Ρ‚Π°
            unsigned char need_reg_arg: 1;  // - РСгистр
            unsigned char need_mem_arg: 1;  // - Π˜Π·Π²Π»Π΅ΠΊΠ°Π΅Ρ‚ΡΡ Π»ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ ΠΈΠ· памяти
        };

        unsigned char reg_num;              // НомСр рСгистра-Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° (Ссли ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ)
        uint64_t imm_arg;                   // ΠšΠΎΠ½ΡΡ‚Π°Π½Ρ‚Π½Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ (Ссли ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ)

        size_t index;                       // НомСр инструкции Π² IR
        instruction_t *next;                // Π£ΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΡƒΡŽ структуру
    };

ΠŸΡ€ΠΈ этом IR рассчитан Π½Π° абстрактный стСковый процСссор, Π° ΠΏΠΎΡ‚ΠΎΠΌΡƒ ΠΈΠΌΠ΅Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ инструкции:

Команда ДСйствиС
push imm/reg/mem ΠŸΠΎΠ»ΠΎΠΆΠΈΡ‚ΡŒ Π² стСк константу, Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΠ· рСгистра ΠΈΠ»ΠΈ ΠΈΠ· ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠΉ памяти ΠΏΠΎ адрСсу reg + imm, Π³Π΄Π΅ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΎΠΏΠ΅Ρ€Π°Π½Π΄ΠΎΠ² (reg ΠΈΠ»ΠΈ imm) ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»Π΅Π½.
pop reg/mem Π˜Π·Π²Π»Π΅Ρ‡ΡŒ ΠΈΠ· стСка Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚ΡŒ Π΅Π³ΠΎ Π² рСгистр ΠΈΠ»ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΡƒΡŽ ΠΏΠ°ΠΌΡΡ‚ΡŒ
add/sub/mul/div АрифмСтичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с двумя Π²Π΅Ρ€Ρ…Π½ΠΈΠΌΠΈ элСмСнтами Π½Π° стСкС (Π²Π΅Ρ€Ρ…Π½ΠΈΠΉ элСмСнт стСка являСтся ΠΏΡ€Π°Π²Ρ‹ΠΌ ΠΎΠΏΠ΅Ρ€Π°Π½Π΄ΠΎΠΌ)
sqrt / sin / cos АрифмСтичСскиС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ с ΠΎΠ΄ΠΈΠ½ элСмСнтом Π½Π° стСкС
call/jmp/j?? imm Π‘ΠΎΠ²Π΅Ρ€ΡˆΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π½Π° адрСс (Π½ΠΎΠΌΠ΅Ρ€ структуры Π² IR). j?? ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ условныС ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Ρ‹ (ja, jae, jb, jbe, je, jne)
inp / out Π’Π²ΠΎΠ΄ / Π²Ρ‹Π²ΠΎΠ΄ Π²Π΅Ρ€Ρ…Π½Π΅Π³ΠΎ элСмСнта стСка
ret Команда Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° ΠΈΠ· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, обратная ΠΊ call
halt Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Π°Π½Π°Π»ΠΎΠ³ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ abort() Π² C

ΠŸΡ€ΠΈ этом всС инструкции ΠΏΠΎΠ³Π»ΠΎΡ‰Π°ΡŽΡ‚ свои ΠΎΠΏΠ΅Ρ€Π°Π½Π΄Ρ‹, Ссли Ρ‚Π°ΠΊΠΎΠ²Ρ‹Π΅ ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ, ΠΈ ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ значСния ΠΊΠ»Π°Π΄ΡƒΡ‚ Π΅Π³ΠΎ Π½Π° Π²Π΅Ρ€Ρ…ΡƒΡˆΠΊΡƒ стСка.

Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° ELF Ρ„Π°ΠΉΠ»Π°

img.png

Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ компиляции создаСтся исполняСмый ELF Ρ„Π°ΠΉΠ», содСрТащий оттранслированный ΠΊΠΎΠ΄ ΠΈ ΠΊΠΎΠ΄ стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ.

Для этого Π² исполняСмый Ρ„Π°ΠΉΠ» записываСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ информация:

  1. Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ELF Ρ„Π°ΠΉΠ»Π° содСрТит ΠΎΠ±Ρ‰ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΏΡ€ΠΎ Π±ΠΈΠ½Π°Ρ€Π½ΠΈΠΊ: Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ процСссора, адрСс Π²Ρ…ΠΎΠ΄Π°, количСство ΠΈ мСстополоТСниС сСгмСнтных Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ².
const Elf64_Ehdr ELF_HEADER = {
    .e_ident = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, // Magic signature
                ELFCLASS64,                         // 64-bit system
                ELFDATA2LSB,                        // LittleEndian / BigEndian
                EV_CURRENT,                         // Version = Current
                ELFOSABI_NONE,                      // Non specified system
                0
                },
                
    .e_type    = ET_EXEC,                      // File type = Executable
    .e_machine = EM_X86_64,                    // Arch = amd64
    .e_version = EV_CURRENT,                   // Version = Current
    
    .e_entry   = 0x402000,                     // Fixed entry addr
    
    .e_phoff    = sizeof(Elf64_Ehdr),          // Offset of program header table. We took size of elf header
    .e_shoff    = 0,                           // Offset of segment header table. Not used => 0
    
    .e_flags    = 0,                           // Extra flags: no flags
    .e_ehsize   = sizeof(Elf64_Ehdr),	       // Size of this header.
    
    .e_phentsize = sizeof(Elf64_Phdr),         // Size of Program header table entry.
    .e_phnum     = NUM_PHEADERS,               // Number of pheader entries. (system + stdlib + code + ram)
    
    .e_shentsize = sizeof(Elf64_Shdr),         // Size of Segment header entry.
    .e_shnum     = 0,                          // Number of segments in programm.
    .e_shstrndx  = 0,                          // Index of string table. (Explained in further parts).
};
  1. Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ сСгмСнтов содСрТат Π΄Π΅Ρ‚Π°Π»ΡŒΠ½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΏΡ€ΠΎ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ сСгмСнт ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹: ΠΏΡ€Π°Π²Π° доступа, мСстополоТСниС ΠΈ Ρ€Π°Π·ΠΌΠ΅Ρ€ Π² исполняСмом Ρ„Π°ΠΉΠ»Π΅, Π° Ρ‚Π°ΠΊΠΆΠ΅ адрСс, ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π΅Π³ΠΎ слСдуСт Π·Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ. Π”Π°Π½Π½Ρ‹ΠΉ компилятор ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ лишь 4 сСгмСнта:
  • Π‘Π»ΡƒΠΆΠ΅Π±Π½Ρ‹ΠΉ сСгмСнт
Elf64_Phdr SYSTEM_PHEADER = {
        .p_type   = PT_LOAD,
        .p_flags  = PF_R       , /* read */
        .p_offset = 0          , /* (bytes into file) */
        .p_vaddr  = 0x400000   , /* (virtual addr at runtime) */
        .p_paddr  = 0x400000   , /* (physical addr at runtime) */
        .p_filesz = sizeof(Elf64_Ehdr) + NUM_PHEADERS * sizeof(Elf64_Phdr), /* (bytes in file) */
        .p_memsz  = sizeof(Elf64_Ehdr) + NUM_PHEADERS * sizeof(Elf64_Phdr), /* (bytes in mem at runtime) */
        .p_align  = 4096       , /* (min mem alignment in bytes) */
};

Π”Π°Π½Π½Ρ‹ΠΉ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ присутствуСт Π²ΠΎ всСх исполняСмых ELF Ρ„Π°ΠΉΠ»Π°Ρ… ΠΈ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ всю ΡΠ»ΡƒΠΆΠ΅Π±Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ исполняСмого Ρ„Π°ΠΉΠ»Π° ΠΏΠΎ адрСсу 0x400000 с ΠΏΡ€Π°Π²Π°ΠΌΠΈ лишь Π½Π° Ρ‡Ρ‚Π΅Π½ΠΈΠ΅.

  • Π‘Π΅Π³ΠΌΠ΅Π½Ρ‚ стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ
Elf64_Phdr STDLIB_PHEADER = {
        .p_type   = PT_LOAD,
        .p_flags  = PF_R | PF_X,           /* Read & Execute */
        .p_offset = 4096,                  /* (bytes into file) */
        .p_vaddr  = 0x401000,              /* (virtual addr at runtime) */
        .p_paddr  = 0x401000,              /* (physical addr at runtime) */
        .p_filesz = x64::STDLIB_SIZE,      /* (bytes in file) */
        .p_memsz  = x64::STDLIB_SIZE,      /* (bytes in mem at runtime) */
        .p_align  = 4096,                  /* (min mem alignment in bytes) */
};

Для простоты Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ исполняСмого Ρ„Π°ΠΉΠ»Π° стандартная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° загруТаСтся Π² собствСнный сСгмСнт ΠΏΠΎ адрСсу 0x403000 с ΠΏΡ€Π°Π²Π°ΠΌΠΈ Π½Π° исполнСниС. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΊΠΎΠ΄ ΠΈΠ· исполняСмого Ρ„Π°ΠΉΠ»Π° Π½Π° самом Π΄Π΅Π»Π΅ Π½Π΅ копируСтся, Π° лишь отобраТаСтся Π² Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ°ΠΌΡΡ‚ΡŒ, Ρ‚ΠΎ всС сСгмСнты обязаны Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒΡΡ с адрСсов, ΠΊΡ€Π°Ρ‚Π½Ρ‹Ρ… Ρ€Π°Π·ΠΌΠ΅Ρ€Ρƒ страницы β€” 4096 Π±Π°ΠΉΡ‚. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ стандартная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π²Ρ‹Π½ΡƒΠΆΠ΄Π΅Π½Π½ΠΎ записываСтся Π² Π±ΠΈΠ½Π°Ρ€Π½ΠΈΠΊ начиная с 4096 Π±Π°ΠΉΡ‚Π° (.p_offset), Π° Π½Π΅ сразу послС сСгмСнтных Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ².

  • Π‘Π΅Π³ΠΌΠ΅Π½Ρ‚ сгСнСрированного ΠΊΠΎΠ΄Π°

Π‘Π΅Π³ΠΌΠ΅Π½Ρ‚ сгСнСрированного ΠΊΠΎΠ΄Π° отличаСтся ΠΎΡ‚ стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ лишь адрСсом Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ β€” 0x402000, ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠΌ с адрСсом Π²Ρ…ΠΎΠ΄Π° ΠΈΠ· ELF Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° (ΠΏΠΎΠ»Π΅ .e_entry). Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ послС Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ELF Ρ„Π°ΠΉΠ»Π° Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ ΠΈΠΌΠ΅Π½Π½ΠΎ этот сСгмСнт.

  • Π‘Π΅Π³ΠΌΠ΅Π½Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠΉ памяти

Π“Π»Π°Π²Π½ΠΎΠ΅ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ сСгмСнта ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠΉ памяти ΠΎΡ‚ ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… β€” ΠΎΠ½ Π½Π΅ Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ‚ мСста Π½Π° дискС. ВмСсто этого ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ ELF Ρ„Π°ΠΉΠ»Π° опСрационная систСма сама Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ ΠΎΠ±Π»Π°ΡΡ‚ΡŒ памяти Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° ΠΈ Π·Π°ΠΏΠΎΠ»Π½ΠΈΡ‚ Π΅Π΅ нулями. ВыраТаСтся это Π² Π½ΡƒΠ»Π΅Π²ΠΎΠΌ ΠΏΠΎΠ»Π΅ .p_filesz, ΠΎΡ‚Π²Π΅Ρ‡Π°ΡŽΡ‰ΠΈΠΌ Π·Π° Ρ€Π°Π·ΠΌΠ΅Ρ€ сСгмСнта Π² Ρ„Π°ΠΉΠ»Π΅, ΠΈ Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠΌ .p_memsz, ΠΎΡ‚Π²Π΅Ρ‡Π°ΡŽΡ‰ΠΈΠΌ Π·Π° Ρ€Π°Π·ΠΌΠ΅Ρ€ послС Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ.

const Elf64_Phdr BSS_PHEADER = {
        .p_type   = PT_LOAD,
        .p_flags  = PF_R | PF_W,
        .p_offset = 0,              /* (bytes into file) */
        .p_vaddr  = 0x405000,       /* (virtual addr at runtime) */
        .p_paddr  = 0x405000,       /* (physical addr at runtime) */
        .p_filesz = 0,              /* (bytes in file) */
        .p_memsz  = x64::RAMSIZE,   /* (bytes in mem at runtime) */
        .p_align  = 4096,           /* (min mem alignment in bytes) */
};

Бтандартная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°

Π’ стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅ ReverseLang Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ β€” Π²Π²ΠΎΠ΄/Π²Ρ‹Π²ΠΎΠ΄, ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ корня ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ (для инструкции halt). Π”Π°Π½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ написаны Π½Π° ассСмблСрС с прямым использованиСм систСмных Π²Ρ‹Π·ΠΎΠ²ΠΎΠ², Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ нСобходимости Π»ΠΈΠ½ΠΊΠΎΠ²ΠΊΠΈ с glibc ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎΠ³ΠΎ услоТнСния структуры ELF Ρ„Π°ΠΉΠ»Π°. Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ stdlib находится Π² src/asm_stdlib/stdlib.nasm.

Бтандартная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° собираСтся Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» для Π»ΠΈΠ½ΠΊΠΎΠ²ΠΊΠΈ с компилятором (Π³Π΄Π΅ ΠΎΠ½Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π² JIT Ρ€Π΅ΠΆΠΈΠΌΠ΅), Π° Ρ‚Π°ΠΊ ΠΆΠ΅ Π² исполняСмый Ρ„Π°ΠΉΠ» для удобства ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. ΠŸΡ€ΠΈ этом для ясности ΠΏΡ€ΠΈ запускС стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΊΠ°ΠΊ исполняСмого Ρ„Π°ΠΉΠ» ΠΎΠ½Π° Π²Ρ‹Π²Π΅Π΄Π΅Ρ‚ справочноС сообщСниС ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ свою Ρ€Π°Π±ΠΎΡ‚Ρƒ.

Π‘Π±ΠΎΡ€ΠΊΠ° стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ происходит автоматичСски с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ make, ΠΎΠ΄Π½Π°ΠΊΠΎ это ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΈ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ:

    $ cd src/asm_strlib
    $ nasm -f elf64 stdlib.asm                        # Π‘Π±ΠΎΡ€ΠΊΠ° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°
    $ ld -e stub_entry -s -S stdlib.o -o stdlib.out # Π‘Π±ΠΎΡ€ΠΊΠ° Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°

Π˜ΡΠΏΠΎΠ»Π½ΡΠ΅ΠΌΡ‹ΠΉ Ρ„Π°ΠΉΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΡ€ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ ΠΊΠΎΠ΄Π° стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Π² Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ Π±ΠΈΠ½Π°Ρ€Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ». ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ stdlib.out, Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Π΅Π³ΠΎ ELF Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΈ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ содСрТащийся Ρ‚Π°ΠΌ ΠΊΠΎΠ΄ Π² Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΉ Ρ„Π°ΠΉΠ». Однако компилятору для обращСния ΠΊ функциям Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Ρ‚Π°ΠΊΠΆΠ΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π·Π½Π°Ρ‚ΡŒ ΠΈΡ… смСщСния, информация ΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… нСльзя ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ простым ΠΏΡƒΡ‚Π΅ΠΌ Π°Π½Π°Π»ΠΈΠ·Π° Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² сСгмСнтов. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅ ΠΌΠ°Π»ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΈ ΠΎΠ½ΠΈ практичСски Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ, Π±Ρ‹Π»ΠΎ принято Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ смСщСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΊΠ°ΠΊ константы.

Π£Π·Π½Π°Ρ‚ΡŒ ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ readelf, ΠΏΡ€ΠΎΠ°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π² с Π΅Π΅ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ:

    $ readelf -a stdlib.o
        ... 48 строк ΠΏΡ€ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ ...

Π’Π°Π±Π»ΠΈΡ†Π° символов Β«.symtabΒ» содСрТит 16 элСмСнтов:
   Чис:    Π—Π½Π°Ρ‡           Π Π°Π·ΠΌ Π’ΠΈΠΏ     Бвяз   Vis      ИндСкс ΠΈΠΌΠ΅Π½ΠΈ
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS stdlib.nasm
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 .text
     3: 000000000000004f     0 NOTYPE  LOCAL  DEFAULT    1 input_asm.L6
     4: 0000000000000059     0 NOTYPE  LOCAL  DEFAULT    1 input_asm.L4
     5: 0000000000000081     0 NOTYPE  LOCAL  DEFAULT    1 input_asm.L19
     6: 0000000000000092     0 NOTYPE  LOCAL  DEFAULT    1 input_asm.L18
     7: 00000000000000a6     0 NOTYPE  LOCAL  DEFAULT    1 input_asm.L16
     8: 0000000000000175     0 NOTYPE  LOCAL  DEFAULT    1 output_asm.L28
     9: 00000000000001a6     0 NOTYPE  LOCAL  DEFAULT    1 output_asm.L27
    10: 00000000000001bf     0 NOTYPE  LOCAL  DEFAULT    1 output_asm.L29
    11: 00000000000001e3     0 NOTYPE  LOCAL  DEFAULT    1 output_asm.L30
    12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 input_asm
    13: 00000000000000ad     0 NOTYPE  GLOBAL DEFAULT    1 output_asm
    14: 00000000000001ef     0 NOTYPE  GLOBAL DEFAULT    1 exit_asm
    15: 00000000000001fb     0 NOTYPE  GLOBAL DEFAULT    1 sqrt_asm

Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· Π²Ρ‹Π²ΠΎΠ΄Π° этой ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, ΠΊΠΎΠ΄ input_asm находится Π² самом Π½Π°Ρ‡Π°Π»Π΅, output_asm начинаСтся со смСщСния 0xAD ΠΈ Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅.

Π‘Ρ€Π°Π²Π½Π΅Π½ΠΈΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Ρ€Π°Π±ΠΎΡ‚Ρ‹

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌ сСмСстрС Π±Ρ‹Π» написан бэкСнд для эмулятора стСкового процСссора (Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ бэкСнда ΠΈ эмулятора), Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΡ€Π°Π²Π½ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Π½Π°Ρ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ x64 ΠΊΠΎΠ΄Π° с запуском Π½Π° эмуляторС стСкового процСссора. Для сравнСния ΠΈΠ·ΠΌΠ΅Ρ€ΠΈΠΌ врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π΄Π²ΡƒΡ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ: Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ уравнСния $2xΒ² + 2x - 12 = 0$ ΠΈ расчСт 15-Π³ΠΎ числа Π€ΠΈΠ±ΠΎΠ½Π°Ρ‡Ρ‡ΠΈ, ΠΊΠΎΠ΄ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… располоТСн Π² examples/ (исходники: ΡƒΡ€Π°Π²Π½Π΅Π½ΠΈΠ΅, Π€ΠΈΠ±ΠΎΠ½Π°Ρ‡Ρ‡ΠΈ).

ΠœΠ΅Ρ‚ΠΎΠ΄ΠΈΠΊΠ° ΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½ΠΈΠΉ

Для увСличСния Π·Π°Ρ‚Ρ€Π°Ρ‡Π΅Π½Π½ΠΎΠ³ΠΎ Π½Π° Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΈ ΠΏΠΎΠ²Ρ‹ΡˆΠ΅Π½ΠΈΡ точности ΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½ΠΈΠΉ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ запускаСтся 10000 Ρ€Π°Π·. ΠŸΡ€ΠΈ этом Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ проводится ΠΏΡΡ‚ΡŒ запусков, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π² послСдствии ΡƒΡΡ€Π΅Π΄Π½ΡΡŽΡ‚ΡΡ ΠΈ считаСтся ΠΏΠΎΠ³Ρ€Π΅ΡˆΠ½ΠΎΡΡ‚ΡŒ.

Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡ ΠΎ тСстовом стСндС
    OS: Arch Linux (22.05.2023)
    Kernel: linux-6.3.1
    CPU: Ryzen 7 4800H
    CPU Governor: perfomance (max frequency) 
    
    Никаких ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ, ΠΊΡ€ΠΎΠΌΠ΅ тСстируСмой ΠΈ слуТСбных, Π²ΠΎ врСмя ΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½ΠΈΠΉ Π½Π΅ Π·Π°ΠΏΡƒΡ‰Π΅Π½ΠΎ, Π° Ρ‚Π°ΠΊΠΆΠ΅ тСстируСмой ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ Π²Ρ‹Π΄Π°Π½ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ (ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ nice выставлСн Π² -20).

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½ΠΈΠΉ:

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° x64 stack cpu УскорСниС
ΠšΠ²Π°Π΄Ρ€Π°Ρ‚Π½ΠΎΠ΅ ΡƒΡ€Π°Π²Π½Π΅Π½ΠΈΠ΅ 9.3 Β± 0.2 ms 50.6 Β± 0.5 ms 5.44 Β± 0.03
Число Π€ΠΈΠ±ΠΎΠ½Π°Ρ‡Ρ‡ΠΈ 68.2 Β± 0.7 ms 403.1 Β± 0.9 ms 5.910 Β± 0.012

Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹, использованиС Π½Π°Ρ‚ΠΈΠ²Π½ΠΎΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ вмСсто эмулятора Π΄Π°Π΅Ρ‚ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ прирост Π² ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ (Π² 5.5 Ρ€Π°Π·).

About

Compiler from own ReverseLang into x64

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published