首页 > 解决方案 > 十六进制字符位旋转

问题描述

我编写了以下要在 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 $4, %esp
movb 8(%ebp), %al
sarb $1, %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 $4, %esp
movb 8(%ebp), %al
sarb $1, %al

leave
ret
.size rotate_left, .-rotate_left

create_key() 函数获取一个 4 位输入,如 0110,并输出一个 8 位输出为 unsigned int 即 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 $0, %eax
# calling the C functions

call printf
movl $0,%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 $48,%eax
# doing this will give us 1 or 0 if the we input 1 or 0
sall $1,%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 $48,%eax
sall $1,%esi
orl %eax,%esi
pushq %rsi

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

call getchar
popq %rsi
subl $48,%eax
sall $1,%esi
orl %eax,%esi

# copy first 4-bits of the key into %rax
movl %esi,%eax
#left shift the key 4 times
sall $4,%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] = '\0';
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;
}

函数原型不能更改,即rotate函数必须是char并且有char参数,create_key函数表面上很好,但是我的代码给出了分段错误。我不知道在这种情况下该怎么做,因此不胜感激。

标签: cassemblyx86-64att

解决方案


这里不需要对堆栈做任何事情。从rdi(SysV) 或rcx(Win32) 中取参数,放入al, 旋转并返回:

    .file "rotate.S"

    .text

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

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

    .end

现在这是 GNUas语法,它可能需要对 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

推荐阅读