对于 x86 汇编和优化代码中的循环?
For loop in x86 assembly and optimising code?
我目前正在学习汇编编程,这是我大学模块之一。我有一个用 C++ 编写的带有内联 x86 程序集的程序,它采用 6 个字符的字符串并根据加密密钥对它们进行加密。
完整程序如下:https://gist.github.com/anonymous/1bb0c3be77566d9b791d
我的 encrypt_chars
函数代码:
void encrypt_chars (int length, char EKey)
{ char temp_char; // char temporary store
for (int i = 0; i < length; i++) // encrypt characters one at a time
{
temp_char = OChars [i]; // temp_char now contains the address values of the individual character
__asm
{
push eax // Save values contained within register to stack
push ecx
movzx ecx, temp_char
push ecx // Push argument #2
lea eax, EKey
push eax // Push argument #1
call encrypt
add esp, 8 // Clean parameters of stack
mov temp_char, al // Move the temp character into a register
pop ecx
pop eax
}
EChars [i] = temp_char; // Store encrypted char in the encrypted chars array
}
return;
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted (in the low 8-bit field, CL).
// Output: register EAX = the encrypted value of the source character (in the low 8-bit field, AL).
__asm
{
encrypt:
push ebp // Set stack
mov ebp, esp // Set up the base pointer
mov eax, [ebp + 8] // Move value of parameter 1 into EAX
mov ecx, [ebp + 12] // Move value of parameter 2 into ECX
push edi // Used for string and memory array copying
push ecx // Loop counter for pushing character onto stack
not byte ptr[eax] // Negation
add byte ptr[eax], 0x04 // Adds hex 4 to EKey
movzx edi, byte ptr[eax] // Moves value of EKey into EDI using zeroes
pop eax // Pop the character value from stack
xor eax, edi // XOR character to give encrypted value of source
pop edi // Pop original address of EDI from the stack
rol al, 1 // Rotates the encrypted value of source by 1 bit (left)
rol al, 1 // Rotates the encrypted value of source by 1 bit (left) again
add al, 0x04 // Adds hex 4 to encrypted value of source
mov esp, ebp // Deallocate values
pop ebp // Restore the base pointer
ret
}
//--- End of Assembly code
}
我的问题是:
- 将此
for loop
转换为程序集的最佳/最有效方法是什么?
- 有没有办法删除对
encrypt
的调用并将代码直接放在它的位置?
- 我如何 optimise/minimise 使用寄存器和指令来使代码更小并可能更快?
- 有没有办法将
OChars
和 EChars
数组转换为汇编?
如果可能的话,您能否向我解释一下该解决方案的工作原理,因为我很想学习。
我建议查看由编译器生成的汇编代码。您可以稍后更改和优化它。
How do you get assembler output from C/C++ source in gcc?
我无法帮助优化或密码学,但我可以向您展示一种制作循环的方法,如果您查看此函数中的循环:
void f()
{
int a, b ;
for(a = 10, b = 1; a != 0; --a)
{
b = b << 2 ;
}
}
循环本质上是:
for(/*initialize*/; /*condition*/; /*modify*/)
{
// run code
}
所以汇编中的函数看起来是这样的:
_f:
push ebp
mov ebp, esp
sub esp, 8 ; int a,b
initialize: ; for
mov dword ptr [ebp-4], 10 ; a = 10,
mov dword ptr [ebp-8], 1 ; b = 1
mov eax, [ebp-4]
condition:
test eax, eax ; tests if a == 0
je exit
runCode:
mov eax, [ebp-8]
shl eax, 2 ; b = b << 2
mov dword ptr [ebp-8], eax
modify:
mov eax, [ebp-4]
sub eax, 1 ; --a
mov dword ptr [ebp-4], eax
jmp condition
exit:
mov esp, ebp
pop ebp
ret
此外,我在源代码中展示了如何创建局部变量;
- 从堆栈指针中减去space。
- 并通过基指针访问它们。
我尽量将源代码设为通用的英特尔 x86 汇编语法,所以如果您的特定环境需要更改任何内容,我深表歉意,我的目的是给出一个关于如何在汇编中构建循环然后给出的总体思路你可以复制、粘贴和 运行.
我目前正在学习汇编编程,这是我大学模块之一。我有一个用 C++ 编写的带有内联 x86 程序集的程序,它采用 6 个字符的字符串并根据加密密钥对它们进行加密。
完整程序如下:https://gist.github.com/anonymous/1bb0c3be77566d9b791d
我的 encrypt_chars
函数代码:
void encrypt_chars (int length, char EKey)
{ char temp_char; // char temporary store
for (int i = 0; i < length; i++) // encrypt characters one at a time
{
temp_char = OChars [i]; // temp_char now contains the address values of the individual character
__asm
{
push eax // Save values contained within register to stack
push ecx
movzx ecx, temp_char
push ecx // Push argument #2
lea eax, EKey
push eax // Push argument #1
call encrypt
add esp, 8 // Clean parameters of stack
mov temp_char, al // Move the temp character into a register
pop ecx
pop eax
}
EChars [i] = temp_char; // Store encrypted char in the encrypted chars array
}
return;
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted (in the low 8-bit field, CL).
// Output: register EAX = the encrypted value of the source character (in the low 8-bit field, AL).
__asm
{
encrypt:
push ebp // Set stack
mov ebp, esp // Set up the base pointer
mov eax, [ebp + 8] // Move value of parameter 1 into EAX
mov ecx, [ebp + 12] // Move value of parameter 2 into ECX
push edi // Used for string and memory array copying
push ecx // Loop counter for pushing character onto stack
not byte ptr[eax] // Negation
add byte ptr[eax], 0x04 // Adds hex 4 to EKey
movzx edi, byte ptr[eax] // Moves value of EKey into EDI using zeroes
pop eax // Pop the character value from stack
xor eax, edi // XOR character to give encrypted value of source
pop edi // Pop original address of EDI from the stack
rol al, 1 // Rotates the encrypted value of source by 1 bit (left)
rol al, 1 // Rotates the encrypted value of source by 1 bit (left) again
add al, 0x04 // Adds hex 4 to encrypted value of source
mov esp, ebp // Deallocate values
pop ebp // Restore the base pointer
ret
}
//--- End of Assembly code
}
我的问题是:
- 将此
for loop
转换为程序集的最佳/最有效方法是什么? - 有没有办法删除对
encrypt
的调用并将代码直接放在它的位置? - 我如何 optimise/minimise 使用寄存器和指令来使代码更小并可能更快?
- 有没有办法将
OChars
和EChars
数组转换为汇编?
如果可能的话,您能否向我解释一下该解决方案的工作原理,因为我很想学习。
我建议查看由编译器生成的汇编代码。您可以稍后更改和优化它。
How do you get assembler output from C/C++ source in gcc?
我无法帮助优化或密码学,但我可以向您展示一种制作循环的方法,如果您查看此函数中的循环:
void f()
{
int a, b ;
for(a = 10, b = 1; a != 0; --a)
{
b = b << 2 ;
}
}
循环本质上是:
for(/*initialize*/; /*condition*/; /*modify*/)
{
// run code
}
所以汇编中的函数看起来是这样的:
_f:
push ebp
mov ebp, esp
sub esp, 8 ; int a,b
initialize: ; for
mov dword ptr [ebp-4], 10 ; a = 10,
mov dword ptr [ebp-8], 1 ; b = 1
mov eax, [ebp-4]
condition:
test eax, eax ; tests if a == 0
je exit
runCode:
mov eax, [ebp-8]
shl eax, 2 ; b = b << 2
mov dword ptr [ebp-8], eax
modify:
mov eax, [ebp-4]
sub eax, 1 ; --a
mov dword ptr [ebp-4], eax
jmp condition
exit:
mov esp, ebp
pop ebp
ret
此外,我在源代码中展示了如何创建局部变量;
- 从堆栈指针中减去space。
- 并通过基指针访问它们。
我尽量将源代码设为通用的英特尔 x86 汇编语法,所以如果您的特定环境需要更改任何内容,我深表歉意,我的目的是给出一个关于如何在汇编中构建循环然后给出的总体思路你可以复制、粘贴和 运行.