XOR汇编语言与C++链接

huangapple go评论72阅读模式
英文:

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 &lt;&lt; &quot;\ncipher with code: &quot;;
    for (register int i = 0; i &lt; str.length(); i++) {
        str[i] = fun_cipher_gamma(str[i], gamma[i]);
        cout &lt;&lt; str[i];
    }
cout &lt;&lt; endl;

The function itself:

char fun_cipher_gamma(register char simbol, register char gamma)
{
    char result = &#39; &#39;;
    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 &quot;C&quot; char funct(void);
extern &quot;C&quot; unsigned char gamma = &#39; &#39;;
extern &quot;C&quot; unsigned char simbol = &#39; &#39;;
extern &quot;C&quot; unsigned char result = &#39; &#39;;

答案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 &quot;C&quot; 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&#39;t using it)

; push any other registers that you&#39;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 &quot;symbol&quot; 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&#39;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

huangapple
  • 本文由 发表于 2023年5月11日 09:50:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76223629.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定