Системски софтвер/К1 Јул 1 2025
Први колоквијум у року јул 1 2025. године одржан је 21. августа 2025. На колоквијуму су од литературе били доступни SystemV ABI и amd64 Architecture Programmer's Manual. Траја је 40 минута и садржао само теоријски део који се скалирао на 20 поена. Иста поставка дошла је и у року септембар 1 2025. године, на испиту одржаном 21. септембра, под истим условима полагања.
- За питања са више одговора, тачни одговори су подебљани и уоквирени
- За питања за које се одговори уносе, тачни одговори су подвучени и сакривени, тако да се прикажу када изаберете тај текст (пример: овако)
- Притисните лево дугме испод за сакривање и откривање свих одговора, или десно дугме за укључивање и искључивање интерактивног режима:
1. задатак
Посматра се програм дефинисан изворним C кодом и изворним асемблерским кодом добијеним превођењем датог изворног C кода:
Изворни C код:
extern void bar();
int foo()
{
int temp[8];
bar();
}
Изворни асемблерски код:
.intel_syntax noprefix
.text
.global foo
.type foo, @function
foo:
endbr64
push rbp
mov rbp, rsp
sub rsp, 32
mov eax, 0
call bar
nop
leave
ret
Шта је тачно за функцију foo уколико се посматра amd64 архитектура и System V ABI конвенција? Изаберите један или више одговора:
- Функција foo морала је да алоцира више простора на стеку него што јој је суштински потребно ради обезбеђивања поравнања за локални подаци.
- Функција foo морала је да алоцира више простора на стеку него што јој је суштински потребно ради очувања гарантованог поравнања области за аргументе позиваних функција.
- Простор који користи на стеку функција foo мора првобитно да алоцира због постојања "црвене зоне".
- Величина простора на стеку, који алоцира функција foo, једнака је збиру величина података смештених на стек.
- Простор који користи на стеку функција foo мора првобитно да алоцира због тога што позива друге функције.
2. задатак
У наставку је дата дефиниција неког типа података StructType:
typedef struct
{
int f1;
char f2;
int f3;
char f4;
int f5;
char f6;
} StructType;
Означити у наставку шта представља сваки бајт дела меморије (дат у "школском" формату приказаном на аудиторним вежбама) под следећим претпоставкама:
- структура
StructTypeсмештена је на прво одговарајуће слободно место у датом делу меморије, - слободан простор у датом делу меморије почиње на адреси
0x8000004502и - посматра се amd64 архитектура и System V ABI конвенција.
| +7 | +6 | +5 | +4 | +3 | +2 | +1 | +0 |
|---|---|---|---|---|---|---|---|
| out | out | out | out | padd | padd | padd | f6 |
| f5 | f5 | f5 | f5 | padd | padd | padd | f4 |
| f3 | f3 | f3 | f3 | padd | padd | padd | f2 |
| f1 | f1 | f1 | f1 | out | out | out | out |
Напомене:
- Одговор
outпредставља бајт изван посматране структуре. - Одговор
paddпредставља неискоришћени односно padding бајт унутар посматране структуре.
3. задатак
Који од наведених регистара позвана функција пре промене њихове вредности прво мора да сачува оригиналну вредност ради касније рестаурације уколико се посматра amd64 архитектура и System V ABI конвенција?
- rsi
- rdi
- rbx
- r11
- rbp
- r8
- r9
- r10
- r13
- rdx
- r12
- rax
- rcx
4. задатак
Посматра се програм описан садржајем дела меморије и сегментом изворног C кода.
Иницијални садржај дела меморије (дат у "школском" формату приказаном на аудиторним вежбама):
| Адреса | +7 | +6 | +5 | +4 | +3 | +2 | +1 | +0 |
|---|---|---|---|---|---|---|---|---|
| 0x400050006000 + 0x20 | 0x00 | 0x00 | 0xFF | 0xFF | 0xEE | 0xEE | 0xDD | 0xDD |
| 0x400050006000 + 0x18 | 0x00 | 0x00 | 0x40 | 0x00 | 0x50 | 0x00 | 0x60 | 0x0A |
| 0x400050006000 + 0x10 | 0xCC | 0xCC | 0xBB | 0xBB | 0xAA | 0xAA | 0x99 | 0x99 |
| 0x400050006000 + 0x08 | 0x88 | 0x88 | 0x77 | 0x77 | 0x66 | 0x66 | 0x55 | 0x55 |
| 0x400050006000 + 0x00 | 0x44 | 0x44 | 0x33 | 0x33 | 0x22 | 0x22 | 0x11 | 0x11 |
Сегмент изворног C кода:
#include <stdio.h>
#include <stdint.h>
extern uint64_t a;
extern uint8_t *b;
void main()
{
printf("%#lx", a);
printf("%p", &a);
printf("%#x", *((uint16_t *)a + 2));
printf("%#x", *((uint16_t *)a + 4));
printf("%p", b);
printf("%p", &b);
printf("%#x", *(b + 2));
printf("%#x", *(b + 4));
}
Допуните следеће констатације уколико се посматра amd64 архитектура и System V ABI конвенција, а симболи a и b имају исту вредност 0x400050006018:
- Наредба
printf("%lx", a);исписује 0x40005000600A. - Наредба
printf("%p", &a);исписује 0x400050006018. - Наредба
printf("%#x", *((uint16_t *)a + 2));исписује 0x8888. - Наредба
printf("%#x", *((uint16_t *)a + 4));исписује 0xAAAA. - Наредба
printf("%p", b);исписује 0x40005000600A. - Наредба
printf("%p", &b);исписује 0x400050006018. - Наредба
printf("%#x", *(b + 2));исписује 0x77. - Наредба
printf("%#x", *(b + 4));исписује 0x88.
Напомене:
- Уколико неку вредност није могуће одредити на основу датог садржаја дела меморије као одговор треба унети знак питања (?)
- Све одговоре за успешно одређене вредности треба унети у истом формату каквом их програм исписује.
- Формат "%p" служи за испис вредности показивача у хексадецималном формату са префиксом 0x (након префикса не исписују се водеће нуле).
- Формат "%#x" служи за испис неозначеног целог броја у хексадецималном формату са префиксом 0x (након префикса не исписују се водеће нуле).
5. задатак
У наставку је дата декларација функције foo и дефиниције пратећих типова података:
typedef struct
{
long fA1;
long fA2;
long fA3;
} StructTypeA;
extern StructTypeA foo(
StructTypeA param0,
StructTypeA param1,
double * param2,
float * param3,
double * param4
);
Допунити следеће констатације уколико се посматра amd64 архитектура и System V ABI конвенција:
- Повратна вредност функције foo прослеђује се као меморијски простор алоциран од стране позиваоца назад до позиваоца.
- Параметар
param0прослеђује се као stackPushII у функцијуfooприликом њеног позива. - Параметар
param1прослеђује се као stackPushI у функцијуfooприликом њеног позива. - Параметар
param2прослеђује се као rsi у функцијуfooприликом њеног позива. - Параметар
param3прослеђује се као rdx у функцијуfooприликом њеног позива. - Параметар
param4прослеђује се као rcx у функцијуfooприликом њеног позива.
Напомене:
- Одговор комбинација GP представља одређену комбинацију (више од једног) искључиво General Purpose регистара.
- Одговор комбинација SSE представља одређену комбинацију (више од једног) искључиво Streaming SIMD Extension регистара.
- Одговор комбинација GP/SSE представља одређену комбинацију (више од једног) General Purpose и Streaming SIMD Extension регистара.
- Одговор stackPush<roman-numeral>, где је <roman-numeral> римски број, представља аргумент који се прослеђује преко стека при чему римски број означава међусобни поредак push операција односно редослед стављања датог аргумента на врх стека у односу на друге аргументе који се такође прослеђују преко стека.