气体组件x86。将char转换为二进制字符串

时间:2016-03-16 18:03:27

标签: c assembly x86

我是装配新手,我也在努力了解我所掌握的工具。我必须为一个小C程序创建一个可调用的汇编函数。目标是让用户输入字母十六进制值-so 41表示A.然后C将此十六进制值作为unsigned char传递给汇编函数。以下是C代码

extern char *printbin(unsigned char);

int main(void)
{
  unsigned int x;

  printf("enter the character's ascii value in hex: \n");
  scanf("%x",&x);
  printf("The binary format for character %c is %s\n", 
                                 x,   printbin((unsigned char)x));
  return 0;
}

我的理解是在堆栈中应该存储一个字节中存储的值41,因为在C字符中实际上只是数字。这个假设是否正确。任务是将输入转换为两个4位二进制数的输出字符串,每个数字用空格分隔,因此0100 0001我的第一个问题是如何将寄存器中的字节分成4位或仅1或4?我为汇编文件

设置了一个框架
.text
.globl _printbin

_printbin:

        pushl %ebp
        movl %esp, %ebp

        movl 4(%ebp), %ecx  #store the char in ecx register
        jmp end

donibble: #function to convert digit to binary

end:
        movl %ebp, %esp
        popl %ebp
        ret

然而,我对如何继续抓取字节的一半感到迷茫。当我对它“工作”时,我只能用%el抓住一个字节来使它只有8位而不是%ecx但是我不知道任何类型的寄存器只能抓取1个字节。任何帮助或想法将不胜感激。

更新了汇编代码

.text
.globl _printbin

_printbin:

        pushl %ebp
        movl %esp, %ebp

        movl 4(%ebp), %edx #grabs the hex byte
        movl $0, %eax   #sets $eax to 0

        shrb $4,%dl
        jmp donibble
        L2:
                incl %eax
        #       addl 0x20, %return string #add the space.
                movl 4(%ebp), %edx
                AND %dl, 0x0f 
                jmp donibble    
        L3:
                jmp end

donibble:
#Takes %dl and gets string and adds string to return String
        cmpb %dl, 0x0
        je Zero
        cmpb %dl, 0x1
        je One

Zero:
         #add 0000 to string
 jmp donibbleEnd
One: 
        #add 0001 to string

        donibbleEnd:
        #to send back to printbin
                cmpb $0, %eax
                je L2
                jmp L3


end:
        movl $returnString, %eax
        movl %ebp, %esp
        popl %ebp
        ret

.data

returnString:
        .asciz "1001 1100\n"

.end

有没有办法在上面这个更新的结构后添加到我的$ returnString?显然addl“0000”,$ returnString根本不起作用:)

2 个答案:

答案 0 :(得分:1)

这是该功能的一个奇怪的原型。你应该返回一个指向静态缓冲区的指针吗?更典型的设计是调用者将指针传递给缓冲区,函数可以存储该字符串。

通常的做法是利用移位指令将CF设置为最后一位移出的事实。然后,您可以使用setc获取零或一,并将其​​转换为ascii '0''1'。另一个技巧是adc $0adc $'0'来读取进位标志。

复制寄存器并使用and来获得低位也是可行的。

如果您遇到困难,请使用搜索功能。以前有过关于此的SO问题。尝试在和/或标记内进行搜索。查看x86标签wiki,了解许多与初学者和参考资料的良好链接。

答案 1 :(得分:0)

要记录关闭这个。这是我结束的代码。我感谢大家的帮助。

.text
.globl _printbin

_printbin:

    pushl %ebp
    movl %esp, %ebp

    movb 8(%ebp), %dl #grabs the hex byte
    movl $0, %eax   #sets $eax to 0

    shrb $4, %dl
    movl $returnString, %ecx
    pushl %ebx #free up ebx
    jmp donibble

returnFromDonibble:
    incl %ecx
    movb 8(%ebp), %dl
    movb $0x0f, %al
    andb $15, %dl
    movb $0x39, %al
    cmpb (%ecx), %al
    je donibble
    jne end




donibble:
#Takes %dl and gets string and adds string to return String
    movb %dl, %bl
    movb $0x08, %al
    andb $8,%dl
    je zero
    jne one

    one:
        movb $0x31, (%ecx)
        incl %ecx
        jmp L2
    zero:
        movb $0x30, (%ecx)
        incl %ecx
        jmp L2
L2:
    movb %bl, %dl
    movb $0x04, %al 
    andb $4, %dl
    je zero2
    jne one2

    one2:
        movb $0x31, (%ecx)
        incl %ecx
        jmp L3
    zero2:
        movb $0x30, (%ecx)
        incl %ecx
        jmp L3

L3:
    movb %bl, %dl
    movb $0x02, %al
    andb $2, %dl
    je zero3
    jne one3

    one3:
        movb $0x31, (%ecx)
        incl %ecx
        jmp L4
    zero3:
        movb $0x30, (%ecx)
        incl %ecx
        jmp L4

L4:
    movb %bl, %dl
    movb $0x01, %al
    andb $1, %dl
    je zero4
    jne one4

    one4:
        movb $0x31, (%ecx)
        incl %ecx
        jmp returnFromDonibble
    zero4:
        movb $0x30, (%ecx)
        inc %ecx
        jmp returnFromDonibble

end:
    popl %ebx
    movl $returnString, %eax
    movl %ebp, %esp
    popl %ebp
    ret




.data

returnString:   .asciz "9999 9999"

.end