Системски софтвер/ЛабП Јул 2020
Пређи на навигацију
Пређи на претрагу
- Овај рок није решен. Помозите 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