factorial and loop have 8, respectively 9, bytes of instructions before the jump backwards. Maybe I'll have to redo them, in the worst case I have to do useless functionsmaster
format ms64 coff | |||||
section '.text' code readable executable | |||||
use64 | |||||
public _loop | |||||
_loop: | |||||
xor eax, eax | |||||
inc eax | |||||
mov rbx, rdx ; RDX is overwritten by mul | |||||
@again: | |||||
cmp rbx, 0 | |||||
je @loop_end | |||||
mul rcx | |||||
dec rbx | |||||
jmp @again | |||||
@loop_end: | |||||
ret | |||||
public _tail_recursion | |||||
_tail_recursion: | |||||
test ecx, ecx | |||||
je @is_0 | |||||
mov eax, ecx | |||||
dec ecx | |||||
@loop: | |||||
test ecx, ecx | |||||
jz @tr_end | |||||
mul ecx | |||||
dec ecx | |||||
jnz @loop | |||||
jmp @tr_end | |||||
@is_0: | |||||
mov eax, 1 | |||||
@tr_end: | |||||
ret |
#pragma once | |||||
extern "C" { | |||||
/** | |||||
* Raises @num @cnt times | |||||
* | |||||
* @param num | |||||
* @param cnt | |||||
*/ | |||||
uint32_t _loop(uint32_t num, uint32_t cnt); | |||||
/** | |||||
* Computes factorial | |||||
* | |||||
* @param x | |||||
*/ | |||||
uint32_t _tail_recursion(uint32_t x); | |||||
} |
</ItemDefinitionGroup> | </ItemDefinitionGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ClInclude Include="advanced_instructions.h" /> | <ClInclude Include="advanced_instructions.h" /> | ||||
<ClInclude Include="backwards.h" /> | |||||
<ClInclude Include="catch.hpp" /> | <ClInclude Include="catch.hpp" /> | ||||
<ClInclude Include="simple_tests.h" /> | <ClInclude Include="simple_tests.h" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<None Include="advanced_instructions.asm" /> | <None Include="advanced_instructions.asm" /> | ||||
<None Include="backwards.asm" /> | |||||
<None Include="README.md" /> | <None Include="README.md" /> | ||||
<None Include="simple_tests.asm" /> | <None Include="simple_tests.asm" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<Object Include="advanced_instructions.obj" /> | <Object Include="advanced_instructions.obj" /> | ||||
<Object Include="backwards.obj" /> | |||||
<Object Include="simple_tests.obj" /> | <Object Include="simple_tests.obj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
<ClInclude Include="advanced_instructions.h"> | <ClInclude Include="advanced_instructions.h"> | ||||
<Filter>Header Files</Filter> | <Filter>Header Files</Filter> | ||||
</ClInclude> | </ClInclude> | ||||
<ClInclude Include="backwards.h"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ClCompile Include="main.cpp"> | <ClCompile Include="main.cpp"> | ||||
<None Include="advanced_instructions.asm"> | <None Include="advanced_instructions.asm"> | ||||
<Filter>Source Files</Filter> | <Filter>Source Files</Filter> | ||||
</None> | </None> | ||||
<None Include="backwards.asm"> | |||||
<Filter>Source Files</Filter> | |||||
</None> | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<Object Include="simple_tests.obj" /> | <Object Include="simple_tests.obj" /> | ||||
<Object Include="advanced_instructions.obj" /> | <Object Include="advanced_instructions.obj" /> | ||||
<Object Include="backwards.obj" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | </Project> |
#include "catch.hpp" | #include "catch.hpp" | ||||
#include "simple_tests.h" | #include "simple_tests.h" | ||||
#include "advanced_instructions.h" | #include "advanced_instructions.h" | ||||
#include "backwards.h" | |||||
TEST_CASE("Simple functions work as expected, unhooked") { | TEST_CASE("Simple functions work as expected, unhooked") { | ||||
REQUIRE(_small() == 0); | REQUIRE(_small() == 0); | ||||
REQUIRE((result[1] - result[2]) < DBL_EPSILON); | REQUIRE((result[1] - result[2]) < DBL_EPSILON); | ||||
REQUIRE((result[2] - result[3]) < DBL_EPSILON); | REQUIRE((result[2] - result[3]) < DBL_EPSILON); | ||||
REQUIRE((result[0] - 3.) < DBL_EPSILON); | REQUIRE((result[0] - 3.) < DBL_EPSILON); | ||||
} | |||||
TEST_CASE("Loops & tail recursion work as expected, unhook") { | |||||
REQUIRE(_loop(2, 3) == 8); | |||||
REQUIRE(_loop(5, 3) == 125); | |||||
REQUIRE(_loop(5, 0) == 1); | |||||
REQUIRE(_loop(5, 1) == 5); | |||||
REQUIRE(_tail_recursion(0) == 1); | |||||
REQUIRE(_tail_recursion(1) == 1); | |||||
REQUIRE(_tail_recursion(2) == 2); | |||||
REQUIRE(_tail_recursion(5) == 120); | |||||
} | } |