I am a beginner in assembly and would like to know ways I could improve my code. I am talking more about assembly specific things and less the logic e.g. what I could've written better, like loops
SECTION .data ; Section containing initialised data
Base64Table: db "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
OutBuf: db "xxxx"
OutBufLen: equ $ - OutBuf
SECTION .bss ; Section containing uninitialized data
InBufLen: equ 3
InBuf: resb InBufLen
SECTION .text ; Section containing code
global _start ; Linker needs this to find the entry point!
_start:
read:
; read chunk from stdin to InBuf
mov rax, 0 ; sys_read
mov rdi, 0 ; file descriptor: stdin
mov rsi, InBuf ; destination buffer
mov rdx, InBufLen ; maximum # of bytes to read
syscall
; check number of bytes read
cmp rax, 0 ; did we receive any bytes?
je exit; if not: exit the program
xor r10, r10 ; clear r10
mov r10, rax ; save # of bytes read
cmp rax, 2 ; If only two bytes were read call specific subroutine
je twobyte
cmp rax, 1
je onebyte
; clear r10, r11 and rax for future usage
xor r11, r11
xor rax, rax
process:
mov eax, [InBuf]
; convert little endian to big endian and shifting right by 8 to remove 0x00
; which we only got because we saved a 24 bit value into a 32 bit register
bswap eax ; example: 0x004e5089 -> 0x89504e00
shr eax, 8 ; example: 0x89504e00 -> 0x0089504e
; clean rdx and rbx to store values there and then copy eax into edx to use edx to shift the values around
xor rdx, rdx
xor rbx, rbx
mov edx, eax
; Get second char in 3 byte chunk
shr edx, 6 ; move first char out of the way
and edx, 0x3F ; mask 3 and 4 char
mov bl, [Base64Table + rdx] ; Lookup and add to ebx on the 4 place xxxx -> xxxV
xor rdx, rdx ; clear rdx
mov edx, eax ; fill edx with eax
and edx, 0x3F ; get first char by masking all others
mov bh, [Base64Table + rdx] ; lookup and add to ebx on the 3 place xxxV -> xxiV
xor rdx, rdx ; clear rdx
mov edx, eax ; fill edx with eax
shl ebx, 16 ; move 3 and 4th place of ebx to first and second xxiV -> iVxx
shr edx, 18 ; move away 1st, 2nd and 3d char out of edx
mov bl, [Base64Table + rdx] ; look up remaining 4th char and add to ebx iVxx -> iVxB
xor rdx, rdx ; clear rdx
mov edx, eax ; fill edx with eax
shr edx, 12 ; move 1st and 2nd char out of edx
and edx, 0x3F ; mask 4 char
mov bh, [Base64Table + rdx] ; look up remaining 3th char and add to 3th place in ebx iVxB -> iVOB
mov [OutBuf + r11], ebx ; move content of ebx to the output at the correct place (r11)
push r11 ; save r11
push r10 ; save r10
call write ; write output
pop r10 ; get r10 back
pop r11 ; get r11 back
add r11, 4 ; add 4 to output index
cmp r11, r10 ; check if all data read in was processed yet by comparing the numbers of read in bytes to the index in the output
jl process ; if r11 is lower, go to process
jmp read ; else read new data
onebyte:
; Clear registers
xor rdx, rdx
xor rbx, rbx
xor rax, rax
;Add two = and move them up 16 to make room for the last two chars
mov bh, 0x3D
mov bl, 0x3D
shl ebx, 16
mov eax, [InBuf]
and eax, 0xFF ; Mask all other bytes except last one
shl eax, 4 ; Add 4 zeroes at the end
mov edx, eax
shr edx, 6 ; move first char out of edx
and edx, 0x3F ; mask everything except the remaining (second) 6 bites
mov bl, [Base64Table + rdx] ; Look up and write to bh
xor rdx, rdx
mov edx, eax
and edx, 0x3F ; Mask second char away
mov bh, [Base64Table + rdx] ; Lookup first char and add to output
; Write and exit the programm
mov [OutBuf], ebx
call write
jmp exit
twobyte: ;TODO Document
; Clear registers
xor rdx, rdx
xor rbx, rbx
xor rax, rax
mov eax, [InBuf]
and eax, 0xFFFF ; Mask all other bytes except the two last ones
bswap eax
shr eax, 16 ; bswap ax doesn't work so we have to do this manually
shl eax, 2 ; Add 2 zeroes at the end
; Add one =
mov bh, 0x3D
mov edx, eax
and edx, 0x3F
mov bl, [Base64Table + rdx]
xor rdx, rdx
mov edx, eax
shl ebx, 16
shr edx, 6
and edx, 0x3F
mov bh, [Base64Table + rdx]
xor rdx, rdx
mov edx, eax
shr edx, 12
and edx, 0x3F
mov bl, [Base64Table + rdx]
; Write and exit the programm
mov [OutBuf], ebx
call write
jmp exit
write: ;TODO Document
mov rax, 1
mov rdi, 1
mov rsi, OutBuf
mov rdx, OutBufLen
syscall
ret
exit: ;TODO Document
mov rdi, 0
mov rax, 60
syscall