Wishful Coding

Didn't you ever wish your computer understood you?

31c3 Lightning Talk

I’ve been putting off writing this post for far to long, because I’m to busy hacking on other things. So here are the video, slides, and code. Enjoy.

Slides

import usb.core
import binascii
import re

dev = usb.core.find(idProduct=0x001e, idVendor=0x0b0c)
dev.set_configuration()

def hex_print(s):
    print(binascii.hexlify(s).decode(), re.sub("[^a-zA-Z0-9]", ".", str(s, 'ascii', 'replace')))

def write(data):
    s = binascii.unhexlify(data)
    hex_print(s)
    dev.write(0x02, s)

def read(t=100):
    try:
        while True:
            s = dev.read(0x81, 8, t)
            hex_print(s)
            t = 100
    except usb.core.USBError:
        pass
    print('---')

def message(data, display=0x01):
    #write = print
    data = chr(display).encode() + chr(len(data)).encode() + data
    write(b"010305" + binascii.hexlify(chr(len(data)).encode()) + b"00000000")
    for i in range(int(len(data)/6)):
        s = data[i*6:i*6+6]
        b = binascii.hexlify(s)
        write(b"0006" + b)

    i += 1
    s = data[i*6:i*6+6]
    b = binascii.hexlify(s.ljust(6))
    write(b'0004' + b)

# always the same lenth
def confirm_login(data, lang='nl'):
    data = b'\x03' + data
    write(b"0103081500000000")
    for i in range(3):
        s = data[i*6:i*6+6]
        b = binascii.hexlify(s.ljust(6))
        write(b"0006" + b)

    write(b'000300' + binascii.hexlify(lang) + b'000000')

if __name__ == '__main__':
    write(b"0209000000000000") # shield
    read()
    write(b"0103020000000000") # version
    read()
    write(b"0103010200000000") # insert card
    write(b"00026e6c00000000")
    read(10000)
    write(b"0103030000000000") # card info
    read()
    write(b"0103040000000000") # ask pin
    read(60000)
    message(b'abbalalalala', 0x00) # sign data
    read()

    message(b"Never gonna give you up Never gonna let you down                    ")
    read(10000)

    write(b"0103060000000000") # cryptogram
    read()

    confirm_login(b'You where drunk', b'en')
    read()
Pepijn de Vos

Branch-free FizzBuzz in Assembly

I came across this post that discusses ways to write FizzBuzz in Clojure without using conditionals. However, most if not all of the solutions still do a lot of branching behind the scenes. Think of hash lookups for example.

So I asked to myself, how can I write a FizzBuzz solution with no branches at all? Probably not in Clojure; you can’t easily tell where it is branching or not.

The only way to be absolutely sure is to write it in assembly. So I did. I never did assembly before, so it might be terrible code.

I used an array of 15 pointers to either “fizz”, “buzz”, “fizzbuzz”, or a number buffer. I then filled the number buffer with the current number in ascii and printed whatever I get from the array.

One thing I struggeled with is how to stop. At first I had one condition to see if I reached 100. Now I use a lookup table that calls sys_time 99 times and then sys_exit.

section .data
  f db "fizz    "
  b db "buzz    "
  fb db "fizzbuzz"
  n db 10 ; newline string
  cycle dq num, num, f, num, b, f, num, num, f, b, num, f, num, num, fb
  callid dq 13, 1 ; sys_time, sys_exit

section .bss
  num resb 8 ; number buffer

section .text
global _start

print:      ;write rcx
  mov rax,4 ;sys_write
  mov rbx,1 ;stdout
  mov rdx,8
  int 0x80
  ret

newline:    ;write newline
  mov rax,4 ;sys_write
  mov rbx,1 ;stdout
  mov rcx,n
  mov rdx,1
  int 0x80
  ret

itoa:      ;convert rax to str
  mov byte[num+1],0x30
  mov rdx,0
  mov rcx,10
  div rcx
  add [num+1],rdx
  mov byte[num],0x30
  mov rdx,0
  mov rcx,10
  div rcx
  add [num],rdx
  ret

_start:
  mov r12,0

hundredtimes:
  ; initialise number buffer
  mov rax,r12
  inc rax
  call itoa

  ; mod 15 the number
  mov rax,r12
  mov rdx,0
  mov rcx,15
  div rcx

  ; look up the number in cycle
  ; prints the num buffer or any of the strings
  mov rcx,[cycle+rdx*8]
  call print
  call newline
  
  ; next...
  inc r12

  ; devide the number by 100
  mov rax,r12
  mov rdx,0
  mov rcx,100
  div rcx

  ; get the time or exit
  mov rax,[callid+rax*8]
  int 0x80

  ; jump to the top of the loop
  jmp hundredtimes

To compile on a 64 bit machine:

nasm -f elf64 fizzbuzz.asm
ld -o fb fizzbuzz.o
./fb
Pepijn de Vos

Constraint Driven Development

I was reflecting on all the fun I’m having with my Arduino GPS system, and found something interesting.

I could have used a Raspi, and have some actual RAM, storage and screen. But by constraining myself to the bare minimum, I created all sorts of wonderful algorithms and hacks.

This is maybe a known thing, but it bears repeating: constraints foster creativity. Writing “a story” is much harder than wiritng “a story about the first brick of the city hall of Amsterdam”. By narrowing down the search space, your brain can do a much more exhaustive search.

An example that comes to mind is LuaJIT. Lua is found in all sorts of places, so a small binary size is a virtue. Someone told me it fits on a floppy, which I found is true.

LuaJIT on a floppy

Consequently, it contains wonderful things like this.

[A recursive backpropagation algorithm with backtracking, employing skip-list lookup and round-robin caching, emitting stack operations on-the-fly for a stack-based interpreter – and all of that in a meager kilobyte? Yep, compilers are a great treasure chest. Throw away your textbooks and read the codebase of a compiler today!]

Once upon a time, Guy Steele set a high tax on special forms (syn-tax, ha, ha…), and consequently invented Scheme. Later, John Shutt thought that wasn’t enough, and invented Kernel. Clojure on the onther hand, is only constrained to be practical.

What is your favourite piece of constrained software? How do you set constraints for yourself?

Pepijn de Vos