十六进制字符位旋转

Hex Character bit rotation

我编写了以下要在 C 程序中调用的 x86-64 函数: 第一个接受 2 位十六进制字符并将其位向右旋转一位,即,如果“12”(表示 0x12 但 0x 未作为输入提供)向右旋转一位以提供“09” (0x09)

.file "rotate_right.s"
.section .rodata
.data
.globl rotate_right
.type   rotate_right, @function
.text
rotate_right:
pushq %rbp
movq %rsp,%rbp

pushq %rsi
pushq %rdi
pushq %rbx

subl , %esp
movb 8(%ebp), %al
sarb , %al

leave
ret
.size rotate_right, .-rotate_right

同样,此函数将位向左旋转一位,因此'12'(0x12) 变为'24'(0x24)。

.file "rotate_left.s"
.section .rodata
.data
.globl rotate_left
.type   rotate_left, @function
.text
rotate_left:
pushq %rbp
movq %rsp,%rbp

pushq %rsi
pushq %rdi
pushq %rbx

subl , %esp
movb 8(%ebp), %al
sarb , %al

leave
ret
.size rotate_left, .-rotate_left

create_key() 函数获取一个四位输入,如 0110,并输出一个 8 位输出作为无符号整数,即 01100110:

.file "create_key.s"
.section .rodata
ask_key:
.string "Enter 4-bit key:"
.data
.globl create_key
.type   create_key, @function
.text
create_key:
pushq %rbp
# stack holding
movq %rsp, %rbp
movl $ask_key, %edi
# printing the ask string
movl [=12=], %eax
# calling the C functions

call printf
movl [=12=],%esi
# rsi is set to 0. the key
pushq %rsi
# take it to the stack

# call getchar for getting each key bit
call getchar
popq %rsi
subl ,%eax
# doing this will give us 1 or 0 if the we input 1 or 0
sall ,%esi
# shift the key by one bit
orl %eax,%esi
# OR key and the sigle input
pushq %rsi
# push rsi to stack to save the value in rsi

# Do the above operation a total of 4 times
call getchar
popq %rsi
subl ,%eax
sall ,%esi
orl %eax,%esi
pushq %rsi

call getchar
popq %rsi
subl ,%eax
sall ,%esi
orl %eax,%esi
pushq %rsi

call getchar
popq %rsi
subl ,%eax
sall ,%esi
orl %eax,%esi

# copy first 4-bits of the key into %rax
movl %esi,%eax
#left shift the key 4 times
sall ,%esi
# OR the secont 4-bits into %rax
orl %esi,%eax
leave
ret
# return the values and end the function
.size create_key, .-create_key

这是C程序,

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>

extern unsigned int create_key();
extern unsigned char rotate_left(unsigned char x);
extern unsigned char rotate_right(unsigned char x);

int main(){
/* This Part Takes The Input To Be Ciphered 
    And Prints The Hexadecimal Value*/
    
char word[200], outword[400], xor_hex[400], hex_rot[400], ch, hex[2];
unsigned int i_key, encodant, rotated;
int i, len, j;
/* i_key is the integer equvivalent of the cipher key*/

printf("enter cleartext:");

i = 0;
ch = getchar();
while(ch!='\n'){
    word[i] = ch;
    ++i;
    ch = getchar();
}
fflush(stdin);
len = i;
word[i] = '[=13=]';
printf("%s\n", word);
printf("hex encoding:\n");
for(i = 0; i<len; i++){
    sprintf(outword+(i*2), "%02X", word[i]);
}
for(i=0;i<(2*len);i++){
    if(i%2==0 & i>0)printf(" ");
    if(i%20==0 & i>0)printf("\n");
    printf("%c", outword[i]);
}
printf("\n");

/* This Part Asks For The Cipher Key */
i_key =  create_key();

/* XOR Encoding of the Hex Cyphertext*/
for(i=0;i<len*2;i+=2){
    hex[0] = outword[i];
    hex[1] = outword[i+1];
    encodant = (int)strtol(hex, NULL, 16);
    sprintf(xor_hex+(i), "%02X", (i_key^encodant));
}

/* Encoding the text using bit rotation */
j=1;
for(i=0;i<len*2;i+=2){
    hex[0]=xor_hex[i];
    hex[1]=xor_hex[i+1];
    encodant = (int)strtol(hex, NULL, 16);
    if(j%2==0)rotated = rotate_right(encodant);
    else rotated = rotate_left(encodant);
    j++;
    sprintf(hex_rot+(i), "%02X", rotated);
}

/* Printing The Finished Ciphered Text */
printf("hex ciphertext:\n");
for(i=0;i<(2*len);i++){
    if(i%2==0 & i>0)printf(" ");
    if(i%20==0 & i>0)printf("\n");
    printf("%c", hex_rot[i]);
}
printf("\n");

return 0;
}

不能更改函数原型,即旋转函数必须是 char 并且具有 char 参数,create_key 函数看起来不错,但我的代码给出了分段错误。我不知道在这种情况下该怎么做,所以感谢您的帮助。

这里不需要对栈做任何操作。从 rdi (SysV) 或 rcx (Win32) 中获取参数,将其放入 al,旋转并 return:

    .file "rotate.S"

    .text

    .globl rotate_right
rotate_right:
    mov %rdi, %rax
    shrb , %al
    ret

    .globl rotate_left
rotate_left:
    mov %rdi, %rax
    shlb , %al
    ret

    .end

现在是 GNU as 语法,可能需要针对 AT&T asm 进行一些调整。

测试一下:

#include <stdio.h>

unsigned char rotate_left(unsigned char);
unsigned char rotate_right(unsigned char);

int main() {
    printf("%02x %02x\n", rotate_left(0x12), rotate_right(0x12));
    return 0;
}

打印:

24 09