Nash's world

Reddit clone in ASM

by on Feb.10, 2010, under cool, Programing

here is reddit clone rewritten in x86 asm Assembly

.globl main
main:
	/* Change to the working directory */
	xorl %eax,%eax
	pushl $dir		// path
	movb $12,%al
	pushl %eax		// chdir
	int $0x80
	setc %bl
	addl $8,%esp
	testb %bl,%bl
	jnz out

	/* Allow up to 32 links */
	pushl $(32*256)
	calll alloc
	addl $4,%esp
	movl %eax,links

	/*
	 * Read each link.
	 * They are stored in files whose name start at 'a' and is
	 * incremented at each new link.
	 * XXX Allow for more than 26
	 */
	xorl %eax,%eax
	movb $'a',%al
	pushl %eax
	movl %esp,%ecx		// ecx = path

read_link:
	xorl %eax,%eax
	pushl %eax		// O_RDONLY
	pushl %ecx		// path
	movb $5,%al
	pushl %eax		// open
	int $0x80
	setc %bl
	addl $12,%esp
	testb %bl,%bl
	jnz out_link2

	movl %eax,%edx		// edx = fd

	leal tmp_buf,%edi

	pushl $256		// len
	pushl %edi		// buf
	pushl %eax		// fd
	xorl %eax,%eax
	movb $3,%al
	pushl %eax		// read
	int $0x80
	setc %bl
	addl $16,%esp
	testb %bl,%bl
	jnz out_link

	movb $0,0(%edi,%eax)

	/*
	 * Store in the "links" array
	 */

	pushl %ecx

	/* Copy url */
	pushl $0xa		// '\n'
	pushl %edi		// url
	calll _strchr
	addl $8,%esp
	subl %edi,%eax
	movl %eax,%ecx
	movl %edi,%esi
	movl nlinks,%ebx
	movl links,%edi
	shll $8,%ebx		// ebx = nlinks * 256
	leal 0(%edi,%ebx),%edi
	cld
	rep movsb
	movb $0,(%edi)

	/* Copy description */
	incl %esi
	pushl $0xa
	pushl %esi
	calll _strchr
	addl $8,%esp
	subl %esi,%eax
	movl %eax,%ecx
	movl links,%edi
	leal 128(%edi,%ebx),%edi
	cld
	rep movsb
	movb $0,(%edi)

	/* Copy path */
	movl 4(%esp),%ecx
	movl links,%edi
	movl %ecx,248(%edi,%ebx)

	/* Copy score */
	incl %esi
	pushl %esi
	calll _atoi
	addl $4,%esp
	movl links,%edi
	leal 252(%edi,%ebx),%edi
	movl %eax,(%edi)

	popl %ecx

	pushl %edx		// fd
	movl $6,%eax
	pushl %eax		// close
	int $0x80
	addl $8,%esp

	incl (%esp)		// Next file (increment the filename)
	incl nlinks
	jmp read_link

out_link:
	pushl %edx		// fd
	movl $6,%eax
	pushl %eax		// close
	int $0x80
	addl $8,%esp
out_link2:
	addl $4,%esp

	/* XXX Implement my own qsort */
	pushl $compar
	pushl $256
	pushl nlinks
	pushl links
	calll qsort
	addl $16,%esp

	/* get QUERY_STRING */
	pushl $query_string
	calll getenv
	addl $4,%esp

	testl %eax,%eax
	jz 1f
	movl (%eax),%ebx
	testb %bl,%bl
	jz 1f
	movl %eax,saved_qs
	jmp have_qs
1:
	/* Output header */
	xorl %eax,%eax
	pushl $(ok_end-ok)	// len
	pushl $ok		// buf
	movb $1,%al
	pushl %eax		// stdout
	movb $4,%al
	pushl %eax		// write
	int $0x80
	addl $16,%esp
	/* Print the links */
	movl nlinks,%ecx
	movl links,%edx
1:
	leal tmp_buf,%edi
	/* Upvote */
	xorl %ebx,%ebx
	pushl %ebx
	pushl $0x003d703f	// ?p=
	movl %esp,%eax
	movl 248(%edx),%ebx
	movb %bl,3(%eax)
	pushl $uarr		// desc
	pushl %eax		// url
	pushl %edi		// dst
	calll make_a_href
	addl $20,%esp
	movl %eax,%edi
	/*
 */
	movl $0x2f72623c,%eax
	stosl
	movb $0x3e,%al
	stosb

	/* Score */
	movl 252(%edx),%eax
	/* XXX Use a proper itoa() */
	addl $'0',%eax
	stosb
	movb $' ',%al
	stosb

	/* The actual link */
	leal 128(%edx),%ebx
	pushl %ebx		// desc
	pushl %edx		// url
	pushl %edi		// dst
	calll make_a_href
	addl $12,%esp
	movl %eax,%edi
	/*
 */
	movl $0x2f72623c,%eax
	stosl
	movb $0x3e,%al
	stosb

	/* Downvote */
	xorl %ebx,%ebx
	pushl %ebx
	pushl $0x003d643f	// ?d=
	movl %esp,%eax
	movl 248(%edx),%ebx
	movb %bl,3(%eax)
	pushl $darr		// desc
	pushl %eax		// url
	pushl %edi		// dst
	calll make_a_href
	addl $20,%esp
	movl %eax,%edi
	/*
 */
	movl $0x2f72623c,%eax
	stosl
	movb $0x3e,%al
	stosb

	leal tmp_buf,%eax
	subl %eax,%edi
	pushl %edi		// len
	pushl %eax		// buf
	xorl %eax,%eax
	movb $1,%al
	pushl %eax		// stdout
	movb $4,%al
	pushl %eax		// write
	int $0x80
	addl $16,%esp

	addl $256,%edx
	decl %ecx
	jnz 1b
	jmp out

have_qs:
	/* Output header */
	xorl %eax,%eax
	pushl $(submit_str_end-submit_str)	// len
	pushl $submit_str	// buf
	movb $1,%al
	pushl %eax		// stdout
	movb $4,%al
	pushl %eax		// write
	int $0x80
	addl $16,%esp

	/* URL submit? */
	movl saved_qs,%eax
	cmpw $0x3d74,(%eax)	// "t="
	jnz 9f
	/* Get Title */
	incl %eax
	incl %eax
	movl %eax,%ebx
	pushl $'&'
	pushl %eax
	calll _strchr
	addl $8,%esp
	movb $0,(%eax)
	pushl %ebx

	/* Get URL */
	incl %eax
	cmpw $0x3d75,(%eax)	// "u="
	jnz 2f
	incl %eax
	incl %eax

	/* Build file */
	/* strlen(URL) < 120 */
	movl %eax,%esi
	pushl %eax
	calll _strlen
	addl $4,%esp
	cmpl $120,%eax
	jge 2f
	movl %eax,%ecx
	leal tmp_buf,%edi
	/* Decode URL */
0:
	movb (%esi),%al		// XXX use lodsb
	cmpb $'%',%al
	jne 1f
	incl %esi
	decl %ecx
	movb (%esi),%al
	cmpb $'9',%al
	jg 3f
	subb $'0',%al
	jmp 4f
3:
	subb $'A',%al		// XXX lowercase too
	addb $10,%al
4:
	shlb $4,%al
	movb 1(%esi),%bl
	cmpb $'9',%bl
	jg 3f
	subb $'0',%bl
	jmp 4f
3:
	subb $'A',%bl		// XXX lowercase too
	addb $10,%bl
4:
	orb %bl,%al
	incl %esi
	decl %ecx
1:
	stosb
	incl %esi
	loop 0b

	movb $'\n',(%edi)
	incl %edi
	/* strlen(title) < 128 */
	movl (%esp),%esi
	pushl %esi
	calll _strlen
	addl $4,%esp
	cmpl $128,%eax
	jge 2f
	/* Replace '+' with ' ' in title */
	/* XXX also do the same thing as URL decoding */
	movl %eax,%ecx
0:
	movb (%esi),%al
	cmpb $'+',%al
	jne 1f
	movb $' ',%al
1:
	stosb
	incl %esi
	loop 0b

	movb $'\n',(%edi)
	incl %edi
	movw $0x0a30,%ax	// "0\n"
	stosw
	leal tmp_buf,%esi
	subl %esi,%edi		// edi = len

	movl nlinks,%eax
	addl $'a',%eax		// XXX more than 26?
	pushl %eax
	movl %esp,%ecx		// ecx = path
	pushl $0644		// mode
	pushl $0x202		// O_RDWR | O_CREAT
	pushl %ecx		// path
	movb $5,%al
	pushl %eax		// open
	int $0x80
	setc %bl
	addl $20,%esp
	testb %bl,%bl
	jnz 2f
	pushl %edi		// len
	pushl $tmp_buf		// buf
	pushl %eax		// fd
	movl $4,%eax
	pushl %eax		// write
	int $0x80
	addl $16,%esp

2:
	addl $4,%esp
	jmp out

9:
	/* Upvote? */
	cmpw $0x3d70,(%eax)	// "p="
	jnz 1f
	movl $1,%ebx		// ebx = up
	jmp 2f
	/* Downvote? */
1:
	cmpw $0x3d64,(%eax)	// "d="
	jnz out
	movl $~0,%ebx		// ebx = down
2:
	xorl %edx,%edx
	movb 2(%eax),%dl
	/* Look for the link we voted on */
	movl nlinks,%ecx
	movl links,%edi
1:
	cmpb %dl,248(%edi)
	je 2f
	addl $256,%edi
	loop 1b
2:
	testl %ecx,%ecx
	jz out
	addl %ebx,252(%edi)	// Update the score
	movl 252(%edi),%ecx
	cmpb $0,%cl
	js out
	cmpb $10,%cl
	jge out
	/* Get offset in the file to update */
	pushl %edi
	calll _strlen
	addl $4,%esp
	movl %eax,%ebx
	leal 128(%edi),%edx
	pushl %edx
	calll _strlen
	addl $4,%esp
	addl %eax,%ebx
	incl %ebx
	incl %ebx		// Account for the two '\n'

	xorl %eax,%eax
	movb $2,%al
	pushl %eax		// O_RDWR
	leal 248(%edi),%esi
	pushl %esi		// path
	movb $5,%al
	pushl %eax		// open
	int $0x80
	setc %cl
	addl $12,%esp
	testb %cl,%cl
	jnz out

	movl %eax,%ecx		// ecx = fd
	xorl %eax,%eax
	pushl %eax		// SEEK_SET
	pushl %ebx		// offset
	pushl %ecx		// fd
	movb $19,%al
	pushl %eax		// lseek
	int $0x80
	setc %bl
	addl $16,%esp
	testb %bl,%bl
	jnz out

	/* Write the new score */
	movl 252(%edi),%eax
	addl $'0',%eax		// XXX proper itoa()
	orl $0x0a00,%eax	// '\n'
	movw %ax,tmp_buf

write:
	pushl $2		// len
	pushl $tmp_buf		// buf
	pushl %ecx		// fd
	movl $4,%eax
	pushl %eax		// write
	int $0x80
	addl $16,%esp

out:
	xorl %eax,%eax
	retl

/*
 * char *make_a_href(char *dst, char *url, char *desc)
 */
 make_a_href:
	pushl %ecx
	pushl %edx
	pushl %edi
	pushl %esi
	movl 20(%esp),%edi
	/*  */
	movw $0x3e22,%ax
	stosw
	/* Description */
	movl 28(%esp),%edx
	pushl %edx
	calll _strlen
	addl $4,%esp
	movl %eax,%ecx
	movl %edx,%esi
	rep movsb
	/*  */
	movl $0x3e612f3c,%eax
	stosl
	movl %edi,%eax
	popl %esi
	popl %edi
	popl %edx
	popl %ecx
	retl

/*
 * char *strchr(char *s, int c)
 */
_strchr:
	pushl %ecx
	pushl %edi
	xorl %ecx,%ecx
	notl %ecx
	movl 12(%esp),%edi
	movl 16(%esp),%eax
	cld
	repnz scasb
	leal -1(%edi),%eax
	popl %edi
	popl %ecx
	retl

_strlen:
	movl 4(%esp),%eax
	pushl $0
	pushl %eax
	calll _strchr
	addl $8,%esp
	subl 4(%esp),%eax
	retl

compar:
	pushl %ebx
	movl 8(%esp),%ebx
	movl 252(%ebx),%ebx
	movl 12(%esp),%eax
	movl 252(%eax),%eax
	subl %ebx,%eax
	popl %ebx
	retl

/*
 * void *alloc(int size)
 */
alloc:
	pushl %ecx
	movl 8(%esp),%ecx
	addl $(0x1000 - 1),%ecx
	andl $~(0x1000 - 1),%ecx
	xorl %eax,%eax
	pushl %eax
	pushl %eax		// offset
	pushl $~0		// fd
	pushl $0x1000		// flags = MAP_ANON
	pushl $3		// prot = PROT_READ | PROT_WRITE
	pushl %ecx		// len
	pushl %eax		// addr
	movb $197,%al		// mmap
	pushl %eax
	int $0x80
	addl $32,%esp
	popl %ecx
	retl

/*
 * int atoi(char *s)
 */
_atoi:
	movl 4(%esp),%eax
	pushl %ebx
	pushl %ecx
	pushl %edx
	pushl %edi
	movl %eax,%ecx		// end
	movl %eax,%edx		// beginning
	xorl %eax,%eax
	xorl %ebx,%ebx
	movl $1,%edi
	/* Find the end */
1:
	movb (%ecx),%bl
	subb $'0',%bl
	js 2f
	cmp $10,%bl
	jge 2f
	incl %ecx
	jmp 1b
2:
	decl %ecx
	cmp %edx,%ecx
	jl 3f
	movb (%ecx),%bl
	subb $'0',%bl
	/* XXX choose registers better to avoid this crap */
	pushl %eax
	pushl %edx
	movl %edi,%eax
	mull %ebx
	movl %eax,%ebx
	popl %edx
	popl %eax
	addl %ebx,%eax
	leal 0(%edi,%edi,4),%edi
	addl %edi,%edi
	jmp 2b
3:
	popl %edi
	popl %edx
	popl %ecx
	popl %ebx
	retl

.data
query_string:
	.asciz	"QUERY_STRING"
ok:
	.ascii "HTTP/1.1 200 OK\r\n"
	.ascii "Server: r.cgi\r\n"
	.ascii "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
	.ascii ""
	.ascii "
" .ascii "Description: " .ascii "URL: " .ascii " " .ascii "
" .ascii "" ok_end: submit_str: .ascii "HTTP/1.1 200 OK\r\n" .ascii "Server: r.cgi\r\n" .ascii "Content-Type: text/html; charset=iso-8859-1\r\n\r\n" .ascii "\n" .ascii "" .ascii "" submit_str_end: saved_qs: .long 0 link_start_str: .ascii "

:, , ,

Leave a Reply

*

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Blogroll

A few highly recommended websites...

IDL

Member of The Internet Defense League