summaryrefslogtreecommitdiffstats
path: root/b32e.asm
blob: 8bab796947446e57e84b63d0c52c73ba5933f4aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
section .data

rfc4648 db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'

section .bss

input_buffer resb 8
output_buffer resb 8

section .text
global _start

; read_input
; reads 5 bytes (40 bits) of input
; uses reg: rax, rdi, rsi, rdx
; uses mem: input_buffer
read_input:
    ; linux x64 read(stdin, input_buffer, 5)
    mov rax, 0
    mov rdi, 0
    mov rsi, input_buffer
    mov rdx, 5
    syscall
    ret

; write_output
; writes the output buffer to stdout
; uses reg: rax, rdi, rsi, rdx
; uses mem: output_buffer(ro)
write_output:
    ; linux x64 write(stdout, output_buffer, 8)
    mov rax, 1
    mov rdi, 1
    mov rsi, output_buffer
    mov rdx, 8
    syscall
    ret

; b32e
; encodes 40 bits (5 bytes) to 8 RFC4648 base32 characters
; uses reg: rax(in: bytes read), rbx, rcx, r11
; uses mem: input_buffer, output_buffer
b32e:
    ; save the number of bits read in cl
    mov bl, 8 ; each byte contains 8 bits
    mul bl
    mov cl, al
    ; set up output counter
    xor r11, r11
    ; initialize output buffer with padding
    mov rbx, 0x3d3d3d3d3d3d3d3d
    mov qword [output_buffer], rbx

.loop:
    ; clear rbx
    xor rbx, rbx

    ; get a byte from the input
    mov bl, byte [input_buffer + 4]

    ; mask and shift to get 5 bits which is a number in 0 ~ 31
    and bl, 0xf8
    shr bl, 3

    ; shift left the input buffer
    shl qword [input_buffer], 5

    ; convert to base32
    add rbx, rfc4648
    mov bl, byte [rbx]
    mov byte [output_buffer + r11], bl 

    ; increase counter
    inc r11

    ; check number of bits converted >= bits read
    mov bl, 5 ; each iteration processed 5 bits
    mov rax, r11
    mul bl
    cmp al, cl
    jge .exit

    ; check counter
    ; when the counter reaches 8 it means that 8 characters (40 bits)
    ; have been processed and written
    cmp r11, 8
    jl .loop 

.exit:
    ret


_start:
    nop

.loop:
    ; try to read 5 bytes
    call read_input
    ; read nothing
    cmp rax, 0
    je .exit

    ; swap endianness of input
    mov rbx, qword [input_buffer]
    bswap rbx
    ; correct position in qword
    shr rbx, 24
    mov qword [input_buffer], rbx

    ; convert to base 32
    call b32e
    ; print
    call write_output
    jmp .loop

.exit:
    ; linux x64 exit(0)
    mov rax, 60
    mov rdi, 0
    syscall