[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