Search code examples
assemblyx86att

Pack bitfields into 32 bit register using x86 assembly


I am working with RNS in assembler x86 AT&T at the moment. I have to put 5 remainders into one register, %eax. Piece of code:

.macro division number
        mov $0, %ecx

    loop_getremainders:
        mov $0, %edx
        mov number, %eax
        mov dividers(,%ecx,4), %ebx
        div %ebx
        mov %edx, remainders(,%ecx,4)
        inc %ecx
        cmp $5, %ecx
        jne loop_getremainders
        int $0x80
.endm

.section .data
     number: .long 158    
     remainders: .long 0,0,0,0,0
     dividers: .long 7,15,31,127,8192

.section .text
    .global _start
    _start:
        division number
        mov $1, %eax
        mov $0, %ebx
        int $0x80

I know that to write 7 in binary i need 3 bits, 15 - 4 bits etc. I want to write every remainder of them in one %eax, "linked" in this order: 111 1111 11111 1111111 1111111111111 (32bits,spaces for better presentation) How to change it from decimal to binary and put these 5 numbers into 1 32bit register?


Solution

  • Looks like the shrd instruction would be helpful in this case. To do it in a loop, you probably need to make a table that contains the shift amounts, since you seem to be needing 3, 4, 5, 7, 13. Something like this:

        xor %eax, %eax                          # accumulator
        movl $5, %edx                           # counter
    loop_shift:
        movb shifts(%edx), %cl                  # the shift amount
        movl remainders(, %edx, 4), %ebx        # next remainder
        shrd %cl, %ebx, %eax                    # shift in the bits
        subl $1, %edx
        jnc loop_shift
    .data
        shifts: .byte 3, 4, 5, 7, 13