【问题标题】:Hex Character bit rotation [duplicate]十六进制字符位旋转[重复]
【发布时间】:2021-06-27 05:16:07
【问题描述】:

我编写了以下要在 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() 函数获取 0110 等 4 位输入,并将 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 $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函数表面上很好,但是我的代码给出了分段错误。我不知道在这种情况下该怎么做,因此感谢您的帮助。

【问题讨论】:

  • 我不太习惯汇编语言,但这看起来很奇怪:pushq %rbp movq %rsp,%rbp。如果我是正确的,这会将 RBP 保存到堆栈中,但使用 RBP 擦除堆栈指针。不应该是movq %rbp, %rsp吗?
  • 超级常见的FAQ:使用int作为getchar的结果。 fflush(stdin) 是未定义的行为。您似乎需要其他学习 C 的资源,因为您当前的资源教错了。
  • 您是否在调试器中运行您的程序?它会将您指向错误访问的位置。 -- 你有单独检查你的汇编函数吗?
  • 我对几天前自己开始的 x86-64 Att 组装了解不多。
  • 每当我尝试单独编译它们时,我都会收到两个旋转函数的错误消息:

标签: c assembly x86-64 att


【解决方案1】:

这里不需要对堆栈做任何事情。从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

现在这是 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

【讨论】:

  • 我确实做到了,代码确实运行了,但我的输出是:c0 30
  • 你的操作系统是什么?
  • 我有 Windows 10 操作系统
  • 我要问一下,我的create_key()函数有同样的问题吗?
  • 对于 Win32,调用约定不同 - 第一个函数参数在 rcx 中传递,而不是在 rdi 中传递。有关详细信息,请参阅here。关于 create_key() - 目前还不清楚它应该做什么,所以不能就此提出建议。我确实看到它覆盖了rdi,但在 Win32 上必须保留 rdi
猜你喜欢
  • 2021-03-27
  • 2016-12-27
  • 2011-05-15
  • 2017-03-09
  • 2012-11-07
  • 2019-01-17
  • 1970-01-01
  • 2017-04-05
  • 2018-07-03
相关资源
最近更新 更多