diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..218c0ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*~ +\#* +.\#* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4d4d98c --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ + + +hello32: + nasm -f elf hello32.s + ld -m elf_i386 -o hello32 hello32.o + +hello64: + nasm -f elf64 hello64.s + ld -o hello64 hello64.o + +clean: + rm -f hello32 hello64 *.o diff --git a/hello32.s b/hello32.s new file mode 100755 index 0000000..afdaee5 --- /dev/null +++ b/hello32.s @@ -0,0 +1,30 @@ + ;; Hello World Program #1 + ;; Compile with: nasm -f elf32 hello.s + ;; Link with: ld -m elf_i386 -o hello hello.o + ;; Run with: ./hello + + ;; sys/syscall.h +%define SYS_write 4 +%define SYS_exit 1 + + ;; unistd.h +%define STDOUT 1 + +section .data + msg db "Hello You Beautiful Human", 0Ah + +section .text + global _start + +_start: + mov edx, 26d ; Length of the message + mov ecx, msg ; Address of the message + mov ebx, STDOUT ; using STDOUT (see definition above) + mov eax, SYS_write ; Using WRITE in 32-bit mode? + int 80h + + mov ebx, 0 + mov eax, SYS_exit + int 80h + + diff --git a/hello64.s b/hello64.s new file mode 100644 index 0000000..95d64b5 --- /dev/null +++ b/hello64.s @@ -0,0 +1,29 @@ + ;; Hello World Program #1 + ;; Compile with: nasm -f elf32 hello.s + ;; Link with: ld -m elf_i386 -o hello hello.o + ;; Run with: ./hello + + ;; sys/syscall.h +%define SYS_write 1 +%define SYS_exit 60 + + ;; unistd.h +%define STDOUT 1 + +section .data + msg db "Hello You Beautiful Human", 0Ah + +section .text + global _start + +_start: + mov rdx, 26d ; Length of the message + mov rsi, msg ; Address of the message + mov rdi, STDOUT ; using STDOUT (see definition above) + mov rax, SYS_write ; Using WRITE in 32-bit mode? + syscall + + mov rdi, 0 + mov rax, SYS_exit + syscall + diff --git a/number.s b/number.s new file mode 100644 index 0000000..d49824f --- /dev/null +++ b/number.s @@ -0,0 +1,48 @@ +;; Pure assembly, library-free Linux threading demo +bits 32 +global _start + +;; sys/syscall.h +%define SYS_write 1 +%define SYS_exit 60 + +;; unistd.h +%define STDOUT 1 + +section .data +hello: db `Goodbye\10` + +section .text +_start: + mov eax, 9234d ; The number we're processing; this is + ; the dividend target for the div operation + xor esi, esi ; fast zero +.loop: + mov edx, 0d ; counter + mov ebx, 10d ; divisor + div ebx + add edx, 48d ; the remainder, plus the ASCII for '0' + ; the quotient is put into eax + push edx ; onto the stack + inc esi ; Increment counter + cmp eax, 0d ; if EAX is zero, we're done. + jz .print + jmp .loop +.print: + cmp esi, 0d ; if counter is zero, we're done. + jz .exit + dec esi ; decrement the counter + pop ecx ; copy the address of the stack pointer to edx + mov edx, 1 ; One byte + mov ebx, STDOUT ; To stdout + int SYS_write ; Do it! + jmp .print + +.exit: + mov esi, hello ; move the contents of the stack pointer into ECX + mov ecx, 6 ; One byte + mov ebx, STDOUT ; To stdout + mov eax, SYS_write ; Do it! + mov edi, 0 ; Success! + mov eax, SYS_exit ; Do it! + syscall diff --git a/something.s b/something.s new file mode 100644 index 0000000..ae516df --- /dev/null +++ b/something.s @@ -0,0 +1,25 @@ +;; Pure assembly, library-free Linux threading demo +bits 32 +global _start + +;; sys/syscall.h +%define SYS_write 1 +%define SYS_exit 60 + +;; unistd.h +%define STDOUT 1 + +section .data +hello: db `Goodbye\n` + +section .text +_start: + mov esi, hello + mov edx, 8d + mov edi, STDOUT + mov eax, SYS_write + syscall + + mov edi, 0 ; Success! + mov eax, SYS_exit ; Do it! + syscall diff --git a/threads-x86_64.s b/threads-x86_64.s new file mode 100644 index 0000000..4d7de83 --- /dev/null +++ b/threads-x86_64.s @@ -0,0 +1,108 @@ +;; Pure assembly, library-free Linux threading demo +bits 64 +global _start + +;; sys/syscall.h +%define SYS_write 1 +%define SYS_mmap 9 +%define SYS_clone 56 +%define SYS_exit 60 + +;; unistd.h +%define STDIN 0 +%define STDOUT 1 +%define STDERR 2 + +;; sched.h +%define CLONE_VM 0x00000100 +%define CLONE_FS 0x00000200 +%define CLONE_FILES 0x00000400 +%define CLONE_SIGHAND 0x00000800 +%define CLONE_PARENT 0x00008000 +%define CLONE_THREAD 0x00010000 +%define CLONE_IO 0x80000000 + +;; sys/mman.h +%define MAP_GROWSDOWN 0x0100 +%define MAP_ANONYMOUS 0x0020 +%define MAP_PRIVATE 0x0002 +%define PROT_READ 0x1 +%define PROT_WRITE 0x2 +%define PROT_EXEC 0x4 + +%define THREAD_FLAGS \ + CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_PARENT|CLONE_THREAD|CLONE_IO + +%define STACK_SIZE (4096 * 1024) + +%define MAX_LINES 1000000 ; number of output lines before exiting + +section .data +count: dq MAX_LINES + +section .text +_start: + ; Spawn a few threads + mov rdi, threadfn + call thread_create + mov rdi, threadfn + call thread_create + +.loop: call check_count + mov rdi, .hello + call puts + mov rdi, 0 + jmp .loop + +.hello: db `Hello from \e[93;1mmain\e[0m!\n\0` + +;; void threadfn(void) +threadfn: + call check_count + mov rdi, .hello + call puts + jmp threadfn +.hello: db `Hello from \e[91;1mthread\e[0m!\n\0` + +;; void check_count(void) -- may not return +check_count: + mov rax, -1 + lock xadd [count], rax + jl .exit + ret +.exit mov rdi, 0 + mov rax, SYS_exit + syscall + +;; void puts(char *) +puts: + mov rsi, rdi + mov rdx, -1 +.count: inc rdx + cmp byte [rsi + rdx], 0 + jne .count + mov rdi, STDOUT + mov rax, SYS_write + syscall + ret + +;; long thread_create(void (*)(void)) +thread_create: + push rdi + call stack_create + lea rsi, [rax + STACK_SIZE - 8] + pop qword [rsi] + mov rdi, THREAD_FLAGS + mov rax, SYS_clone + syscall + ret + +;; void *stack_create(void) +stack_create: + mov rdi, 0 + mov rsi, STACK_SIZE + mov rdx, PROT_WRITE | PROT_READ + mov r10, MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN + mov rax, SYS_mmap + syscall + ret