commit: f3bb29739dce70badebf121c322c1374292c4c7a
parent e7b0fe83ce6f56f0c4838c7ed3c8d5d091170666
Author: LinuxMercedes <LinuxMercedes@gmail.com>
Date: Tue, 11 Dec 2018 14:47:56 -0600
Merge pull request #465 from PoroCYon/eeeeeeeeeeeeeeeeeeeeeeee
Add/improve some assembly versions
Diffstat:
M | e.asm | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
A | e.linux.arm.S | 36 | ++++++++++++++++++++++++++++++++++++ |
A | e.mbr.asm | 31 | +++++++++++++++++++++++++++++++ |
3 files changed, 118 insertions(+), 12 deletions(-)
diff --git a/e.asm b/e.asm
@@ -1,17 +1,56 @@
+; compile with:
+; $ [ny]asm -felf(32|64) -oe.o e.asm
+; $ (gcc|clang) -m(32|64) -oe e.o -nostdlib -nostartfiles
+
section .text
-global _start
+global _start
+
+%if __BITS__ == 32
+%define r(n) e%+n
+%define SYS_write 4
+%define rarg0 ebx
+%define rarg1 ecx
+%define rarg2 edx
+%define syscall int 0x80
+%else
+%define r(n) r%+n
+%define SYS_write 1
+%define rarg0 rdi
+%define rarg1 rsi
+%define rarg2 rdx
+default rel
+%endif
+
+; size of a Linux pipe buffer
+%define PIPE_SIZE 0x10000
+%define STDOUT_FILENO 1
+
+; Instead of simply storing a char in .rodata and write(2)-ing it
+; over and over again, we first fill a buffer full of e's, and *then*
+; write the entire buffer. This is much faster than the first option,
+; because we only need to issue a syscall once every 65536 bytes. (Remember
+; that doing a syscall requires the kernel to handle an interrupt etc etc etc.)
-_start:
+_start:
+ ; allocate space for the message
+ mov r(cx), PIPE_SIZE
+ mov r(bx), r(cx) ; we'll need it later
+ sub r(sp), r(cx)
- mov rax, 1
- mov rdi, 1
- mov rsi, msg
- mov rdx, len
- loop:
- syscall
- jmp loop
+ ; quick memset(3)
+ mov al, 'e'
+ mov r(di), r(sp)
+ rep stosb
-section .data
+ ; push+pop is actually a smaller encoding than mov for ints that fit within 8 bit
+ push STDOUT_FILENO
+ pop rarg0
+ mov rarg1, r(sp)
+ mov rarg2, r(bx)
-msg: db "e"
-len: equ $ - msg
+.loop:
+ ; set this within the loop because the syscall's exit code is placed in r(ax)
+ push SYS_write
+ pop r(ax)
+ syscall
+ jmp short .loop
diff --git a/e.linux.arm.S b/e.linux.arm.S
@@ -0,0 +1,36 @@
+#define SYS_write 4
+#define STDOUT 1
+#define PIPE_SIZE 0x10000
+
+.arm
+.align 4
+
+.section .text, "ax", %progbits
+
+type _start, %function
+globl _start
+_start:
+ mov r1, #PIPE_SIZE
+
+ ldr r3, =('e'|('e'<<8)|('e'<<16)|('e'<<24))
+ mov r4, r3
+ mov r5, r3
+ mov r6, r3
+
+.Lloop:
+ push {r3-r6}
+ sub r1, #(4*4)
+ cmp r1, #0
+ bgt .Lloop
+
+ mov r7, #SYS_write
+ mov r1, sp
+ mov r2, #PIPE_SIZE
+
+.Lcall:
+ mov r0, #STDIN
+ swi #0
+ b .Lcall
+
+.align 4
+.pool
diff --git a/e.mbr.asm b/e.mbr.asm
@@ -0,0 +1,31 @@
+bits 16
+org 0x7C00
+
+_start:
+ ; enable cursor
+ xor cx, cx
+ mov ch, 00100000b
+ mov ah, 1
+ int 0x10
+
+ ; move cursor to top
+ xor dx, dx
+ xor bx, bx
+ inc ah
+ int 0x10
+
+ ; print 1 char
+ mov ax, 'e'|(0x0E<<8)
+ .loop:
+ int 0x10
+ jmp short .loop
+
+END:
+ times 0x200-2-(END-_start) db 'e'
+ db 0x55,0xAA
+
+stack:
+
+%if END-_org > 0x200-2
+%error "Not enough space!"
+%endif