Системски софтвер/ЛабП Јул 2020

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу
Овај рок није решен. Помозите SI Wiki тако што ћете га решити.

Поправна лаб вежба на РТИ смеру из Јула 2020. године

1. задатак

Поставка

За дати код у асемблеру дати како би могао изгледати Ц код чијим је превођењен добијен.

.intel-syntax noprefix
.text
.global foo
.type foo, @function
foo:
    push rbp
    mov rbp, rsp
    mov DWORD PTR -36[rbp], edi
    mov DWORD PTR -32[rbp], 0
    mov eax, DWORD PTR -36[rbp]
    mov QWORD PTR -24[rbp], rax
    cmp DWORD PTR -36[rbp], 1
    jg label_1
    mov eax, DWORD PTR -36[rbp]
    mov QWORD PTR -24[rbp], rax
    jmp label_2
label_1:
    mov eax, DWORD PTR -36[rbp]
    sub eax, 1
    mov edi, eax
    call foo
    mov rcx, rdx
    mov rdx, rcx
    mov rbx, rdx
    mov eax, DWORD PTR -36[rbp]
    sub eax, 2
    mov edi, eax
    call foo
    mov rcx, rdx
    mov rdx, rcx
    mov rax, rdx
    add rax, rbx
    mov QWORD PTR -24[rbp], rax
label_2:
    mov rax, QWORD PTR -32[rbp]
    mov rdx, QWORD PTR -24[rbp]
    mov rcx, rax
    mov rbx, rdx
    mov eax, ecx
    pop rbp
    ret

Решење

// 0 0 0 0 int int int int (l1)
// int int int int 0 0 0 0 (lstruct.a and padding)
// long long long long long long long long (lstruct.b)

typedef struct
{
    int a;
    long b;
} A;

A foo(int a)
{
    int l1 = a;
    A lstruct = {0, (unsigned long)l1}; // lstruct.a is l2, lstruct.b is l3

    if (l1 > 1)
        lstruct.b = foo(l1 - 1).b + foo(l1 - 2).b;
    else
        lstruct.b = (unsigned long)l1;

    return lstruct;
}


Објашњење:

.intel-syntax noprefix
.text
.global foo
.type foo, @function
foo:
    push rbp
    mov rbp, rsp # sub rsp, 0x10 (three times); mov QWORD PTR -8[rbp], rbx (saves rbx to stack)
    mov DWORD PTR -36[rbp], edi # int l1 = rdi; (param1)
    mov DWORD PTR -32[rbp], 0 # int l2 = 0; (lstruct.a)
    mov eax, DWORD PTR -36[rbp] # eax = l1;
    mov QWORD PTR -24[rbp], rax # long (or pointer) l3 = (unsigned long) a; (lstruct.b)
    cmp DWORD PTR -36[rbp], 1 # l1 - 1
    jg label_1 # jumps if l1 - 1 > 0
    mov eax, DWORD PTR -36[rbp] # eax = l1;
    mov QWORD PTR -24[rbp], rax # l3 = (unsigned long) l1;
    jmp label_2
label_1: # then
    mov eax, DWORD PTR -36[rbp] # eax = l1;
    sub eax, 1 # eax = l1 - 1;
    mov edi, eax # foo: param1: l1 - 1;
    call foo # recursive call, returns two eightbytes using rax and rdx
    mov rcx, rdx # rcx = second eightbyte of foo's return (foo1_ret2)
    mov rdx, rcx # rdx = rcx (foo1_ret2)
    mov rbx, rdx # rbx = foo1_ret2 (rbx is callee saved, should be saved to stack)
    mov eax, DWORD PTR -36[rbp] # eax = l1;
    sub eax, 2 # eax = l1 - 2;
    mov edi, eax # foo: param1: l1 - 2;
    call foo # recursive call
    mov rcx, rdx # rcx = foo2_ret2
    mov rdx, rcx # rdx = rcx (foo2_ret2)
    mov rax, rdx # rax = foo2_ret2
    add rax, rbx # rax += rbx (rax = foo1_ret2 + foo2_ret2)
    mov QWORD PTR -24[rbp], rax # l3 = foo1_ret2 + foo2_ret2;
label_2:
    mov rax, QWORD PTR -32[rbp] # lower rax = l2, upper rax is undefined (struct padding)
    mov rdx, QWORD PTR -24[rbp] # rdx = l3 (second eightbyte of foo's return)
    mov rcx, rax # rcx = rax (l2 and padding)
    mov rbx, rdx # rbx = l3
    mov eax, ecx # eax = l2 (no padding) (first eightbyte of foo's return)
    pop rbp # 'mov rsp, rbp' before this line, or 'leave' instead; mov rbx, QWORD PTR -8[rbp] (restoring rbx)
    ret