nthnjhnsn
/
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
Public
forked from eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
-
Notifications
You must be signed in to change notification settings - Fork 0
/
e.asm
56 lines (48 loc) · 1.42 KB
/
e.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
%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:
; 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)
; quick memset(3)
mov al, 'e'
mov r(di), r(sp)
rep stosb
; 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)
.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