英文:
XOR in assembly language linked with C++
问题
The problem is related to the function of encrypting a string with a gamma sequence.
Function call:
cout << "\ncipher with code: ";
for (register int i = 0; i < str.length(); i++) {
str[i] = fun_cipher_gamma(str[i], gamma[i]);
cout << str[i];
}
cout << endl;
The function itself:
char fun_cipher_gamma(register char symbol, register char gamma)
{
char result = ' ';
funct();
return result;
}
Assembly code:
.686
.MODEL FLAT, C
.STACK 256
.DATA
.CODE
EXTRN gamma : BYTE
EXTRN symbol : BYTE
EXTRN result : BYTE
PUBLIC funct
funct PROC far
mov al, symbol
mov bl, gamma
xor al, bl
mov result, al
retn
funct ENDP
END
Using the debugger, I realized that the assembly language function doesn't return a result, but how to fix it I don't understand. I assume I need to use push
, but I'm not sure, and I'm lost since my assembly language skills are almost non-existent.
This function worked successfully in C++, and I need to redo its logic in assembly language:
return btowc(symbol) ^ btowc(gamma);
UPD: In .cpp, I've added these externs:
extern "C" char funct(void);
extern "C" unsigned char gamma = ' ';
extern "C" unsigned char symbol = ' ';
extern "C" unsigned char result = ' ';
英文:
The problem is related to the function of encrypting a string with a gamma sequence.
Function call:
cout << "\ncipher with code: ";
for (register int i = 0; i < str.length(); i++) {
str[i] = fun_cipher_gamma(str[i], gamma[i]);
cout << str[i];
}
cout << endl;
The function itself:
char fun_cipher_gamma(register char simbol, register char gamma)
{
char result = ' ';
funct();
return result;
}
Assembly code:
.MODEL FLAT, C
.STACK 256
.DATA
.CODE
EXTRN gamma : BYTE
EXTRN simbol : BYTE
EXTRN result : BYTE
PUBLIC funct
funct PROC far
mov al, simbol
mov bl, gamma
xor al, bl
mov result, al
retn
funct ENDP
END
Using the debugger I realized that the assembly language function doesn't return result, but how to fix it I don't understand.
I assume I need to use push
, but I'm not sure and I'm lost, since my assembly language skills are almost non-existent
This function worked successfully in C++, and I need to redo its logic in assembly language:
return btowc(simbol) ^ btowc(gamma);
UPD: In .cpp I`ve added these externs:
extern "C" char funct(void);
extern "C" unsigned char gamma = ' ';
extern "C" unsigned char simbol = ' ';
extern "C" unsigned char result = ' ';
答案1
得分: 6
As @Chris Dodd mentioned, you aren't using the global variables in the assembly!
And it's better to use a calling convention instead of using global variables as parameters. It improves readability and makes it easier to understand.
extern "C" char funct(unsigned char symbol, unsigned char gamma);
char fun_cipher_gamma(unsigned char symbol, unsigned char gamma)
{
return funct(symbol, gamma);
}
; 在 C 调用约定中:
; 调用者通过堆栈传递参数,所有参数都被推送到堆栈上作为双字(4 字节)
; 被调用者应该保留 EBX、ESI、EDI、EBP 和 ESP,并使用 EAX 返回值
push ebp ; 被调用者应该保留旧的 EBP 值
mov ebp, esp ; 设置基指针为堆栈指针
; sub esp, 8 ; 为 8 字节的变量腾出空间(被注释掉,因为我们没有使用它)
; 在这里推送你将要使用的其他寄存器
; ...
; [ebp - 12] = 局部变量 #3
; [ebp - 8] = 局部变量 #2
; [ebp - 4] = 局部变量 #1
; [ebp + 0] = 我们推送的旧 EBP
; [ebp + 4] = 返回地址
; [ebp + 8] = 参数 #1
; [ebp + 12] = 参数 #2
; [ebp + 16] = 参数 #3
; [ebp + 20] = 参数 #4
; ...
; 所以这意味着 "symbol" 在 [ebp + 8],gamma 在 [ebp + 12]
; [ebp + 8] = symbol
; [ebp + 12] = gamma
mov eax, [ebp + 8]
xor eax, [ebp + 12]
; 在这里弹出保存的寄存器
mov esp, ebp ; 恢复 ESP 到其原始值
pop ebp ; 恢复 EBP 的值
ret
但请注意,如今使用汇编语言不会提高程序的性能(事实上,性能可能会下降),编译器能够比我们写得更快的汇编语言。
如果编译器没有进行优化,可能有可能编写比编译器更快的汇编语言,但一旦启用优化,编译器将比你写得更快。
MSVC19 编译了这个:
char funct(unsigned char symbol, unsigned char gamma) {
return symbol^gamma;
}
生成了这个:
xor cl, dl
mov al, cl
ret 0
这个实现占用的空间更少,而且比我们的实现更快(它使用了 fastcall
调用约定)。
有关调用约定的更多信息,请参阅:https://www.dyncall.org/docs/manual/manualse11.html
英文:
As @Chris Dodd mentioned, you aren't using the global variables in the assembly!
And it's better to use a calling convention instead of using global variables as parameter. It improves readability and makes it easier to understand.
extern "C" char funct(unsigned char symbol, unsigned char gamma);
char fun_cipher_gamma(unsigned char symbol, unsigned char gamma)
{
return funct(symbol, gamma);
}
; in C calling convention:
; Caller passes Parameters via stack and all arguments are pushed to stack as dwords (4 byte)
; Callee should preserve EBX, ESI, EDI, EBP, and ESP
; and use EAX to return a value
push ebp ; Callee should preserver old value of EBP
mov ebp, esp ; set the base pointer to stack pointer
; sub esp, 8 ; make room for 8 byte of variables (commented out because we aren't using it)
; push any other registers that you'll use HERE
; ...
; [ebp - 12] = local variable #3
; [ebp - 8] = local variable #2
; [ebp - 4] = local variable #1
; [ebp + 0] = old EBP the we pushed
; [ebp + 4] = return address
; [ebp + 8] = parameter #1
; [ebp + 12] = parameter #2
; [ebp + 16] = parameter #3
; [ebp + 20] = parameter #4
; ...
; so this means "symbol" is at [ebp + 8] and gamma is at [ebp + 12]
; [ebp + 8] = symbol
; [ebp + 12] = gamma
mov eax, [ebp + 8]
xor eax, [ebp + 12]
; pop saved registers HERE
mov esp, ebp ; restore ESP to its original value
pop ebp ; restore EBP's value
ret
But please note that nowadays using assembly won't improve your program's performance (in fact you may lose performance), compilers write faster assembly than we.
It may be possible to write faster assembly than compiler if they aren't optimizing but as soon as you enable optimizing they'll write faster assembly than you.
MSVC19 compiled this:
char funct(unsigned char symbol, unsigned char gamma) {
return symbol^gamma;
}
to this:
xor cl, dl
mov al, cl
ret 0
which uses less space while being faster than our implementation (it's using fastcall
calling convention).
For more info about calling conventions: https://www.dyncall.org/docs/manual/manualse11.html
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论