Last active
October 15, 2017 07:00
-
-
Save netman69/189a87d23ad3a1c479e01f758aa7e4a4 to your computer and use it in GitHub Desktop.
32bit matsum with direct syscalls
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; | |
; 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