Skip to content

Instantly share code, notes, and snippets.

@tallpeak
Last active March 7, 2023 19:11
Show Gist options
  • Save tallpeak/5628c31c33aeb07b797032ed545b764d to your computer and use it in GitHub Desktop.
Save tallpeak/5628c31c33aeb07b797032ed545b764d to your computer and use it in GitHub Desktop.
Character Frequency from stdin -- flat assembler version
format PE64 CONSOLE
entry start
include 'C:\util\fasmw17330\INCLUDE\WIN64a.INC'
section '.data' data readable writeable
;freq dq 256 dup(0) ; why waste 2kb in exe?
;freq equ rbp-8*256 ;stack allocation
define freq rbp-8*256 ;same as equ
header1 db "Top hex digits are the second digit of the character value", 10, "Left-side hex numbers are the first digit of the character value", 10, "numbers in the table are the frequency of each character found in stdin.", 10, 0
header2 db " 0 1 2 3 4 5 6 7 8 9 a b c d e f",13,10,0
header3 db " =======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", "=======", 10, 0
fmt db "%7d", 0
fmt2 db "%02x: ", 0
section '.text' code readable executable
start:
push rbp
mov rbp, rsp
sub rsp, 32+8*256 ; stack allocate the freq table
; Clear the frequency table
cld
lea rsi,[freq]
mov rdi,rsi
mov rcx, 256
xor rax,rax
rep stosq
; Print the header
lea rcx, [header1]
call [printf]
lea rcx, [header2]
call [printf]
lea rcx, [header3]
call [printf]
;_setmode(_fileno(stdin),_O_BINARY)
mov rcx, 0 ; _fileno(stdin) == -11
mov rdx, 0x8000 ; _O_BINARY == 0x8000
call [setmode]
read_loop:
; Read a character from stdin
xor rcx,rcx
xor rax,rax
call [getchar]
cmp eax, -1
je end_read_loop
; Increment the frequency table for the character
movzx rcx, al
inc qword [freq + rcx*8]
jmp read_loop
end_read_loop:
; Print the frequency table
xor rsi,rsi
print_loop:
; Print left header
lea rcx, [fmt2]
mov rdx,rsi
call [printf]
inner_loop:
; Print the frequency for the current character
mov rdx, [freq + rsi*8]
lea rcx, [fmt]
call [printf]
inc rsi
mov rcx,rsi
and rcx,15
jnz inner_loop
; Print a newline
mov rcx, 0x0d
call [putchar]
mov rcx, 0x0a
call [putchar]
cmp rsi, 256
jb print_loop
; Return 0
xor rax, rax
add rsp, 32+8*256
pop rbp
invoke ExitProcess,0
section '.idata' import data readable
library msvcrt, 'msvcrt.dll',\
kernel32, 'kernel32.dll'
import msvcrt, \
printf, 'printf',\
getchar, 'getchar',\
putchar, 'putchar',\
setmode, '_setmode'
import kernel32, \
ExitProcess, 'ExitProcess', \
SetLastError, 'SetLastError'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment