Системски софтвер/Јун 2022 — разлика између измена

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу
м (Takođe objašnjenje zašto ovo ispunjava uslove zadatka)
ознака: враћена измена
Ред 7: Ред 7:
<syntaxhighlight lang="asm">
<syntaxhighlight lang="asm">
.intel_syntax noprefix
.intel_syntax noprefix
.section .text
.extern a
.global min, la1
.global f
min: enter 0, 0          # 0x00
.type f, @object
    mov rbx, la1        # 0x04
.equ f, b-c
     cmp rbx, [rbp]+0x12 # 0x0c
 
     call var[rip]      # 0x10
.text
    jle la1            # 0x16
call a[+ip] # 0x00
    mov rax, [rbp]+0x12 # 0x18
e: mov rax, c # 0x06
    jmp la2            # 0x1c
  jz e     # 0x0e
la1: mov rax, rbx       # 0x1e
  jz c     # 0x10
la2: leave              # 0x21
d: mov rax, [b - f] # 0x16
    ret                # 0x22
  .long e       # 0x1e


.data
.data
.global var
.skip 0x6 # 0x00
.type var, @object
c: .long b + 0xe # 0x06
var:
b:
.quad la1, la2-4
.end
.end
</syntaxhighlight>
</syntaxhighlight>
Напомена: хексадецимални бројеви наведени у коментару изворног асемблерског кода представљају померај до почетка инструкције у том реду гледано од почетка секције којој инструкција припада. Такође, усвојити претпоставку да је величина операционог кода:
''Напомена:'' Хексадецимални бројеви наведени у коментару изворног асемблерског кода представљају померај до почетка инструкције у том реду гледано од почетка секције којој инструкција припада. Такође, усвојити претпоставку да је величина операционог кода:
* 2B за инструкцију <code>call</code> за ''PC'' релативно адресирање,
* 2B за инструкцију <code>call</code> за ''PC'' релативно адресирање,
* 4B за инструкцију <code>mov</code> за апсолутно адресирање и
* 4B за инструкцију <code>mov</code> за апсолутно адресирање и
* 1B за инструкције <code>jle</code> и <code>jmp</code> за ''PC'' релативно адресирање.
* 2B или 1B за инструкције скока за ''PC'' релативно адресирање, у зависности од ширине операнда.


=== Решење ===
=== Решење ===
{| class="wikitable"
|+ <code>.symtab</code>
! Num !! Value !! Size !! Type  !! Bind !! Ndx !! Name
|-
| 0:  || 0    || 0    || NOTYP || LOC  || UND ||
|-
| 1:  || 0    || 0    || SCTN  || LOC  || 1  || .text
|-
| 2:  || 0    || 0    || SCTN  || LOC  || 2  || .data
|-
| 3:  || 0    || 0    || SCTN  || LOC  || 3  || .bss
|-
| 4:  || 21    || 0    || NOTYP || LOC  || 1  || la2
|-
| 5:  || 0    || 0    || NOTYP || GLOB || 1  || min
|-
| 6:  || 1E    || 0    || NOTYP || GLOB || 1  || la1
|-
| 7:  || 0    || 0    || OBJ  || GLOB || 2  || var
|}
Иако није приказано у школском формату, симболи означени преко <syntaxhighlight lang="asm" inline>.type simbol, @object</syntaxhighlight> имају тип <code>OBJECT</code> у ''GNU'' асемблеру.
{| class="wikitable"
|+ <code>.rela.text</code>
! Offset !! Type          !! Symbol    !! Addend
|-
| 8      || R_X86_64_32  || 6 (la1)  || 0
|-
| 12    || R_X86_64_PC32 || 7 (var)  || -4
|-
| 17    || R_X86_64_PC8  || 6 (la1)  || -1
|-
| 1D    || R_X86_64_PC8  || 1 (.text) || 20
|}
Релокациони записи на 17 и 1D не морају да постоје, пошто се померај може уградити и током асемблирања.
{| class="wikitable"
|+ <code>.rela.data</code>
! Offset !! Type          !! Symbol    !! Addend
|-
| 0      || R_X86_64_64  || 6 (la1)  || 0
|-
| 8      || R_X86_64_64  || 1 (.text) || 1D
|}


== 2. задатак ==
== 2. задатак ==

Верзија на датум 21. септембар 2025. у 16:28

Испит у јунском испитном року 2022. године одржан је 16. јуна. Трајао је 2 сата и радио се у вежбанкама.

1. задатак

Поставка

Посматра се процес асемблирања датог ивзорног асемблерског кода за amd64 архитектуру. Резултат асемблирања је предметни програм по ELF формату. Приказати садржај (1) табеле симбола и (2) релокационих записа строго поштујући школски формат и обавезно у складу са задатом нумерацијом симбола.

.intel_syntax noprefix
.extern a
.global f
.type f, @object
.equ f, b-c

.text
call a[+ip] # 0x00
e: mov rax, c # 0x06
   jz e      # 0x0e
   jz c      # 0x10
d: mov rax, [b - f] # 0x16
   .long e        # 0x1e

.data
.skip 0x6 # 0x00
c: .long b + 0xe # 0x06
b:
.end

Напомена: Хексадецимални бројеви наведени у коментару изворног асемблерског кода представљају померај до почетка инструкције у том реду гледано од почетка секције којој инструкција припада. Такође, усвојити претпоставку да је величина операционог кода:

  • 2B за инструкцију call за PC релативно адресирање,
  • 4B за инструкцију mov за апсолутно адресирање и
  • 2B или 1B за инструкције скока за PC релативно адресирање, у зависности од ширине операнда.

Решење

2. задатак

Поставка

У C претпроцесору треба написати макри дефиницију REPEAT(str, n) која као свој резултат даје стринг str надовезан n пута на самог себе за вредности параметра n између 0 и 5. На пример, макро позив REPEAT("ha ", 3) резултује стрингом "ha ha ha ". Треба имати на уму да C претпроцесор не дозвољава рекурзију (макро не може рекурзивно позвати самог себе) нити дозвољава коришћење #if у телу макроа.

Решење

#define REP0(X)
#define REP1(X) X
#define REP2(X) REP1(X) X
#define REP3(X) REP2(X) X
#define REP4(X) REP3(X) X
#define REP5(X) REP4(X) X
#define REPEAT(str, n) REP##n(str)

При позиву REPEAT("ha ", 3) макропроцесор ће генерисати "ha " "ha " "ha " што је еквивалентно стрингу "ha ha ha " (тако функционише конкатенација стринг литерала у C). Ово понашање је било напоменуто на испиту.

3. задатак

Поставка

Задати модули main.c и other.c одвојено се преводе и потом статички повезују у јединствену извршну датотеку помоћу GNU ланца алата. Приликом повезивања не користе се други модули нити библиотеке. Треба попунити сваки од коментара /* ??? */ у датотеци other.c једном од наведених ознака које дефинишу какав ефекат изазива декларација која претходи коментару на датој линији:

  • OK-GLB: ово је исправна декларација променљиве која је глобална и за main.c и за other.c (глобална у смислу да ће се промена коју направи foo() функција коректно рефлектовати и у main() функцији као и обрнуто),
  • OK-LOC: ово је исправна декларација променљиве која је локална само за foo() (локална у смислу да се било која промена коју направи foo() функција неће рефлектовати на main() функцију),
  • CMPL_E: ова декларација ће изазвати пријаву грешке од стране преводиоца (линкер неће бити ни покренут),
  • LINK_E: ова декларација ће изазвати пријаву грешке од стране линкера (обе датотеке биће преведене без грешке, али линкер ће пријавити грешку приликом повезивања на симболу на датој линији),
  • SMNT_E: ова декларација неће изазвати пријаву никакве грешке (ни преводиоца нити линкера), али ће програм имати семантичку грешку односно логичку неисправност која се може манифестовати током његовог извршавања и
  • OTHR_E: дешава се нека друга грешка која није покривена претходним случајевима.
// file main.c
extern int a;
static double b;
int help; int *c = &help;
struct
{
  double d;
} e;
int f = 0;
double g = 0.1;
#define h 99
int i;
unsigned j;

int main() {
  // ...
}

// file other.c
double a;       /* ??? */
double b;       /* ??? */
int *c;         /* ??? */


double d;       /* ??? */
int e = 0;      /* ??? */
int f;          /* ??? */
double g = 0.1; /* ??? */
int h = 99;     /* ??? */
unsigned *i;    /* ??? */
static int j;   /* ??? */

int foo() {
  // ...
}

Решење

main.c other.c Класификација

extern int a;

double a;

SMNT_E

static double b;

double b;

OK-LOC

int help; int *c = &help;

int *c;

OK-GLB
struct
{
  double d;
double d;
OK-LOC

} e;

int e = 0;

SMNT_E

int f = 0;

int f;

OK-GLB

double g = 0.1;

double g = 0.1;

LINK_E

#define h 99

int h = 99;

OK-LOC

int i;

unsigned *i;

SMNT_E

unsigned j;

static int j;

OK-LOC

4. задатак

Поставка

Посматра се JIT емулатор и емулирање следећег програма.

  1. Означити све блокове који ће у току рада емулатора бити преведени. За сваки преведени блок навести јединствену идентификацију у облику B<n>(<x>-<y>) (<n> је редни број блока у погледу тренутка његовог превођења при чему нумерација почиње од броја један, <x> је редни број прве а <y> редни број последње линије изворног кода блока).
  2. Навести секвенцу извршавања. У секвенци извршавања могу се нађи само GP (сваки пут када се емулатор врати у главну петљу), BH (сваки пут када се позове функција која помаже у разрешавању скокова) и B<n> (сваки пут када се изврши дати блок у складу са ознакама из претходне тачке).
      BEG       ; line  1
      LDI 2     ; line  2   ( PZ) A <= <V>
  L1  SUB B     ; line  3   (CPZ) A <= A - mem[<V>]
  L2  ADD C     ; line  4   (CPZ) A <= A + mem[<V>]
      BNG L2    ; line  5         if (!flags[P]) PC <= <V>
      BZE L3    ; line  6         if ( flags[Z]) PC <= <V>
      SBI 2     ; line  7   (CPZ) A <= A - <V>
      BNZ L1    ; line  8         if (!flags[Z]) PC <= <V>
  L3  HLT       ; line  9         stop execution
  B   DC 9      ; line 10
  C   DC 2      ; line 11
      END       ; line 12

Решење

  1. Блокови по редоследу додавања у табелу (B3 је додат у табелу док још није био преведен):
    1. B0(1-5)
    2. B1(4-5)
    3. B2(6-6)
    4. B3(9-9)
    5. B4(7-8)
    6. B5(3-3)
  2. Редослед извршавања:
    1. GP
    2. B0
    3. BH
    4. GP
    5. B1
    6. BH (уколико се приликом превођења B1 није извршила оптимизација да се уместо branch helper угради скок на B1)
    7. B1
    8. B1
    9. BH
    10. GP
    11. B2
    12. BH
    13. GP
    14. B4
    15. BH
    16. GP
    17. B5
    18. B1
    19. B1
    20. B1
    21. B1
    22. B1
    23. BH
    24. B2
    25. BH
    26. GP
    27. B3
    28. BH
    29. GP