0

[Link for output after decoding. ][1]The code starts off well and then goes bezerk and then comes back to normal. It is meant to convert base64 nasm into its original form. I turn the first byte received, in ASCII in the rax register, into Base64 to get the binary equivalent. Make room for two bits and then take the next byte in rbx and do the same thing. Then get the top two bits in rbx and add to the first byte to get the ASCII equivalent and save the result. I cannot treat the end of the file with = because of this issue. Thanks for the help.

 ;  Build using these commands:
 ;    nasm -f elf64 -g -F dwarf decode.asm
 ;    ld -o decode decode.o

%macro writeIt 0
          add al,bl                 ; add bl to al because upper rbx contains the rest
          mov byte[B64LIN+rcx-1],al ; move the equivalent into B64LIN
%endmacro
        ; ************************************************************************
        ;;; Note: This process does automatic conversion into ASCII ##############
        ; ************************************************************************

%macro clear 1
   xor %1,%1
%endmacro


SECTION .bss        ; Section containing uninitialized data

 BUFFLEN equ 4
 Buff: resb  BUFFLEN

SECTION .data           ; Section containing initialised data

  B64LIN:       db "000",0  ; used for output
  B64LEN:       EQU $-B64LIN ; only used to determine the size of the string treated

SECTION .text   ; Section containing code

           ;;; We convert ASCII to Base 64
Base64:
   .UpperCase:              ; remove 65 to convert match the B64Table
       sub rax,65
       ret

   .LowerCase:           ; remove 71 to convert match the B64Table
        sub rax,71
        ret

    .Numbers:                ; add 4 for numbers
        add rax,4
        ret

    .Addition:               ; remove 62 to convert match the B64Table
        sub rax,62
        ret

    .BackSlash:          ; remove 63 to convert match the B64Table
        sub rax,63
        ret



 ;------------------------------------------------------------------------
        ; Encode:       Enconde binary datas into Base 64
        ; UPDATED:      15/12/2017
        ; IN:           File
        ; RETURNS:      ASCII VERSION
        ; MODIFIES:     ASCII to Base 64

        ;;; Behaves like a switch statement
        ;;; Look for the equivalent Base64
        Convert:
            cmp rax,61h
            jge Base64.LowerCase

            cmp rax,41h
            jge Base64.UpperCase

            cmp rax,3Dh
            je .EOF1

            cmp rax,30h
            jge Base64.Numbers

            cmp rax, 2Bh
            je Base64.Addition

            cmp rax,2Fh
            je Base64.BackSlash

            cmp rax,rbx       ; comparing rbx to rax for zeros
            je Exit                 ; we're done if that happens


        ; *****************************************************************************
        ;;; Note: This process doesn't send any values back because it was added to the
        ;;;       file in the encoding process. ##############
        ; *****************************************************************************
          .EOF1:
            clear rax
            writeIt
            ret

            ;;; Register clean up
        Decode:
            ;;; Treating 1st Byte
          mov al,byte[Buff+rcx] ; takes in the first element in the input
          call Convert                  ; convert to get their Base64 value

        ;;; Treating 2nd Byte
          inc rcx                       ; increment to get the next element in the Buff
          mov bl,byte[Buff+rcx] ; moves second element into rbx
          xchg al,bl                ; xchg rax with rbx because Convert deals with rax
          call Convert          ; call Convert to get the base64 equiv.
          xchg bl,al                ; get the values back and exchange them
          rol rax,2                 ; make room for the first 2 bits in rbx
          ror rbx,4                 ; keep only the top four since first 2 bits are 00
          writeIt
          clear bl                  ; clear bl so we can role back
          rol rbx,8                 ; role 8 so we already make room when we moves rax

            ;;; Treating 3rd Byte
          inc rcx                     ; increment to get the next element
          mov al,byte[Buff+rcx] ; moves it directly into al since previous element is gone
          call Convert          ; Converts to Base64
          ror rax,2               ; roll right to get the top 4 bits only
          xchg rax,rbx          ; xchg so even the top bits are kept in the process
          writeIt

            ;;; Treating 4th Byte
          clear bl                ; clear lower 4 bits
              clear rax         ; clears everything since we have no use for it
          inc rcx                     ; increments to get next
          mov al,byte[Buff+rcx] ; moves next Byte into al
          call Convert          ; converts to Base64 equiv.
          rol rbx,8               ; make room for last 2 bits coming
          writeIt
          ret


            ;;; code keeps on running onto PrintLine to finish off

        ;-------------------------------------------------------------------------
        ; IN:           Nothing
        ; RETURNS:      The Original text
        ; MODIFIES:     Nothing
        ; CALLS:        Kernel sys_write

        PrintLine:
            push rax           ; Save all used registers
            push rbx           ; Save all used registers
            push rcx           ; Save all used registers
            push rdx           ; Save all used registers
            mov rax,4        ; Specify sys_write call
            mov rbx,1          ; Specify File Descriptor 1: Standard output
            mov rcx,B64LIN ; Pass offset of line string
            mov rdx,B64LEN ; Pass size of the line string
            int 80h          ; Make kernel call to display line string
            pop rdx          ; Restore all caller's registers
            pop rcx          ; dito
            pop rbx          ; dito
            pop rax          ; dito
            ret                ; Return to caller


        ;-------------------------------------------------------------------------


        LoadBuff:
            push rax        ; Save caller's EAX
            push rbx        ; Save caller's EBX
            push rdx        ; Save caller's EDX

            mov rax,3       ; Specify sys_read call
            mov rbx,0           ; Specify File Descriptor 0: Standard Input
            mov rcx,Buff    ; Pass offset of the buffer to read to
            mov rdx,BUFFLEN ; Pass number of bytes to read at one pass
            int 80h         ; Call sys_read to fill the buffer
            mov rbp, rax    ; Save # of bytes read from file for later
            xor rcx,rcx   ; Clear buffer pointer ECX to 0
            pop rdx         ; Restore caller's EDX
            pop rbx         ; Restore caller's EBX
            pop rax         ; Restore caller's EAX
            ret               ; And return to caller


        GLOBAL _start
        ; ------------------------------------------------------------------------
        ; MAIN PROGRAM BEGINS HERE
        ;-------------------------------------------------------------------------
        _start:
        ; We will stay into this loop until the buffer is empty
        Read:
            call LoadBuff    ; Read first buffer of data from stdin
            cmp rbp,0          ; If ebp=0, sys_read reached EOF on stdin
            jbe Exit           ; If ebp=0, we jumps to Exit
            call Decode    ; If there's still some data into the buffer, we call Encode to convert them
            call PrintLine ; Save the enconded data into stdout
            clear rbp        ; Clear ebp for the next LoadBuff
            jmp Read           ; Read one more time the data from stdi


        ; The programm did his job, we can exit
        Exit:
            xor rax, rax     ; Clear rax
            xor rbx, rbx     ; Clear rbx
            mov rax,1          ; Code for Exit Syscall
            mov rbx,0            ; Return a code of zero
            int 0x80             ; Make kernel call`


      [1]: https://i.stack.imgur.com/bHJnI.jpg
  • 1
    base64 has padding exactly to simplify decoding (and encoding). I haven't read your code but, if not already, consider processing four chars at a time. In order to improve the change of getting a useful answer consider making a [mcve] and a more precise description of the problem. Finally, you may be interested in course on gdb? It is worth it if you are planning on keeping using assembly. – Margaret Bloom Dec 29 '17 at 14:28
  • provide an input on which it fails. Base on two simple check it coverts fine (maybe printing is a bit wrong - print some odd characters at the end) – Paweł Łukasik Dec 29 '17 at 19:02
  • Your code is very weird. Normal calling conventions use `rax` as the return value, not `rbp`. Normally `rbp` is call-preserved, but `rax`, `rcx`, `rdx`, and several other regs are call-clobbered so you don't have to push/pop them around every function. You're writing `_start` so you can make up your own calling convention, but the one you made up appears to have zero advantages. The rest of your code is full of weird stuff like using 32-bit address-size but 64-bit operand-size, the opposite of the defaults for 64-bit mode. And using `dec` twice instead of `sub rbp, 2`. – Peter Cordes Dec 29 '17 at 19:34
  • Also, `int 0x80` only works for static addresses; your functions will fail if you use a buffer outside the low 32 bits of address space. [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/questions/46087730/what-happens-if-you-use-the-32-bit-int-0x80-linux-abi-in-64-bit-code). Also `movzx eax, byte [Buff+rcx]` would be easier and more efficient than `xor`-zeroing rax before doing a byte load (but produce identical results.) – Peter Cordes Dec 29 '17 at 19:35
  • Related: [NASM Linux x64 | Encode binary to base64](https://stackoverflow.com/questions/47755183/nasm-linux-x64-encode-binary-to-base64) – Peter Cordes Dec 29 '17 at 19:37

0 Answers0