Created
July 27, 2016 14:59
-
-
Save hdorothea/216adfa913a887c8f9203f5db2c86b40 to your computer and use it in GitHub Desktop.
CracklePop in x86 assembly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.section .data | |
number: | |
.quad 0 # we start out with 0 | |
crackle_output: | |
.ascii "Crackle\n" | |
pop_output: | |
.ascii "Pop\n" | |
cracklepop_output: | |
.ascii "CracklePop\n" | |
number_output: | |
.ascii " \n" | |
# constants | |
.equ CRACKLE_LENGTH, 8 | |
.equ POP_LENGTH, 4 | |
.equ NUMBER_OUTPUT_LENGTH, 3 | |
.equ CRACKLEPOP_LENGTH, 11 | |
.equ CRACKLE_NUMBER, 3 | |
.equ POP_NUMBER, 5 | |
.equ BASE, 10 | |
.equ SYS_WRITE, 4 # write system call number | |
.equ SYS_EXIT, 1 # exit system call number | |
.equ STDOUT, 1 # file descriptor | |
.equ LINUX_SYSCALL, 0x80 | |
# stack positions | |
.equ ST_OUTPUT_LENGTH, -8 # outputlength | |
.equ ST_OUTPUT_ADDRESS, -16 # outputaddress | |
.equ ST_NUMBER_OFFSET, -24 # numberoffset | |
.equ ST_CRACKLE_BOOL, -25 # cracklebool | |
.equ ST_POP_BOOL, -26 # popbool | |
.equ ST_CRACKLEPOP_BOOL, -27 # cracklepopbool | |
.equ ST, 27 | |
.section .text | |
.globl _start | |
_start: | |
movq %rsp, %rbp # save the stack pointer | |
subq $ST, %rsp # allocate space for stack variables | |
loop: | |
movb $0, %al | |
movb %al, ST_CRACKLE_BOOL(%rbp) # (re)set crackle_bool | |
movb $0, %al | |
movb %al, ST_POP_BOOL(%rbp) # (re)set pop_bool | |
cmpq $100, number # compare current number with 100 | |
jg leave # if it is greater jump to leave | |
# set up crackle bool | |
movq $0, %rdx # empty %rdx for the division | |
movq number, %rax # the number is the dividend. It needs to be in %rax | |
movq $CRACKLE_NUMBER, %rbx # 3 is the divisor. Move it to any memory location | |
divq %rbx # perform the division | |
cmpq $0, %rdx # compare the remainder of the division(in %rdx) with 0 | |
jne set_up_pop_bool # if it is not 0 jump to set_up_pop_bool | |
movb $1, %al | |
movb %al, ST_CRACKLE_BOOL(%rbp) # set cracklebool to 1 | |
set_up_pop_bool: | |
movq $0, %rdx # empty %rdx for the division | |
movq number, %rax # the number is the dividend. It needs to be in %rax | |
movq $POP_NUMBER, %rbx # 5 is the divisor. Move it to any memory location | |
divq %rbx # perform the division | |
cmpq $0, %rdx # compare the remainder of the division(in %rdx) with 0 | |
jne set_up_cracklepop_bool # if is not 0 jump to set_up_cracklepop_bool | |
movb $1, %al | |
movb %al, ST_POP_BOOL(%rbp) # set popbool to 1 | |
set_up_cracklepop_bool: | |
movb ST_CRACKLE_BOOL(%rbp), %al # move cracklebool to any general purpose register | |
andb ST_POP_BOOL(%rbp), %al # compute 'logical and' of cracklebool and popbool | |
movb %al, ST_CRACKLEPOP_BOOL(%rbp) # set cracklepopbool to the result of the 'logical and' of cracklebool and popbool | |
is_it_cracklepop_output: | |
movb ST_CRACKLEPOP_BOOL(%rbp), %al # move cracklepopbool to any general purpose register | |
cmpb $1, %al # compare cracklepopbool with 1 | |
jne is_it_crackle_output # if it is not 1 jump to is_it_crackle_output | |
movq $cracklepop_output, %rax # move the address of cracklepop_output to any general purpose register | |
movq %rax, ST_OUTPUT_ADDRESS(%rbp) # set the outputaddress to the address of cracklepop_output | |
movq $CRACKLEPOP_LENGTH, %rax # move the length of cracklepop_output to any general purpose register | |
movq %rax, ST_OUTPUT_LENGTH(%rbp) # set the outputlength to the length of cracklepop_output | |
jmp write_output # jump to write_output | |
is_it_crackle_output: | |
movb ST_CRACKLE_BOOL(%rbp), %al # move cracklebool to any register | |
cmpb $1, %al # compare cracklebool with 1 | |
jne is_it_pop_output # if it is not one jump to is_it_pop_output | |
movq $crackle_output, %rax # move the address of crackle_output to any register | |
movq %rax, ST_OUTPUT_ADDRESS(%rbp) # set the outputaddress to the address of crackle_output | |
movq $CRACKLE_LENGTH, %rax # move the length of crackle_output to any general purpose register | |
movq %rax, ST_OUTPUT_LENGTH(%rbp) # set the outputlength to the length of crackle_output | |
jmp write_output # jump to write_output | |
is_it_pop_output: | |
movb ST_POP_BOOL(%rbp), %al # move popbool to any register | |
cmpb $1, %al # compare popbool with 1 | |
jne set_up_number_output # if it is not one jump to set_up_number_output | |
movq $pop_output, %rax # move the address of pop_output to any register | |
movq %rax, ST_OUTPUT_ADDRESS(%rbp) # set the outputaddress to the address of pop_output | |
movq $POP_LENGTH, %rax # move the length of pop_output to any general purpose register | |
movq %rax, ST_OUTPUT_LENGTH(%rbp) # set the outputlength to the length of pop_output | |
jmp write_output # jump to write_output | |
set_up_number_output: | |
movq $0, %rax | |
movq %rax, ST_NUMBER_OFFSET(%rbp) # set the numberoffset to 0 | |
movq $0, %rdx # empty %rdx for the division | |
movq number, %rax # the number is the dividend it needs to be in %rax | |
movq $BASE, %rbx # 10 is the divisor move it to any memory location | |
divq %rbx # perform the division | |
cmpq $0, %rax # # The result of the divison(in %rax) is the first digit. Compare it with 0 | |
je zeroth_digit # if it is 0 we have a zero digit number. Jump to zeroth_digit | |
addq $48, %rax # Get the ascii code of the first digit | |
movb %al, number_output # move the result to number_output | |
addq $1, ST_NUMBER_OFFSET(%rbp) # add 1 to number_offset | |
zeroth_digit: | |
addq $48, %rdx # The remainder of the divison(in %rdx) is the 0th digit. Get its ascii code | |
movq ST_NUMBER_OFFSET(%rbp), %rax # move the number_offset to any register | |
movb %dl, number_output(%rax) # move the zeroth digit to number_output plus number_offset | |
movq $number_output, %rax # move the address of number_output to any register | |
movq %rax, ST_OUTPUT_ADDRESS(%rbp) # move the address of number_output to outputaddress | |
movq $NUMBER_OUTPUT_LENGTH, %rax # move the length of number_output to any general purpose register | |
movq %rax, ST_OUTPUT_LENGTH(%rbp) # move the length of number_output to outputlength | |
write_output: | |
movq $SYS_WRITE, %rax # the (write) system call number needs to be in %rax | |
movq $STDOUT, %rbx # the (standard output) file descriptor needs to be in %rbx | |
movq ST_OUTPUT_ADDRESS(%rbp), %rcx # the starting address of the buffer to write needs to be in %rcx | |
movq ST_OUTPUT_LENGTH(%rbp), %rdx # the length of the buffer to write needs to be in %rdx | |
int $LINUX_SYSCALL # call the Linux kernel | |
incq number # increment the number | |
jmp loop # jump to the beginning of the loop | |
leave: | |
movq $SYS_EXIT, %rax # the (exit) system call number needs to be in %rax | |
int $LINUX_SYSCALL # call the Linux kernel |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment