Assembly Blast From the Past (And First Post of 2025!)
Hey I’m back! (Again)
Well. What do you know? I’m back online again after only a slight hiatus of, checks notes, 5 months. I guess that’s what happens when life starts happening. But hey no I’m back. Just with less savings and more personal space. Now let’s see what I commited myself too that I happened to miss.
New Years Resolutions Should Be Called New Years Missed Goals
Well. I’m a bit late to be setting resolutions this year. So I’ll keep it simply by simply setting the goal of attempting to avoid further needless debt. While also maintaining my current responsibilities at my job. That seems like a good enough goal. But what about last year’s goals?
Last Year’s Resolutions
Even if I’m not putting much effort into resolutions this year. I probably should still look at the goals I had originally set.
- Find a better method of managing projects and using it.
For this one. I kind of did it. As seen in my New Year’s post last year I ended up setting up Vikunja. And while it works I’m still not 100% happy with it. I’ve found that I need something a little less structured which allows for more notes. Just so I can document some random things. I plan on looking into TrilliumNext. But that hasn’t happened quite yet. Mostly because I’ve been rather busy.
- Make Progress on Projects
Great idea in theory. Difficult in practice because I definitely tend to create scope creep on myself. But hey. The only person to disappoint for most of my projects is myself. So no problem there.
- More Regular Monthly Posts.
Do I need to say more on this? Yea failed. I just don’t think I can really keep up with the output required for this, unfortunately. So I don’t plan on enforcing it again any time soon. It was a fun goal though.
- Be More Productive
I have concluded that this was because the projects I was working on at work where reaching a point in which there was very little clear and measurable progress simply due to the nature of the projects. With many of the things that needed done being minor corrections. Which required me to wait for user feedback. But hey recongizing that solved a couple issues.
Now For the Real Post ASSEMBLY!
So a bit of a primer on why I ended up doing this little misadventure of a project. A couple of months ago. A friend of mine asked the somewhat rhetorical question “Why are devs so lazy? Why do they feel the need to charge extra to enable encryption?” I ended up answering with a couple of reasons that for many would just be excuses. Such as it technically being more work to support it. That it can cause unexpected slowdowns. And the idea that it’s not always as simply as flipping an enable switch.
This got me thinking a bit. Specifically about the performance. So I decided I was going to create a little demo for it.
The Demo
The idea was simple. Write a program in assembly that takes in an input and “encrypts” or “decrypts” the provided text using a provided key. There being a third option for it to simply spit out what ever it receives as input in as a comparision. I had even done it in my Computer Architecture class as a bit of extra credit. So how hard could it be.
So over the course of about 2 weeks in my free time I went about writing said program using the NASM assembler and trusty GDB. Both of which I had to partially relearn how to use.
In the end, what I ended up with was a program with 5 options. Passthrough, Encode, Decode, Encrypt, and Descrypt. The reason for 5 rather than the originally planned 3 was because of an issue I remembered having when I wrote this for a grade. And that was the “encryption” I’m using isn’t encryption. It’s just simply taking the byte of each character and XORing the bits with some key value. And that can result in unprintable characters. So I ended up setting it up so that the program would encode the resulting “encrypted” message into hexadecimal. Which I tested using the encode and decode options originally.
But hey. She works. And while I did originally brainstorm the idea of using RSA encryption rather than simply XORing text. I decided I didn’t want to be working on this project forever. The last time I “implemented” RSA was a couple of years ago in Python.
The Results
And well. This certainly demonstrates some of my comments to my friend.
With a 4.2 megabyte message (which was simply the bible) it took 0.331 seconds to encrypt it and then decrypt it. With the non-encrypted run taking 0.145 seconds. Both tests involved the running of the program twice. The encryption doubles the file size due to the method of encoding. The code needed to encode, decode, encrypt, and decrypt the text taking up nearly half of the code.
In reality, though this was little more than a thought experiment. Cause I am no wizard in assembly and I’m sure there are more efficient methods to do what I did. But it works as a simple demonstration. Which is all I needed to do. Maybe in the future, I’ll revisit it and actually attempt to implement RSA. But that will be for another time.
If you are interested in seeing how truely bad my assembly skills are. You are free to look below where I’ll hopefully have a cleaned-up copy of my assembly file.
; Sys Call numbers.
%define sys_read 0
%define sys_write 1
%define sys_exit 60
%define sys_stdin 0
%define sys_stdout 1
; Max size that can be taken as input to be encrypted.
%define input_max_len 16777216 ; 16 megabytes
; Max size that can be taken in as input to be decrypted.
%define encrypt_max 33554432 ; 32 Megs
; Block Starting Symbol Variables
SECTION .bss
input: RESB input_max_len
input_size: RESD 1
parm_count: RESQ 1
parm_array: RESQ 1
encrypt: RESB encrypt_max
; Define variables in the data section
SECTION .data
start_msg: DB "Assembly Encryption Demo",0
linebreak db 0x0A
passthrough_parm: DB "--pass",0
encrypt_parm: DB "--encrypt",0
decrypt_parm: DB "--decrypt",0
encode_parm: DB "--encode",0
decode_parm: DB "--decode",0
help_parm: DB "--help",0
parms_required_msg_1: DB "Usage: ",0
parms_required_msg_2: DB " [--pass] [--encrypt key] [--decrypt key] [--help]",0x0A," --pass: Takes in input and simply spits it back out.",0x0A," --encrypt key: Encrypts the provided text with provided key",0x0A," --decrypt key: Decrypts the provided text with provided key",0x0A," --help: Show this message",0
invalid_parm_msg: DB "Invalid Parm: ",0
end_line: DB 0x0A,0
output_label: DB "Output:",0
SECTION .text
GLOBAL _start
; Prints out the C style "help" text
print_usage:
push rbp
mov rbp, rsp
push rax
mov rax, [rbp+16]
push rax
push 0
push 0
call get_parm_n
pop rax
push start_msg
call print_line_to_null
push parms_required_msg_1
call print_to_null
push rax
call print_to_null
push parms_required_msg_2
call print_line_to_null
push 0
call exit
; Takes in the starting address of a C style string and prints the contents to
; the terminal until finding a null. (Queue the issues caused by this security
; wise)
print_to_null:
push rbp
mov rbp, rsp
push rax
push rdx
mov rax, [rbp+16]
push rax
call strlen
pop rdx
push rax
push rdx
call print
pop rdx
pop rax
; My method of managing the stack for functions may be questionable.
; All my functions take in parameters using only values found in the
; stack. Ignoring all the values found in the registers when entering
; the function for the most part. The functions also return values
; within the stack rather than making use of the registers. Requiring
; some possibly strange manipulation of the stack. When returning
; nothing like what happens in this function. The address that ret uses
; needs moved to where the original first parameter was within the
; stack. Then effectively popping off the now unneeded parameters off
; the stack. This idea is found in all of my functions.
mov rbp, [rbp+8] ; The return address into rbp.
mov [rsp+16], rbp ; Move the return address where the first parameter was originally.
pop rbp ; Pop the original value of rbp back into itself.
add rsp, 8 ; Move the stack pointer so that it's now pointing the new save location of the return address.
ret ; Make use of the return address at top of the current stack and return the function.
; Similar to print_to_null except a new line character is printed out
; once the string is done being printed.
print_line_to_null:
push rbp
mov rbp, rsp
push rax
push rdx
mov rax, [rbp+16]
push rax
call strlen
pop rdx
push rax
push rdx
call print_line
pop rdx
pop rax
mov rbp, [rbp+8]
mov [rsp+16], rbp
pop rbp
add rsp, 8
ret
; Generic print method. Takes in an address representing the start of the array
; of characters. And a count representing how many characters are within that
; array of characters. Using that to print out the characters to the terminal
; using the sys_out system call.
print:
; prep
push rbp
mov rbp, rsp
; preserve regs
push rax
push rdi
push rsi
push rdx
; do thing
mov rsi, [rbp+24]
mov rdx, [rbp+16]
mov rax, sys_write
mov rdi, sys_stdout
syscall ; Preform the Sys Call
; restore regs
pop rdx
pop rsi
pop rdi
pop rax
; return
mov rbp, [rbp+8] ; Get a copy of the return address into rbp.
mov [rsp+24], rbp ; Copy the return address to the where the first parameter would be.
pop rbp ; pop the original value of rbp back in.
add rsp, 16 ; Clear the return address in the from it's original address within the stack and clear all values in the stack except for the new copy of the return address.
ret
; Same as print except a new line character is printed at the end.
print_line:
; prep
push rbp
mov rbp, rsp
; preserve regs
push rsi
push rdx
mov rsi, [rbp+24] ; To Print
mov rdx, [rbp+16] ; Length
push rsi
push rdx
call print
push linebreak
push 1
call print
; restore regs
pop rdx
pop rsi
; return
mov rbp, [rbp+8] ; Get a copy of the return address into rbp.
mov [rsp+24], rbp ; Copy the return address to the where the first parameter would be.
pop rbp ; pop the original value of rbp back in.
add rsp, 16 ; Clear the return address in the from it's original address within the stack and clear all values in the stack except for the new copy of the return address.
ret
; Read in a string from standard input. Takes in address representing start of
; a buffer and another value representing the max value.
read:
push rbp
mov rbp, rsp
; preserve regs
push rax
push rdi
push rsi
push rdx
mov rsi, [rbp+24]
mov rdx, [rbp+16]
read_loop:
mov byte [rsi],0
inc rsi
dec rdx
cmp rdx, 0
jnz read_loop
read_loop_end:
mov rsi, [rbp+24]
mov rdx, [rbp+16]
mov rax, sys_read
mov rdi, sys_stdin
syscall
; restore regs
; return
read_return:
pop rdx
pop rsi
pop rdi
pop rax
mov rbp, [rbp+8] ; Get a copy of the return address into rbp.
mov [rsp+24], rbp ; Copy the return address to the where the first parameter would be.
pop rbp ; pop the original value of rbp back in.
add rsp, 16 ; Clear the return address in the from it's original address within the stack and clear all values in the stack except for the new copy of the return address.
ret
; Finds the length of a C style string. Only parameter is the address of the
; start of the array of characters. The function then counts until it reaches
; the null character at the end. Returning the count.
strlen:
; prep
push rbp
mov rbp, rsp
; Preserve Regs
push rdx
push rax
; Do thing
xor rax, rax
mov rdx, [rbp+16]
strlen_loop:
cmp byte [rdx], 0
je strlen_return
inc rdx
inc rax
jmp strlen_loop
strlen_return:
mov [rbp+16], rax
; Restore Regs
pop rax
pop rdx
; Return
pop rbp
ret
; Get the Nth command line parameter from the provided array.
; Parameters:
; 1. Address of parameter array.
; 2. Count of values in the array
; 3. Index of N.
get_parm_n:
push rbp
mov rbp, rsp
push rcx
mov rcx, [rbp+16]
cmp rcx, [rbp+24]
js get_parm_n_valid
jz get_parm_n_valid
mov rcx, 0
jmp get_parm_n_exit
get_parm_n_valid:
imul rcx, 8
add rcx, [rbp+32]
mov rcx, [rcx]
mov [rbp+32], rcx
get_parm_n_exit:
pop rcx
mov rbp, [rbp+8]
mov [rsp+24], rbp
pop rbp
add rsp, 16
ret
; Exit the program with the provided int value.
exit:
; Prep for run
push rbp
mov rbp, rsp
; Preserve Regs
push rax
push rdi
; Do thing
mov rax, sys_exit
mov rdi, [rbp+16]
syscall
; Restore Regs
pop rdi
pop rax
; return
mov rbp, [rbp+8] ; Get a copy of the return address into rbp.
mov [rsp+16], rbp ; Copy the return address to the where the first parameter would be.
pop rbp ; pop the original value of rbp back in.
add rsp, 8 ; Clear the return address in the from it's original address within the stack and clear all values in the stack except for the new copy of the return address.
ret
; Compares two strings. Taking only the addresses of the start of both C-Style
; Strings. Returns 0 if they are equal.
cmp_str:
push rbp
mov rbp, rsp
push rax
push rdx
push r8
push r9
xor r8, r8
xor r9, r9
mov rax, [rbp+24]
mov rdx, [rbp+16]
cmp_str_loop:
cmp byte [rax], 0
jne cmp_str_str_one_not_ended
cmp byte [rdx], 0
je cmp_str_return
mov r8, 1
jmp cmp_str_loop
cmp_str_str_one_not_ended:
cmp byte [rdx], 0
jne cmp_str_str_two_not_ended
mov r8, 1
jmp cmp_str_return
cmp_str_str_two_not_ended:
mov r8b, byte [rax]
mov r9b, byte [rdx]
xor r8b, byte [rdx]
cmp r8, 0
jnz cmp_str_return
inc rax
inc rdx
jmp cmp_str_loop
cmp_str_return:
pop r9
mov [rbp+24], r8
pop r8
pop rdx
pop rax
mov rbp, [rbp+8]
mov [rsp+16], rbp
pop rbp
add rsp, 8
ret
; Main function 1. Simply takes the incoming text and spits it to the terminal.
; Takes in the address of the buffer and then the max size of said buffer.
pass_through_text:
push rbp
mov rbp, rsp
push r8
push r9
push rax
mov r8, [rbp+24]
mov r9, [rbp+16]
pass_through_text_loop:
push r8
push r9
call read
push r8
call strlen
pop rax
twmp2:
cmp rax, 1
jle pass_through_text_done
add r8, rax
sub r9, rax
cmp r9, 0
je pass_through_text_done
jmp pass_through_text_loop
pass_through_text_done:
push output_label
call print_line_to_null
mov r8, [rbp+24]
push r8
call print_to_null
temp3:
pop rax
pop r9
pop r8
mov rbp, [rbp+8]
mov [rsp+24], rbp
pop rbp
add rsp, 16
ret
; Encode the incoming text. Parameters are as follows.
; Input buffer, Input buffer size, Output buffer, Output buffer size.
; Output bufffer should be 2x the Size of the input Buffer.
encode_text:
push rbp
mov rbp, rsp
push r8
push r9
push rax
mov r8, [rbp+40]
mov r9, [rbp+32]
encode_text_readin_loop:
push r8
push r9
call read
push r8
call strlen
pop rax
cmp rax, 1
jle encode_text_readin_done
add r8, rax
sub r9, rax
cmp r9, 0
je encode_text_readin_done
jmp encode_text_readin_loop
encode_text_readin_done:
mov r8, [rbp+40]
push r8
call strlen
pop r9
push r8
push r9
mov r8, [rbp+24]
push r8
mov r8, [rbp+16]
push r8
call encode_binary
mov r8, [rbp+16]
imul r9, 2
cmp r8, r9
jge encode_text_done
mov r9, r8
encode_text_done:
push output_label
call print_line_to_null
mov r8, [rbp+24]
push r8
push r9
call print_line
pop rax
pop r9
pop r8
mov rbp, [rbp+8]
mov [rsp+40], rbp
pop rbp
add rsp, 32
ret
; Decodes the incoming text.
; Parameters as follows. Input Buffer, Input Buffer Size, Output Buffer, Output
; Buffer Size.
; Ouput buffer should be at least half the size of the input buffer or more.
decode_text:
push rbp
mov rbp, rsp
push r8
push r9
push rax
push rdx
mov r8, [rbp+40]
mov r9, [rbp+32]
decode_text_readin_loop:
push r8
push r9
call read
push r8
call strlen
pop rax
cmp rax, 1
jle decode_text_readin_done
add r8, rax
sub r9, rax
cmp r9, 0
je decode_text_readin_done
jmp decode_text_readin_loop
decode_text_readin_done:
mov r8, [rbp+40]
push r8
call strlen
pop r9
push r8
mov r8, r9
and r8, 0b1
cmp r8, 0
je decode_even_count
sub r9, 1
decode_even_count:
push r9
mov r8, [rbp+24]
push r8
mov r8, [rbp+16]
push r8
call decode_binary
mov r8, [rbp+16]
mov rax, r9
mov rdx, 0
mov r11, 2
div r11
mov r9, rax
cmp r8, r9
jge decode_text_done
mov r9, r8
decode_text_done:
push output_label
call print_line_to_null
mov r8, [rbp+24]
push r8
push r9
call print
pop rdx
pop rax
pop r9
pop r8
mov rbp, [rbp+8]
mov [rsp+40], rbp
pop rbp
add rsp, 32
ret
; Encrypts the incoming text.
; Parameters as follows. Key String Address, Key String Length, Input Buffer,
; Input Buffer Size, Output Buffer, Output Buffer Size.
; Output buffer should be at least twice the size of the input buffer.
encrypt_text:
push rbp
mov rbp, rsp
push r8
push r9
push rax
push r10
push r11
mov r8, [rbp+40]
mov r9, [rbp+32]
encrypt_text_readin_loop:
push r8
push r9
call read
push r8
call strlen
pop rax
cmp rax, 1
jle encrypt_text_readin_done
add r8, rax
sub r9, rax
cmp r9, 0
je encrypt_text_readin_done
jmp encrypt_text_readin_loop
encrypt_text_readin_done:
mov r8, [rbp+40]
push r8
call strlen
pop r9
push r8
push r9
mov r10,[rbp+56]
mov r11,[rbp+48]
push r10
push r11
call xor_str_with_key
push r8
push r9
mov r8, [rbp+24]
push r8
mov r8, [rbp+16]
push r8
call encode_binary
mov r8, [rbp+16]
imul r9, 2
cmp r8, r9
jge encrypt_text_done
mov r9, r8
encrypt_text_done:
push output_label
call print_line_to_null
mov r8, [rbp+24]
push r8
push r9
call print_line
pop r11
pop r10
pop rax
pop r9
pop r8
mov rbp, [rbp+8]
mov [rsp+56], rbp
pop rbp
add rsp, 48
ret
; Decrypt the incoming text.
; Parameters as follows. Key String Address, Key String Length, Input Buffer,
; Input Buffer Size, Output Buffer, Output Buffer Size.
; Output buffer should be at least half the size of the input buffer or larger.
decrypt_text:
push rbp
mov rbp, rsp
push r8
push r9
push rax
push rdx
push r10
push r11
mov r8, [rbp+40]
mov r9, [rbp+32]
decrypt_text_readin_loop:
push r8
push r9
call read
push r8
call strlen
pop rax
cmp rax, 1
jle decrypt_text_readin_done
add r8, rax
sub r9, rax
cmp r9, 0
je decrypt_text_readin_done
jmp decrypt_text_readin_loop
decrypt_text_readin_done:
mov r8, [rbp+40]
push r8
call strlen
pop r9
push r8
mov r8, r9
and r8, 0b1
cmp r8, 0
je decrypt_even_count
sub r9, 1
decrypt_even_count:
push r9
mov r8, [rbp+24]
push r8
mov r8, [rbp+16]
push r8
call decode_binary
mov r8, [rbp+16]
mov rax, r9
mov rdx, 0
mov r11, 2
div r11
mov r9, rax
cmp r8, r9
jge decrypt_text_done
mov r9, r8
decrypt_text_done:
mov r8, [rbp+24]
temp1:
push r8
push r9
mov r10,[rbp+56]
mov r11,[rbp+48]
push r10
push r11
call xor_str_with_key
push output_label
call print_line_to_null
mov r8, [rbp+24]
temp2:
push r8
push r9
call print
pop r11
pop r10
pop rdx
pop rax
pop r9
pop r8
mov rbp, [rbp+8]
mov [rsp+56], rbp
pop rbp
add rsp, 48
ret
; Apply XOR "encryption" on the input buffer's contents.
; Parameters as follows. Input Buffer, Input Buffer Length, Key Buffer,
; Key Length.
; Note the results are saved to the input buffer.
xor_str_with_key:
push rbp
mov rbp, rsp
push rax
push rdx
push r9
push r10
push r11
mov rax, 0
mov rdx, [rbp+40] ; rbp+40 String
mov r9, [rbp+32] ; rbp+32 String Length
mov r10, [rbp+24] ; rbp+24 Key
mov r11, [rbp+16] ; rbp+16 Key Length
xor_str_with_key_loop:
cmp r9, 0
je xor_str_with_key_return
cmp r11, 0
jg xor_str_with_key_xor_char
mov r11, [rbp+16]
mov r10, [rbp+24]
xor_str_with_key_xor_char:
mov al, [rdx]
xor al, [r10]
mov [rdx], al
inc rdx
dec r9
inc r10
dec r11
jmp xor_str_with_key_loop
xor_str_with_key_return:
pop r11
pop r10
pop r9
pop rdx
pop rax
mov rbp, [rbp+8]
mov [rsp+40], rbp
pop rbp
add rsp, 32
ret
; Takes in an input buffer of raw binary and converts it into printable
; characters that are basically just the hexadecimal representation of the raw
; binary.
; Parameters as follows. Input Buffer, Input buffer length, Output buffer,
; Output buffer length.
; Note. Output buffer should be at least twice the size of the input buffer.
encode_binary:
push rbp
mov rbp, rsp
push rax
push rdx
push r9
push r10
push r11
; rbp+16 max encode length
; rbp+24 encode location
; rbp+32 Length of byte list
; rbp+40 Byte list start (to encode)
mov r11, [rbp+40]
mov rdx, 0 ; Chars looked at from byte list
mov r9, [rbp+24]
mov r10, 0 ; chars placed in encode
encode_binary_loop:
mov rax, [rbp+32]
cmp rdx, rax
jge encode_binary_return
mov rax, [rbp+16]
cmp r10, rax
jge encode_binary_return
mov rax, 0
mov al, byte [r11]
shr al, 4
and al, 0b1111
xor al, 0b00110000
cmp al, 57
jle encode_high_nibble_less_than_10
add al, 7
encode_high_nibble_less_than_10:
mov byte [r9], al
inc r9
inc r10
mov al, byte [r11]
and al, 0b1111
xor al, 0b00110000
cmp al, 57
jle encode_low_nibble_less_than_10
add al, 7
encode_low_nibble_less_than_10:
mov byte [r9], al
inc r11
inc r9
inc r10
inc rdx
jmp encode_binary_loop
encode_binary_return:
pop r11
pop r10
pop r9
pop rdx
pop rax
mov rbp, [rbp+8]
mov [rsp+40], rbp
pop rbp
add rsp, 32
ret
; Takes in an input buffer that should be a string of hexadecimal values.
; And converts it into a binary value that may or may not be printable.
; Parameters as follows. Input Buffer, Input buffer length, Output buffer,
; Output buffer length.
; Note. Output buffer should be at least half the size or larger of the input
; buffer.
decode_binary:
push rbp
mov rbp, rsp
push rax
push rdx
push r9
push r10
push r11
; rbp+16 max decode length
; rbp+24 decode location
; rbp+32 Length encode
; rbp+40 Byte list of encode
mov r11, [rbp+40]
mov rdx, 0 ; Chars looked at from byte list
mov r9, [rbp+24]
mov r10, 0 ; chars placed in encode
decode_binary_loop:
mov rax, [rbp+32]
cmp rdx, rax
jge decode_binary_return
mov rax, [rbp+16]
cmp r10, rax
jge decode_binary_return
mov al, byte [r11]
cmp al, 57
jle decode_high_nibble_greater_than_9
sub al, 7
decode_high_nibble_greater_than_9:
and al, 0b1111
shl al, 4
mov byte [r9], al
inc r11
inc rdx
mov al, byte [r11]
cmp al, 57
jle decode_low_nibble_greater_than_9
sub al, 7
decode_low_nibble_greater_than_9:
and al, 0b1111
or byte [r9], al
inc r11
inc r9
inc r10
inc rdx
jmp decode_binary_loop
decode_binary_return:
pop r11
pop r10
pop r9
pop rdx
pop rax
mov rbp, [rbp+8]
mov [rsp+40], rbp
pop rbp
add rsp, 32
ret
_start:
; Save the parameter addresses into memory
save_program_parameters:
mov rax, [rsp]
mov [parm_count], rax
add rsp, 8
mov [parm_array], rsp
sub rsp, 8
process_program_parameters:
mov rax, [parm_count]
cmp rax, 1
jz need_help ; If no parms found print message. And exit
cmp rax, 2
jz process_single_parm
cmp rax, 3
jz process_two_parm
jmp need_help
process_single_parm:
mov rax, [parm_array]
push rax
push 2
push 1
call get_parm_n
pop rax
push rax
push help_parm
call cmp_str
pop rdx
cmp rdx, 0
je need_help
push rax
push passthrough_parm
call cmp_str
pop rdx
cmp rdx, 0
je passthrough_parm_given
push rax
push encode_parm
call cmp_str
pop rdx
cmp rdx, 0
je encode_parm_given
push rax
push decode_parm
call cmp_str
pop rdx
cmp rdx, 0
je decode_parm_given
push invalid_parm_msg
call print_to_null
push rax
call print_line_to_null
jmp need_help
passthrough_parm_given:
mov r8, input
mov r9, input_max_len
push r8
push r9
call pass_through_text
push 0
call exit
encode_parm_given:
mov r8, input
mov r9, input_max_len
push r8
push r9
mov r8, encrypt
mov r9, encrypt_max
push r8
push r9
call encode_text
push 0
call exit
decode_parm_given:
mov r8, encrypt
mov r9, encrypt_max
push r8
push r9
mov r8, input
mov r9, input_max_len
push r8
push r9
call decode_text
push 0
call exit
process_two_parm:
mov rax, [parm_array]
push rax
push 3
push 1
call get_parm_n
pop rax
push rax
push encrypt_parm
call cmp_str
pop rdx
cmp rdx, 0
je encrypt_parm_given
push rax
push decrypt_parm
call cmp_str
pop rdx
cmp rdx, 0
je decrypt_parm_given
jmp need_help
encrypt_parm_given:
mov rax, [parm_array]
push rax
push 3
push 2
call get_parm_n
pop rax
push rax ; First parm of encrypt_text
push rax ; First parm of strlen which will be replaced with length or second parm of encrypt_text
call strlen
mov r8, input
mov r9, input_max_len
push r8 ; Third Parm of encrypt_text
push r9 ; Fourth parm of encrypt_text
mov r8, encrypt
mov r9, encrypt_max
push r8 ; Fifth
push r9 ; Sixth
call encrypt_text
push 0
call exit
decrypt_parm_given:
mov rax, [parm_array]
push rax
push 3
push 2
call get_parm_n
pop rax
push rax ; First parm of encrypt_text
push rax ; First parm of strlen which will be replaced with length or second parm of encrypt_text
call strlen
mov r8, encrypt
mov r9, encrypt_max
push r8
push r9
mov r8, input
mov r9, input_max_len
push r8
push r9
call decrypt_text
push 0
call exit
need_help:
mov rax, [parm_array]
push rax
call print_usage