Files

225 lines
3.3 KiB
NASM

; -*- tab-width: 8 -*-
; MD5 checksum utility for x86_64 Linux, assembly version
; To build: nasm -f bin -O9 prog.x86_64.asm -o prog
%define @pie 0
BITS 64
%if @pie
ORG 0
%else
ORG 0x400000
%endif
%define @sys_read 0
%define @sys_write 1
%define @sys_exit 60
section .text
_code_seg:
_elf: db 0x7f,'ELF',2,1,1,0 ; e_ident
dq 0
dw 2+@pie ; e_type
dw 62 ; e_machine
dd 1 ; e_version
dq _start ; e_entry
dq .ph-_elf ; e_phoff
dq 0 ; e_shoff
dd 0 ; e_flags
dw 0x40 ; e_ehsize
dw 0x38, 1 ; e_phentsize, e_phnum
dw 0x40, 0 ; e_shentsize, e_shnum
dw 0 ; e_shstrndx
.ph: dd 1, 5 ; p_type, p_flags
dq 0 ; p_offset
dq _code_seg ; p_vaddr
dq _code_seg ; p_paddr
dq _code_end-_code_seg ; p_filesz
dq _code_end-_code_seg ; p_memsz
dq 0x1000 ; p_align
_start:
mov rax, ~0xefcdab8967452301
push rax
not rax
push rax
sub rsp, 64+8
xor r12, r12
; xor edx, edx
cdq
.2: mov rdi, rsp
xor eax, eax
lea ecx, [rax+8]
rep stosq
test edx, edx
lea edx, [rax+64]
jne .2a
xchg edi, eax ; 0 (stdin)
mov rsi, rsp
%if @sys_read != 0 || @sys_write != 1
lea ebx, [rdi+@sys_read]
%endif
call _io
mov byte [rsi], 0x80
sub esi, esp
lea r12, [r12+rsi*8]
.2a: cmp edx, 8
jb .2b
neg edx
mov [rsp+56], r12
.2b: push rdx
xor ebx, ebx
mov r14, 0x8a51407da834 << 15 ; cos(1) * 2^48
mov r15, 0xd76aa4784867 << 15 ; sin(1) * 2^48
mov r8, r14
mov r9, r15
mov rdx, rsp
mov ecx, [rdx+0x50]
mov edi, [rdx+0x54]
mov esi, [rdx+0x58]
mov ebp, [rdx+0x5c]
.1:
mov rax, r9
cqo
shr rax, 31
xor eax, edx
add ecx, eax
; r9' = r9 * r14 + r8 * r15
; r8' = r8 * r14 - r9 * r15
mov rax, r9
imul r15
mov r11, rdx
mov rax, r8
imul r14
sub rdx, r11
lea rax, [rdx+rdx]
xchg rax, r8
imul r15
lea rax, [rdx+rdx]
xchg rax, r9
imul r14
lea r9, [rdx*2+r9]
; r10d, edi, esi, ebp
%define PACK(a,b,c,d,e,f) (d<<15|c<<10|b<<5|a)<<4|e<<24|f
mov edx, ebx
shr edx, 5
mov eax, ebp
jne .1b
jc .1a
; 0: ((b^c)&a)^c
mov edx, PACK(7,12,17,22,1,0)
xor eax, esi
and eax, edi
xor eax, ebp
jmp .1e
.1a: ; 1: ((a^b)&c)^b
mov edx, PACK(5, 9,14,20,5,1)
mov eax, edi
xor eax, esi
and eax, ebp
jmp .1d
.1b: jc .1c
; 2: a^b^c
mov edx, PACK(4,11,16,23,3,5)
xor eax, edi
jmp .1d
.1c: ; 3: (~c|a)^b
mov edx, PACK(6,10,15,21,7,0)
not eax
or eax, edi
.1d: xor eax, esi
.1e: add eax, ecx
mov ecx, edx
shr ecx, 24
imul ecx, ebx
add ecx, edx
and ecx, 15
add eax, [rsp+8+rcx*4]
mov ecx, ebx
and ecx, 3
lea ecx, [rcx+rcx*4+4]
shr edx, cl
mov ecx, edx
rol eax, cl
mov ecx, ebp ; a = d
mov ebp, esi ; d = c
mov esi, edi ; c = b
add edi, eax ; b += x
inc ebx
cmp ebx, 64
jne .1
mov rdx, rsp
add [rdx+0x50], ecx
add [rdx+0x54], edi
add [rdx+0x58], esi
add [rdx+0x5c], ebp
pop rdx
test edx, edx
jge .2
xor edx, edx
mov rdi, rsp
.3: mov eax, edx
shr eax, 1
mov al, [rsp+0x40+8+rax]
jc .3a
shr al, 4
.3a: and al, 15
cmp al, 10
jb .3b
add al, 'a'-'0'-10
.3b: add al, '0'
stosb
inc edx
cmp edx, 32
jne .3
mov al, 10
stosb
inc edx
mov rsi, rsp
lea edi, [rdx-32] ; 1 (stdout)
%if @sys_read != 0 || @sys_write != 1
lea ebx, [rdi+@sys_write-1]
%endif
call _io
xor edi, edi ; exit code
lea eax, [rdi+@sys_exit]
syscall
_io:
%if @sys_read != 0 || @sys_write != 1
mov eax, ebx
%else
mov eax, edi
%endif
syscall
test eax, eax
jle .1
add rsi, rax
sub edx, eax
ja _io
; xor edx, edx
cdq
.1: ret
_code_end: