Skip to content

Instantly share code, notes, and snippets.

@netman69
Last active October 15, 2017 07:00
Show Gist options
  • Save netman69/189a87d23ad3a1c479e01f758aa7e4a4 to your computer and use it in GitHub Desktop.
Save netman69/189a87d23ad3a1c479e01f758aa7e4a4 to your computer and use it in GitHub Desktop.
32bit matsum with direct syscalls
;
; Command line CRC32C calculation utility for Linux using SSE4.2 CRC32C instruction.
;
; TODO
; - Probably fails quite miserably if cpu does not have crc32c instruction.
; - Fails miserably if attempting to hash a folder.
;
%define BUFSIZE 4096 ; Must be not TOO tiny cause output string is also written there.
bits 32
section .text
%define sys_exit 0x01
%define sys_read 0x03
%define sys_write 0x04
%define sys_open 0x05
%define sys_close 0x06
%define stdout 1
%define stderr 2
align 16
strlen: ; ECX should point to string, EDX will hold result.
push eax
push esi
mov esi, ecx
cld
.loop:
lodsb
test al, al
jnz .loop
mov edx, esi
sub edx, ecx
pop esi
pop eax
ret
align 16
print: ; Print text, pointer in ECX.
call strlen
mov ebx, stdout
mov eax, sys_write
int 0x80
ret
align 16
eprint: ; Print text to STDERR, pointer in ECX.
call strlen
mov ebx, stderr
mov eax, sys_write
int 0x80
ret
align 16
eexit: ; Quit program in error.
pop eax ; Lose our own adress.
popad
pop ebp
mov ebx, 1
mov eax, sys_exit
int 0x80
ret
%macro fail 1+
mov ecx, %%str
call eprint
int 0x80
call eexit
%%str: db %1, 10, 0
%endmacro
global _start
align 16
_start:
; Set up stack frame.
push ebp
mov ebp, esp
pushad
; Check if we got the right amount of arguments (1).
cmp dword [ebp+4], 2 ; argc - 2
je .argc_ok
; If we reach here try to explain how the user should do instead.
mov ecx, .err_args1
call eprint
mov ecx, [ebp+8] ; argv[0]
call eprint
mov ecx, .err_args2
call eprint
call eexit
.err_args1: db "usage: ", 0
.err_args2: db " <filename>", 10, 0
.argc_ok:
; Try to open the specified file.
xor edx, edx ; mode
mov ecx, 0o00100000 ; flags (O_LARGEFILE)
mov eax, [ebp+12] ; argv[1]
mov ebx, eax ; filename
mov eax, sys_open
int 0x80
mov [fd], eax
test eax, eax
jns .open_ok
fail "error: can't open file"
.open_ok: ; TODO trying to CRC a folder will segfault
; EBX will hold the sum here.
mov ebx, 0xFFFFFFFF
align 16
.doblock:
; Read a bit of the file.
push ebx
mov edx, BUFSIZE
mov ecx, buf
mov ebx, [fd]
mov eax, sys_read
int 0x80
pop ebx
; Count the length while we're at it.
add dword [len], eax
adc dword [len+4], 0
; Calculate CRC of that bit.
mov edx, buf
.crc32c: ; EAX = length, EBX = sum, EDX = buf
; Do 4-byte blocks.
mov ecx, eax
shr ecx, 2
test ecx, ecx
jz .end32
align 16
.step32:
crc32 ebx, dword [edx] ; Doesn't seem to matter much wether aligned.
add edx, 4
loop .step32
.end32:
; Finish.
mov ecx, eax
and ecx, 3
test ecx, ecx
jz .end
align 16
.step8:
crc32 ebx, byte [edx]
inc edx
loop .step8
.end:
cmp eax, BUFSIZE
je .doblock
xor ebx, 0xFFFFFFFF
; Close the file.
push ebx
mov ebx, [fd]
mov eax, sys_close
int 0x80
pop ebx
; Convert checksum to ASCII hex form.
mov ecx, 8
mov edi, buf + 7
std
.hexloop:
mov al, bl
and al, 0x0F
cmp al, 9
jng .notletter
add ax, 'A' - '0' - 10
.notletter:
add ax, '0'
stosb
shr ebx, 4
loop .hexloop
; Convert file length to readable form.
cld
mov edi, buf + 8
mov al, ' '
mov ecx, 20
rep stosb
mov al, 10
stosb
xor al, al
stosb
std
sub edi, 3
.divloop:
; Divide high dword by 10.
mov eax, [len+4]
xor edx, edx
mov ebx, 10
div ebx
mov [len+4], eax ; Store result.
; Divide low dword + remainder.
mov eax, [len]
div ebx
mov [len], eax
; Now we have remainder of division by 10.
mov al, dl
add ax, '0'
stosb
; Repeat if necessary.
cmp dword [len+4], 0
jnz .divloop
cmp dword [len], 0
jnz .divloop
; Print it all.
mov ecx, buf
call print
; The end.
popad
pop ebp
xor ebx, ebx
mov eax, sys_exit
int 0x80
ret
section .bss
fd: resd 1
len: resq 1
buf: resb BUFSIZE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment