Системски софтвер/К1 Јул 1 2025

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

Први колоквијум у року јул 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 конвенција? Изаберите један или више одговора:

  1. Функција foo морала је да алоцира више простора на стеку него што јој је суштински потребно ради обезбеђивања поравнања за локални подаци.
  2. Функција foo морала је да алоцира више простора на стеку него што јој је суштински потребно ради очувања гарантованог поравнања области за аргументе позиваних функција.
  3. Простор који користи на стеку функција foo мора првобитно да алоцира због постојања "црвене зоне".
  4. Величина простора на стеку, који алоцира функција foo, једнака је збиру величина података смештених на стек.
  5. Простор који користи на стеку функција 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 конвенција:

  1. Повратна вредност функције foo прослеђује се као меморијски простор алоциран од стране позиваоца назад до позиваоца.
  2. Параметар param0 прослеђује се као stackPushII у функцију foo приликом њеног позива.
  3. Параметар param1 прослеђује се као stackPushI у функцију foo приликом њеног позива.
  4. Параметар param2 прослеђује се као rsi у функцију foo приликом њеног позива.
  5. Параметар param3 прослеђује се као rdx у функцију foo приликом њеног позива.
  6. Параметар param4 прослеђује се као rcx у функцију foo приликом њеног позива.

Напомене:

  • Одговор комбинација GP представља одређену комбинацију (више од једног) искључиво General Purpose регистара.
  • Одговор комбинација SSE представља одређену комбинацију (више од једног) искључиво Streaming SIMD Extension регистара.
  • Одговор комбинација GP/SSE представља одређену комбинацију (више од једног) General Purpose и Streaming SIMD Extension регистара.
  • Одговор stackPush<roman-numeral>, где је <roman-numeral> римски број, представља аргумент који се прослеђује преко стека при чему римски број означава међусобни поредак push операција односно редослед стављања датог аргумента на врх стека у односу на друге аргументе који се такође прослеђују преко стека.

Напомене