Системски софтвер/Јун 2022 — разлика између измена
ознака: враћена измена |
ознака: поништење |
||
| Ред 7: | Ред 7: | ||
<syntaxhighlight lang="asm"> | <syntaxhighlight lang="asm"> | ||
.intel_syntax noprefix | .intel_syntax noprefix | ||
. | .section .text | ||
.global | .global min, la1 | ||
min: enter 0, 0 # 0x00 | |||
mov rbx, la1 # 0x04 | |||
cmp rbx, [rbp]+0x12 # 0x0c | |||
call var[rip] # 0x10 | |||
jle la1 # 0x16 | |||
mov rax, [rbp]+0x12 # 0x18 | |||
jmp la2 # 0x1c | |||
la1: mov rax, rbx # 0x1e | |||
la2: leave # 0x21 | |||
ret # 0x22 | |||
.data | .data | ||
. | .global var | ||
.type var, @object | |||
var: | |||
.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'' релативно адресирање. | ||
=== Решење === | === Решење === | ||
{| 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
.section .text
.global min, la1
min: enter 0, 0 # 0x00
mov rbx, la1 # 0x04
cmp rbx, [rbp]+0x12 # 0x0c
call var[rip] # 0x10
jle la1 # 0x16
mov rax, [rbp]+0x12 # 0x18
jmp la2 # 0x1c
la1: mov rax, rbx # 0x1e
la2: leave # 0x21
ret # 0x22
.data
.global var
.type var, @object
var:
.quad la1, la2-4
.end
Напомена: хексадецимални бројеви наведени у коментару изворног асемблерског кода представљају померај до почетка инструкције у том реду гледано од почетка секције којој инструкција припада. Такође, усвојити претпоставку да је величина операционог кода:
- 2B за инструкцију
callза PC релативно адресирање, - 4B за инструкцију
movза апсолутно адресирање и - 1B за инструкције
jleиjmpза PC релативно адресирање.
Решење
| 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 |
Иако није приказано у школском формату, симболи означени преко .type simbol, @object имају тип OBJECT у GNU асемблеру.
| 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 не морају да постоје, пошто се померај може уградити и током асемблирања.
| Offset | Type | Symbol | Addend |
|---|---|---|---|
| 0 | R_X86_64_64 | 6 (la1) | 0 |
| 8 | R_X86_64_64 | 1 (.text) | 1D |
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
|
Класификација |
|---|---|---|
|
|
|
SMNT_E |
|
|
|
OK-LOC |
|
|
|
OK-GLB |
struct
{
double d;
|
double d;
|
OK-LOC |
|
|
|
SMNT_E |
|
|
|
OK-GLB |
|
|
|
LINK_E |
|
|
|
OK-LOC |
|
|
|
SMNT_E |
|
|
|
OK-LOC |
4. задатак
Поставка
Посматра се JIT емулатор и емулирање следећег програма.
- Означити све блокове који ће у току рада емулатора бити преведени. За сваки преведени блок навести јединствену идентификацију у облику
B<n>(<x>-<y>)(<n>је редни број блока у погледу тренутка његовог превођења при чему нумерација почиње од броја један, <x> је редни број прве а <y> редни број последње линије изворног кода блока). - Навести секвенцу извршавања. У секвенци извршавања могу се нађи само
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
Решење
- Блокови по редоследу додавања у табелу (B3 је додат у табелу док још није био преведен):
- B0(1-5)
- B1(4-5)
- B2(6-6)
- B3(9-9)
- B4(7-8)
- B5(3-3)
- Редослед извршавања:
- GP
- B0
- BH
- GP
- B1
- BH (уколико се приликом превођења B1 није извршила оптимизација да се уместо branch helper угради скок на B1)
- B1
- B1
- BH
- GP
- B2
- BH
- GP
- B4
- BH
- GP
- B5
- B1
- B1
- B1
- B1
- B1
- BH
- B2
- BH
- GP
- B3
- BH
- GP