Sistemski softver/LabP Jul 2020
Pređi na navigaciju
Pređi na pretragu
- Ovaj rok nije rešen. Pomozite SI Wiki tako što ćete ga rešiti.
Popravna lab vežba na RTI smeru iz Jula 2020. godine
1. zadatak
Postavka
Za dati kod u asembleru dati kako bi mogao izgledati C kod čijim je prevođenjen dobijen.
.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
Rešenje
// 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;
}
Objašnjenje:
.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