Системски софтвер/Пробни тестови 2022
Пробни тестови 2022 били су дати на Moodle курсу предмета.
- За питања са више одговора, тачни одговори су подебљани и уоквирени
- За питања за које се одговори уносе, тачни одговори су подвучени и сакривени, тако да се прикажу када изаберете тај текст (пример: овако)
- Притисните лево дугме испод за сакривање и откривање свих одговора, или десно дугме за укључивање и искључивање интерактивног режима:
К1 - теорија
1. задатак
У наставку су дате дефиниције неких типова података StructTypeA
и StructTypeB
:
typedef struct
{
char fA1;
long fA2;
short fA3;
} StructTypeA;
typedef struct
{
int fB1;
int fB2;
short fB3;
StructTypeA fB4;
char fB5;
short fB6;
} StructTypeB;
Допунити следеће констатације уколико се посматра amd64 архитектура и System V ABI конвенција:
- Величина структуре
StructTypeB
изражено у бајтовима односноsizeof(StructTypeB)
износи 48. - Померај до поља
fB4.fA1
гледано од почетка структуреStructTypeB
износи 16 изражено у броју адресибилних јединица (бајтова). - Најдужи континуални низ неискоришћених односно padding бајтова у оквиру структуре
StructTypeB
почиње на померају 17 изражено у броју адресибилних јединица (бајтова) гледано од почетка структуреStructTypeB
. - Структура
StructTypeB
садржи укупно 24 неискоришћених односно padding бајтова.
Напомене:
- Све одговоре треба унети у децималном формату.
2. задатак
У наставку је дата декларација функције foo
и дефиниције пратећих типова података:
typedef struct
{
long f1;
long f2;
long f3;
} StructType;
extern StructType foo(
char param0,
double param1,
StructType param2,
void * param3,
StructType param4,
float param5,
long param6);
Допунити следеће констатације уколико се посматра amd64 архитектура и System V ABI конвенција:
- Повратна вредност функције
foo
прослеђује се као меморијски простор алоциран од стране позиваоца назад до позиваоца.
- Параметар
param0
прослеђује се као rsi у функцијуfoo
приликом њеног позива. - Параметар
param1
прослеђује се као xmm0 у функцијуfoo
приликом њеног позива. - Параметар
param2
прослеђује се као stackPushII у функцијуfoo
приликом њеног позива. - Параметар
param3
прослеђује се као rdx у функцијуfoo
приликом њеног позива. - Параметар
param4
прослеђује се као stackPushI у функцијуfoo
приликом њеног позива. - Параметар
param5
прослеђује се као xmm1 у функцијуfoo
приликом њеног позива. - Параметар
param6
прослеђује се као rcx у функцијуfoo
приликом њеног позива.
Напомене:
- Одговор комбинација GP представља одређену комбинацију (више од једног) искључиво General Purpose регистара.
- Одговор комбинација SSE представља одређену комбинацију (више од једног) искључиво Streaming SIMD Extension регистара.
- Одговор комбинација GP/SSE представља одређену комбинацију (више од једног) General Purpose и Streaming SIMD Extension регистара.
- Одговор stackPush<roman-numeral>, где је <roman-numeral> римски број, представља аргумент који се прослеђује преко стека при чему римски број означава међусобни поредак push операција односно редослед стављања датог аргумента на врх стека у односу на друге аргументе који се такође прослеђују преко стека.
3. задатак
Да ли функција, која током свог извршавања позива друге функције, сме без претходне алокације да користи стек за чување локалних променљивих уколико се посматра amd64 архитектура и System V ABI конвенција?
- Да, јер надаље позване функције неће мењати садржај меморије који одговара врху стека.
- Да, услед постојања имплицитне алокације стека приликом уласка у функцију.
- Да, због постојања "црвене зоне".
- Не.
4. задатак
У наставку је дат садржај датотеке syscall.s са изворним асемблерским кодом:
.intel_syntax noprefix
.data
message:
.asciz "Hello World!\n"
.text
loop:
jmp loop
entry:
mov rax, 1
mov rdi, 1
mov rsi, offset message
mov rdx, offset 13
syscall
mov rax, 60
mov rdi, 0
syscall
.end
Посматра се amd64 архитектура и System V ABI конвенција, а покренуте су следеће команде:
as -o syscall.o syscall.s ld --entry=entry -o executable syscall.o ./executable
- Није могуће добити извршну датотеку executable зато што у процес линковања нису укључене C runtime објектне датотеке.
- Није могуће добити извршну датотеку executable зато што у процес линковања није укључена стандардна C библиотека.
- Програм се регуларно извршава и исписује поруку Hello World! на стандардни излаз.
- Програм се регуларно извршава, али неће исписати поруку Hello World! зато што се врти у бесконачној петљи.
- Није могуће добити извршну датотеку executable зато што симбол који представља улазну тачку није видљив линкеру.
5. задатак
Посматра се програм описан садржајем дела меморије и сегментом изворног C кода.
Иницијални садржај дела меморије (дат у "школском" формату приказаном на аудиторним вежбама):
+7 +6 +5 +4 +3 +2 +1 +0 | 0xAA | 0xAA | 0xAA | 0xAA | 0x99 | 0x99 | 0x99 | 0x99 | <--- 0x8000004500 + 0x20 | 0x88 | 0x88 | 0x88 | 0x88 | 0x77 | 0x77 | 0x77 | 0x77 | <--- 0x8000004500 + 0x18 | 0x66 | 0x66 | 0x66 | 0x66 | 0x55 | 0x55 | 0x00 | 0x00 | <--- 0x8000004500 + 0x10 | 0x00 | 0x80 | 0x00 | 0x00 | 0x45 | 0x02 | 0x33 | 0x33 | <--- 0x8000004500 + 0x08 | 0x22 | 0x22 | 0x22 | 0x22 | 0x11 | 0x11 | 0x11 | 0x11 | <--- 0x8000004500 + 0x00
Сегмент изворног C кода:
#include <stdio.h>
#include <stdint.h>
extern uint64_t identifier;
void main()
{
printf("%#lx", identifier);
uint64_t *a = (uint64_t *)identifier;
printf("%p", a);
printf("%#lx", a[0]);
printf("%#lx", a[1]);
uint64_t *b = (uint64_t *)&identifier;
printf("%p", b);
printf("%#lx", b[0]);
printf("%#lx", b[1]);
}
Допунити следеће констатације уколико се посматра amd64 архитектура и System V ABI конвенција, а симбол identifier
има вредност 0x800000450A
:
- Наредба
printf("%#lx", identifier);
исписује 0x8000004502. - Наредба
printf("%p", a);
исписује 0x8000004502. - Наредба
printf("%#lx", a[0]);
исписује 0x3333222222221111. - Наредба
printf("%#lx", a[1]);
исписује 0x8000004502. - Наредба
printf("%p", b);
исписује 0x800000450A. - Наредба
printf("%#lx", b[0]);
исписује 0x8000004502. - Наредба
printf("%#lx", b[1]);
исписује 0x7777666666665555.
Напомене:
- Уколико неку вредност није могуће одредити на основу датог садржаја дела меморије као одговор треба унети знак питања (?)
- Све одговоре за успешно одређене вредности треба унети у истом формату каквом их програм исписује.
- Формат
"%p"
служи за испис вредности показивача у хексадецималном формату са префиксом0x
(након префикса не исписују се водеће нуле). - Формат
"%#x"
служи за испис неозначеног целог броја у хексадецималном формату са префиксом0x
(након префикса не исписују се водеће нуле).
К1 - задатак
Поставка
У наставку је дат сегмент изворног асемблерског кода написан за amd64 архитектуру према System V ABI конвенцији:
.intel_syntax noprefix
.extern bar
.text
.global foo
.type foo, @function
foo:
endbr64
sub rsp, 72
mov rdi, rsp
mov r8d, DWORD PTR 132[rsp]
mov ecx, 9
mov edx, DWORD PTR 96[rsp]
mov esi, 2
call bar
mov eax, DWORD PTR 44[rsp]
add eax, DWORD PTR 28[rsp]
add rsp, 72
ret
Написати сегмент изворног C кода, који одговара наведеном сегменту изворног асемблерског кода, тако да садржи само следеће елементе:
- дефиниције потенцијално потребних типова података,
- декларацију функције
bar
и - дефиницију функције
foo
.
Напомене:
- Уколико се текстуални едитор Ace не учита на исправан начин треба освежити интернет страницу односно извршити refresh (претходно унети одговори на друга питања чувају се на серверу и неће бити изгубљени услед освежавања интернет странице).
- Кликом на дугме за проверу решења могуће је одмах, чак и пре предаје, испитати исправност решења. Penalty regime дефинише износ казне односно пенала за сваку проверу решења изражено у процентима максималног могућег броја поена за ово питање. У складу са вредношћу Penalty regime пенали за проверу решења редом износе 0%, 0%, 0%, 30%, 40%, 50% и 60%. Дакле, само прве три провере решења не узрокују никакав пенал, четврта провера решења узрокује пенал од 30%, пета пенал од 40%, шеста пенал од 50%, док свака провера решења почев од седме узрокује пенал од 60% (потпуно тачно решење које је проверавано седам или више пута биће оцењено са (100 - 60)% поена).
Решење
typedef struct
{
int array[16];
} StructType;
extern StructType bar(int a, int b, int c, int d);
int foo(StructType param)
{
StructType result = bar(2, param.array[4], 9, param.array[13]);
return result.array[7] + result.array[11];
}