assembly 汇编语言中与C++连接的异或运算

n6lpvg4x  于 2023-05-13  发布在  其他
关注(0)|答案(1)|浏览(174)

这个问题与用伽马序列加密字符串的功能有关。
函数调用:

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;

函数本身:

char fun_cipher_gamma(register char simbol, register char gamma)
{
    char result = ' ';
    funct();
    return result;
}

装配代码:

.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

使用调试器我意识到汇编语言函数不返回结果,但如何修复它我不明白。
我假设我需要使用push,但我不确定,我迷路了,因为我的汇编语言技能几乎不存在
这个函数在C++中运行得很成功,我需要用汇编语言重新编写它的逻辑:

return btowc(simbol) ^ btowc(gamma);

UPD:在.cpp中,我添加了这些externs:

extern "C" char funct(void);
extern "C" unsigned char gamma = ' ';
extern "C" unsigned char simbol = ' ';
extern "C" unsigned char result = ' ';
dluptydi

dluptydi1#

正如@Chris Dodd提到的,你没有在程序集中使用全局变量!
最好使用调用约定,而不是使用全局变量作为参数。它提高了可读性,使其更容易理解。

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

但是请注意,现在使用汇编不会提高程序的性能(事实上你可能会失去性能),编译器编写汇编比我们更快。
如果编译器没有进行优化,那么编写汇编程序的速度可能会比编译器快,但是一旦启用优化,它们编写汇编程序的速度就会比你快。
MSVC 19编译了这个:

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

相关问题