Баш - как посчитать количество инструкций? - PullRequest
3 голосов
/ 29 ноября 2010

У меня есть несколько файлов сборки * .s.Я хотел бы посчитать, сколько инструкций они содержат.Например, чтобы подсчитать все mul инструкции, которые я делаю:

cat *.s | grep -P '\t'"mul" | wc -l

, что дает мне составной номер всех команд mul.как:

mul: 893
add: 12054
sub: 2356
...

Проблема в том, что нет таблицы инструкций, поддерживаемых целевой платформой.У каждой целевой платформы свой набор инструкций.Поддерживаемые инструкции должны быть выведены из существующих файлов сборки.Могу ли я сделать это в Bash только без Perl / Python Foundry?

Ответы [ 5 ]

5 голосов
/ 29 ноября 2010

При условии, что все ваши инструкции имеют отступ от другого кода с использованием пробела (вкладка в порядке), тогда этот awk 1-строчный будет работать:

awk '/^[[:space:]]+/{a[$1]++}END{for(op in a){print op,a[op]}}' /path/to/*.s

Input

$ cat asm.s
section .text
global _start, write
write:
  mov al,1 ;write syscall
  syscall
  ret
_start:
  mov rax,0x0a68732f6e69622f
  push rax
  xor rax,rax
  mov rsi,rsp
  mov rdi,1
  mov rdx,8
  call write

exit: ; just exit not a function
  xor rax,rax
  mov rax,60
  syscall

выход

$ awk '/^[[:space:]]+/{a[$1]++}END{for(op in a){print op,a[op]}}' ./*.s
push 1
xor 2
ret 1
mov 6
syscall 2
call 1
5 голосов
/ 29 ноября 2010

Вы можете получить их все так:

grep -hP '^[ \t]+[a-z]*' *.s | sed 's/^[ \t]\+\([a-z]*\).*/\1/' | sort | uniq -c

Редактировать: я изменил это для работы с примером, предоставленным SiegeX.

Выход:

1 call
6 mov
1 push
1 ret
2 syscall
2 xor
1 голос
/ 30 ноября 2010

Bash 4 без каких-либо внешних утилит:

declare -A c;while IFS=$'\n' read -r t;do [[ ! $t =~ ^[[:space:]] ]] && continue;w=($t);((c[${w[0]}]++));done<asm.s;for op in ${!c[@]};do echo $op ${c[$op]};done

Чтобы сделать несколько файлов, оберните цикл while в цикл for f in *.s с done while, например: done < "$f" или doвремя done выглядит следующим образом: done < <(cat *.s) вместо for f.

Немного короче для подсчета первого слова в каждой строке без учета отступа:

declare -A c;while read -ra t;do [[ $t ]]&&((c[${t[0]}]++));done<asm.s;for op in ${!c[@]};do echo $op ${c[$op]};done

Тем не менее,это длиннее, чем другие ответы.

0 голосов
/ 30 ноября 2010

grep -Eo '\ w +' /source.file | uniq -c

0 голосов
/ 29 ноября 2010

Просто, черт возьми, ответ от SiegeX на awk на Perl

perl -n '/^\s+(\w+)/&&$a{$1}++;END{print map{"$_ $a{$_}\n"}keys%a}' ./*.s

Потому что «все, что вы можете сделать, я могу сделать так, чтобы это больше походило на шум линий» (-:

...