Skip to content

Instantly share code, notes, and snippets.

@jpoler
Created September 3, 2014 21:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpoler/8ecbef27861bd06eca27 to your computer and use it in GitHub Desktop.
Save jpoler/8ecbef27861bd06eca27 to your computer and use it in GitHub Desktop.
Code CracklePop written in 32-bit x86 assembly (GAS syntax).
### Code CracklePop ###
### I have been learning assembly recently
### and this project was a good fit for my skill level
### to assemble on linux, please use:
### as code_crackle_pop.S -o crackle.o
### ld crackle.o -o crackle
### and run the program with:
### ./crackle
.section .bss
.lcomm buff, 50
.section .data
crackle:
.ascii "Crackle\n"
c_len = . - crackle
pop:
.ascii "Pop\n"
p_len = . - pop
cracklepop:
.ascii "CracklePop\n"
cp_len = . - cracklepop
.section .text
.globl _start
.equ SYS_WRITE, 4
.equ SYS_EXIT, 1
.equ STDOUT, 1
_start:
pushl $0x0 # Prime the 5 counter
pushl $0x0 # Prime the 3 counter (jk, zero isn't prime)
pushl $0x0 # overall counter
loop:
popl %eax # Pop overall counter into eax
popl %ecx # Pop 3 counter into ecx
popl %edx # Pop 5 counter into edx
incl %eax # Increment all three counters
incl %ecx
incl %edx
cmpl $0x64, %eax # check if we are past 100
jg end_loop # if so, we are done
cmpl $0x3, %ecx # check if the 3 counter == 3
pushf # push flags onto the stack
popl %ebx # pop flags into ebx
andl $0x40, %ebx # we are interested in the 6th bit 2**6 = 0x40 (zero flag)
shrl $0x1, %ebx # make room for the result of second comparison
cmpl $0x5, %edx # check if the 5 counter == 5
pushf # push flags onto the stack
andl $0x40, (%esp) # save only the 6th bit of value pointed to by esp
orl (%esp), %ebx # or the comparison results
addl $0x4, %esp # take the flags off the stack
cmpl $0x60, %ebx # divisible by 5 and 3?
je cp # jump to CracklePop (cp)
cmpl $0x20, %ebx # divisible by 3?
je c # jump to Crackle (c)
cmpl $0x40, %ebx # divisible by 5?
je p # jump to pop (p)
jmp default # jump to default
cp:
pushl $0x0 # push reset 5 counter onto stack
pushl $0x0 # push reset 3 counter onto stack
movl $cracklepop, %ecx # buffer for write system call
movl $cp_len, %edx # length of buffer
jmp print # jump to print
c:
pushl %edx # push 5 counter onto stack
pushl $0 # push reset 3 counter onto stack
movl $crackle, %ecx # buffer for write system call
movl $c_len, %edx # length of buffer
jmp print # jump to print
p:
pushl $0 # push reset 5 counter on to stack
pushl %ecx # push 3 counter on to stack
movl $pop, %ecx # buffer for write system call
movl $p_len, %edx # length of buffer
jmp print # jump to print
default:
pushl %edx # push 5 counter onto stack
pushl %ecx # push 3 counter onto stack
pushl %eax # this saves the actual overall counter
call wrangle_digits # wrangle digits will convert into ascii string
movl %eax, %edx # buffer length is at most 4
movl $buff, %ecx # buffer for write system call
movl $SYS_WRITE, %eax # the length of the buffer was returned in eax
movl $STDOUT, %ebx # specify standard output for write
int $0x80 # system interrupt (call kernel)
jmp loop # jump to start of loop
print:
pushl %eax # save overall counter
movl $SYS_WRITE, %eax # SYS_WRITE sytem call
movl $STDOUT, %ebx # specify standard output for write
int $0x80 # system interrupt
jmp loop # jump to start of loop
end_loop:
movl $SYS_EXIT, %eax # prepare for system call
movl $0x0, %ebx # signal that all was well at exit
int $0x80 # exit gracefully
.type wrangle_digits, @function
wrangle_digits:
pushl %ebp # save value of base pointer
movl %esp, %ebp # set base pointer to equal stack pointer (preamble)
movl 8(%ebp), %eax # move integer to be printed into eax
pushl $0xa # push a newline onto the stack
movl $0xa, %ebx # we will be dividing by 10
dig_loop:
cmpl $0x0, %eax # if our integer has reached zero, we are done
je write # jump to write if the comparison was true
xor %edx, %edx # clear edx (so only eax is the dividend)
divl %ebx # divide our integer by 10
addl $0x30, %edx # convert digit to ascii
pushl %edx # push least significant digit onto stack
jmp dig_loop # repeat
write:
xor %edi, %edi # clear the index register
write_loop:
cmpl %ebp, %esp # does the stack point to the base?
je end_wrangle # if so, we have printed everything
popl %ebx # pop the most recent digit into ebx
movb %bl, buff(, %edi, 1) # move the lowest byte of ebx into our buffer offset
incl %edi # by our index, and increment index.
jmp write_loop # repeat
end_wrangle:
movl %edi, %eax # return length of string
movl %ebp, %esp # reset stack pointer to base
popl %ebp # reset base pointer
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment